Thursday, October 06, 2016

Ruby Conf 2012 - Boundaries by Gary Bernhardt

this is the only one word talk titled this conference which I'm very proud of
the next shortest is three words thank you
this is some stuff in this talk is going to be very familiar to anyone who comes
from certain functional programming backgrounds but this is a story of me
approaching some ideas that they have from a very different direction from a
very different history so i am very Bernhardt's I would look like this on
the Internet where sometimes I get mad and my bluetooth is not working very
well might have to forgo it i own a company called destroy all software that
produces screencasts on various advanced software development topics and to start
us off in this talk we're going to start with test doubles there are a couple
talks about test doubles mocking and stopping at this conference this is not
a talk about test doubles but they are going to be part of my motivation just
to make sure everyone's on the same page let's go through a quick example of what
an isolated unit tests might look like I have a sleeper class this is in some
kind of recurring billing situation and if i have a user who has subscribed but
has not paid in the last month I want to tell him that something's wrong and and
disable his access so you know when a subscription when a subscription is
we will make a user bobby is going to be a stub he's an active user and he last
paid two months ago we will have an array of users that's just Bob for
convenience and before every test we're going to stub out the user . all method
to return that array of Bob so this is one of the ways in which were isolating
ourselves from third parties from other classes like user we want to email the
user when the subscription is expired so we will invoke the sweeper and we expect
it to call user mailer . building problem to send an email to this user
telling him things are bad so this is an isolated unit test its isolated because
removes its dependencies like user and like the user mailer hopefully my phone
is back now
awesome ok the implementation of this is very simple we will pull out all the
users from the database we will select only the ones who are active users but
have not paid recently enough and then for each of those we will send the email
right so very straightforward stuff what we have here is a three-class system
these three classes integrate in production but in test we're moving to
the dependencies replacing them with Stubbs and mocks giving us this as our
testing world so everything is nice and isolated there are several good reasons
to do this several very big benefits that come out of it but there's also one
really terrible thing that happens when you do this so let's go through those
this allows you to do real test driven design looking at your test seeing that
you have mocked six things and two of them are mach3 method calls deep this
tells you that your design is not so good for this class so it gives you a
form of feedback that you can't get without isolated tests at least I don't
know how to it let allows you to outside in TD where you actually build higher
level pieces before the low-level pieces exist so we could TD the sweeper using
the user using the user mailer before those classes exist because we're just
stopping them out anyway then we want to write the user class for real we can
look at what we stopped and that tells us the interfaces it needs and finally
this gives you very fast test this is one of the main things in the whole fast
rails tests me more
I don't wanna call it a movement but people getting excited about fast tests
in the rails world and we're talking about the difference between a 200
millisecond time from hitting return to seeing the prompt back versus a
30-second time to run a very small test it's a very big difference when you're
when you're really isolating so these are all very good things that you want
but they are balanced out by a very bad thing and that bad thing is that in test
you're running against the maca stub in production you're running against real
classes and if you don't stop the boundary correctly your test will pass
in your production system will be wrong and this is this is such a big problem
that for most people I think it overshadows
it's all those benefits even if you explain them to them they're going to
look at this problem and say it's not worth it
now there have been attempts to fix this attend various various approaches to try
to solve this problem in one way or another one of which is to solve it with
more testing contract and collaboration tests this is an idea sort of most
closely associated with jb rains berger who is one of the people who was most
influential on my understanding of isolated unit testing
I've not actually done this and something about it doesn't resonate well
with me but it is one attempt to fix this
there's also the tools approach r-spec fire is a tool and Ruby that that tries
to solve this problem if you mock a class in art with our spec fire it will
make sure that you only mock methods it actually exists so and make sure that
you don't cause these boundary problems or at least you know cause simple
boundary problems and finally you can solve this with static typing like so
many things in life
it comes with all the same costs you pay to solve anything with a powerful static
type system but if you think about your mocs as being subclasses of the real
class that just remove all the actual implementations that gives you an idea
of how static typing can solve this boundary problem all of these only solve
simple Canadians mismatches between objects they solve things like I called
the method with the wrong name like pass the wrong number of arguments they don't
solve deeper things like my two algorithms that need to cooperate don't
actually cooperate correctly the way that you can solve that and the the most
common way people try to fix this problem is by just not doing isolated
unit testing by just integrating right
the problem with solving the isolation problem with integration is that
integration test service scam
I can try correct take credit for the sentence is once again jb rains burger
there's a talk called integration tester scam which you should all watch it's a
really good talk that really lays out the argument for why integration testing
doesn't work on a long enough time scale and he nowadays uses the terminology
integrated test
I mean any tests integrating multiple pieces i'll give you the really quick
and dirty argument for why integration tests don't work the number of paths
your program goes like two to the N where n is the number of branches or
conditionals and that includes try except that includes short-circuiting
boolean expression that includes a loop
every time a branch is happening if you have any of those you have to the N
paths and if you're trying to test the whole thing you have a space of 2d and
to decide to choose from if you have 500 conditions in your program this is a
number with about a hundred fifty digits in it it's a very large space it's very
difficult to effectively choose which wich pads matter because they're
effectively uncountable to you the other problem is that sweet runtime in an
integration sweet is super linear whenever you add a unit test or whatever
kind of test your writing
you're also adding a little bit of code so your number of test goes up by one
and you make the system a little bit bigger which means all your existing
integration test get a little bit slower so every time you had a test
there are two sources of slowness one of which is linear in one of which is
something else i'm not sure of but together it's definitely super linear
runtime and anyone who has a three-hour rails test suite will be able to tell
you that this is in fact the case and they will probably not like their lives
very much either so that's all background this is this is how i came to
the ideas of this the the time going to talk about for the rest of this talk
this was this has been a large focus in my software development career for the
last 55 years is isolated testing and figuring out how to do it well so now
let's shift gears entirely talk about values values meaning the the pieces of
data inside of a program if you want to test the plus method and let's just
think about plus on machine integers and for whatever reason you decide you want
to test it in isolation so you don't want any other dependencies involved in
the testing what you have to do
to isolate plus nothing right it isolates for free plus doesn't have any
dependencies there's nothing to mock out there's nothing to stub it's totally
local and why is that the case it's not just because plus whoops it's not just
because plus is simple it's it's tempting to say 0 plus simple so of
course license for free that is not what's happening
it has two properties that are necessary to be naturally isolated with no stubs
or marks the first is that it takes values arguments and returns new values
and it doesn't mutate those values it just gives you a new value right
it takes an integer integer and it gives you an integer the second property is
that it doesn't have any dependencies there's nothing to mock it doesn't it
doesn't need anything else it's a local computation that just produces a new
value so how could we apply that to more complex code that we work with all the
time stuff like the sweeper let's go through this and just impose both of
these constraints and see what happens
starting with the Bob stub we can't use a stub because we're not faking out any
boundaries so let's replace that with a user object but not like an active
record object but like just a struct some kind of a piece of data even a hash
i wouldn't use a hash but you can just use a hash we can't do the the user all
stuff because we're not allowed to so we'll just delete that and then the
actual body of the test instead of doing a mock expectation we can just call the
method and get back the array of users who are expired now this does less than
the original code we're going to get to that later the the implementation
changes we basically lose the second half we now have a method that goes
through all the users and returns only the expired ones this difference is huge
the difference between the original code is huge the the nature of the
communication between the components has changed instead of having synchronous
method calls as the boundaries between things we now have values as boundaries
the value returned or taken by the method is the boundary between it and
another object now just as a quick digression when I talk about values
I often mean things like this maybe a class that is a structure has two fields
title and body and it has a slug computer from the title but behaviorally
this is equivalent to a class that has a title body and slug and computes the
slug creation time they're basically the same thing right
the only way to tell the difference on the outside is timing properties on the
method calls so I'm going to use these two ideas interchangeably but really
they're basically the same so we've seen isolated testing as a bit of background
the idea of converting the code in the system to communicate via values at the
boundaries instead of via message sends or method calls its boundaries and now i
want to look at how this fits into the three dominant programming paradigms
putting aside logic programming but how does this relate to procedural oh and
functional programming heres a small piece of procedural code we want to feed
some horses so for each of the walruses we shovel some food into its stomach we
shovel some cheese into walruses stomach
there are two properties of this code that make it very obvious that its
procedural the first is the each whenever you see each and Ruby there's
something destructive going on each each with it with a non-destructive body is a
no op so there's something destructive happening and we know the structure of
the walrus and the structure of its stomach we know it has a stomach we know
the stomach can have things shoveled into it we have knowledge of the
internals contrast this with the 00 solution where you still have in each
it's still destructive in most locoed but now we tell the walls to eat
something he knows how to eat instead of us knowing about his stomach and then
the eat method will shovel things into the stomach same code as before just
encapsulated and my bluetooth is dying again so we have two two paradigms here
both of them involve mutation one of them separate state and code that's
procedural one of them combined them into units called objects if we add
functional to this instead of doing in each we do a map and we're going to take
all the walruses and produce new Wallace's that is slightly different so
for each of them were going to call it on the walls and some food some cheese
and i'm going to use a hash for the walrus an array for the stomach and
strings for the food so in the heat functions
kind of weird but we build a new stomach that's the old stomach plus the new food
and we build we build a new all risk that's the old walrus with the new
stomach you can see why o.o models real world things a little better than
functional programming does
ok so that's that's functional nothing is being mutated and so we have no
mutation but data encoder separate they are not combined into a single things if
you look at this table obviously have left a row there's one more road to go
but even just looking at the variables we have two variables doesn't mutate or
not doesn't bind data and code together or not they clearly very independently
which means we have four possibilities so what is the fourth possibility it's
not logic programming by the way here's what the four spot fourth possibility
looks like we map like in functional programming so we're producing new
walruses but we're telling The Walrus to eat something and that's not a
destructive eat instead the eat method construct a new walrus it is the old
Wallace with a new stomach that contains the new food so it combines the
immutability of the functional code but it combines the merging of data and code
together like Hello does and that is the fourth entry and I call it lovingly
photo because it's not real oh now there's a problem with programming this
way and that problem is that you lose the ability to do anything destructive
to talk to network to talk to disk to do any kind of i/o you lose the ability to
maintain state overtime so 22 reintroduced the idea of state we have
to add imperative programming back into this sort of photo style of programming
we have to figure out how to compose the user database the expired users class
and the mailer together even though the expired users classes functional in
nature so we have our fun are expired users it returns an array of users who
we need to notify and what we need to do is reintroduce the imperative layer
around an imperative shell that surrounds the functional core it talks
the database it uses expired users to filter those users and then it emails
each of the ones that comes out
so the imperative shell is a layer that surrounds the functional core the
functional core is the bulk of the application it has all the intelligence
and the imperative shell is sort of a glue layer between the functional pieces
of the system and the nasty external world of disks and networks and other
things that fail in our slow if we if we look at what's actually happening in
these two things it's not an arbitrary distinction even though all i did was
cut the original method in half this division runs very deep if you look at
what these things do the expired users class makes all the decisions and the
sweeper class has all the dependencies so if we look at the way that relates to
testing the functional core is heavy on paths have your decisions light on
dependencies which is exactly what unit testing is good at especially isolated
unit testing when you take away the need to step out the dependencies you can
just focus on the logic and test become very simple and exactly the same thing
is true for the shell lots of dependencies few paths is exactly what
an integration test is good at it because it make sure all the boundaries
are lining up all the pieces are communicating correctly but you don't
have a lot of test cases which means you don't end up with a 30 minute or
three-hour test suite just to get a sense of what that integration tests
might look like since we already saw the unit tests maybe I create to users in
the database actually create them in an actual database i invoke the sweeper I
pull out all the males that were delivered by action mailer and I make
sure that only Alice was mailed she's the only one who's expired here she paid
two months ago Bob paid yesterday but i only have to write one of these whereas
i'm going to have to write a bunch of the isolated test on the functional core
so now we have a a solution to the isolation problem in foremost coding
system because we can build it all as functional pieces in this sort of 400
style where there are still objects but they're not mutating and just taking
values in and out and we have a way to reintroduce the imperative part around
it so we can actually talk to the outside world and it turns out that this
leads to all kinds of amazing benefits not just the testing benefit
just the fact that functional code is easier to reason about overtime but it
even makes certain types of concurrency much easier if we think about the actor
model concurrency which is the one that I have the most faith in as something
sort of approaching a general-purpose concurrency style or currency
programming method let me quickly explain it to you just in case
everyone is not familiar i'm going to do it with just threads and Q's so we have
a queue and this is going to be the communication mechanism between two
processes it is the inbox of process to process was going to send to it for
process 1 i'm just gonna fork off the thread that is going to infinitely loop
reading from standard and pushing into the queue process to is going to
infinitely loop reading from the queue and writing the standardout so this is
an echo program that's communicating through a queue where the queue is the
inbox for process to if I just run this at the shell and start typing things
into it it's just going to print out whatever i sent in this is the the
simplest way I know to explain the actor model you have independent processes
each of them has an inbox it is only readable by that process and they
communicate by sending messages to each other into each other's inboxes the
reason the way that this relates back to functional core imperative shell 2400 to
the idea of having lots of values is that every value in your system is a
potential message a possible message between two processes every value that
is struct like and can be easily see realized can also be easily sent over
the wire and this is a special case of the value is the boundary between the
components so if we rewrite our sweeper in a slightly different way so we have a
sweep method it calls expired users on user also pulled everything out of the
data out of the database finds only the expired ones and then for each of those
emails this is the imperative shell that you're looking at right now the
functional core is the expired users class it's going to do what it did
before already expired users method excuse me which is going to filter out
expired users and then we have this very trivial notified building problem thing
that just delegate to the mailer let's translate this into the actor model for
the first one I'm going to make an actor that pulls everything out of the
database and just send them one by one into the expired users
actor and then dies if I didn't dude I then this would loop infinitely the
expired users actor is just going to pop a user off of its inbox it's going to
decide whether that users late and if it is late is going to forward that user
onto the mailer process and the mailer process just going to invoke the mailer
so the imperative shell is sort of a bigger process it takes a little while
to run it fires off all these messages to the smaller processes and what we've
just done is converted a program that could only use one core into a program
that can use three cores not on MRI but on other pm's we'vewe've paralyzed this
by doing very little work because we have the values available to send over
the wire
oh i forgot to actually translate that there's the new version it's the same
thing as the old basically values in your system of Ford shifting process
boundaries but really in general values in your system afford shifting
boundaries between anything between class arrangement between subsystem
arrangement between the way they're building a program whether it's cereal
car or parallel so this has programming is in the style has surprisingly deep
effects on the things you can do in the way that you can do them that was a lot
of stuff so now i'm going to try to reset it in like three minutes to to
make it all together in the style you design your program as a core of
independent functional pieces that take values and return values the imperative
shell orchestrates the relationships between those interfaces them to the
network the disc other nasty systems like that and maintain state for example
i wrote a twitter client in the style sort of its terminal program its
interactive like them would be so you hit Jay to go down to the next tweet the
imperative shell sees the j calls into the functional core to generate a new
cursor position the new cursor is generated and returned and the
imperative shell updates the instance variable holding the cursor to be the
new cursor the functional core built the new cursor and it was a purely
functional operation the imperative she'll just updates references to these
new objects as are constructed
what you get from this is easy testing especially isolated you also get easy
integration testing and the distinction between which one happens where is a lot
more obvious than it is if you just start throwing things against the wall
and try to figure out what gets tested how later you get fast tests you don't
have to do any weird stuff to get fast tests are just inherently fast because
they're functional and working on small pieces of code you have no call boundary
risks you don't have to start over Mach you have easier concurrency at least in
the actor model and you have more fluid transition between concurrent and cereal
computation and that's all just a special case of having higher code
mobility in general moving code between components moving code between processes
so that is the end of the actual talk once again i'm gary bernhardt and run
historial software which produces screencasts and if you are a subscriber
or want to become one
it is not free but there is a screencast on tutorial software called functional
core imperative shell which is the first time i ever talked about this in public
and the one that's coming out two weeks from now is also about this topic
expanded look a little more and in that screencast I give a much larger example
that I can't really give here but I show you the twitter client and how its
arranged and how how the the different parts of the system are segregated into
in this way
so with that thank you guys very much for listening to me for half an hour
that actually went way faster than I expected so I would be happy to to take
comments or questions or yeah
do you think there's any
useful distinctions besides the functional bit between like a port and
adapters architecture right that's a wonderful question the question is about
port the relationship to ports and adapters writer or hexagonal
architecture or are these kinds of things
yeah so I if you're building a large system is going to be thirty thousand
lines of code you don't want to have one functional core and one imperative shell
if you a school program about doing this they will tell you that it just becomes
a nightmare i think that the the ideal large system is actually many smaller
systems built out of this in a sort of way you you have the functional pieces
you wrap them in a layer of scar tissue to interface them to the nasty outside
world and then you build a bunch of those that communicate in destructive
ways is it does that answer the question
sure there's no adapter in that explanation but it's sort of you
the doctors are the first yeah exactly that's true I guess you had to some
extent the the imperative shell is just a an adapter fair observation over the
the question is how if I had how I find found success in in using actors with
Ruby the answer is no I have so this this twitter client that I that I wrote
to as I was figuring this out does use the actor model but it's just threads
and Q's I just built a little after $TIME libraries like 35 lines of code a
simple actor library is easy a more complex one
I see diminishing returns if your vm isn't built for it
you can't spawn half-million processes and Ruby your machine just gonna go up
to explode into smoke so user lang
let's get additional
so the question is how suited with rails happy to this style development the
answer once again is no uh-huh
the it's not going to work very well you could I mean it depends on how large a
rails app is the thing about a rails app is if your rails has a hundred thousand
lines you don't have a rails app you have ninety-five thousand lines of your
application and you have five thousand lines of rails glue code and probably
what you've done is dumped those 95,000 lines into models controllers and
helpers and failed to actually design your system if you have designed a
system and treated rails as a small component of it that you want to mostly
protect yourself from then you might be able to do this but to be honest i've
i've never even thought hard about how you would do that I guarantee it's
possible but but you're not going to transition your large rails app into
this easily by like a lot
software and what
really is a dramatic overhaul you can you I if it with with the imperative
shell wrapped around the functional core you can do whatever you want out there
right so you can use I mean like my Twitter my Twitter client uses all tons
of general not tons it uses like six or eight gems
normal jobs that are just you know work like anything else in there there
imperative in nature as 00 programs and Ruby programs tend to be and i just put
them out in the scar tissue layer and I let that be as big as it needs to be to
reasonably allow me to use it and then in the in the functional core it doesn't
have to see any of that stuff
it is this is exactly this is the difference between just thinking about
that sort of photo style programming the functional Oh style and then actually
adding the imperative shell the imperative shell is what allows you to
build real software that actually does work in this way
yeah so when you give the functional sample
in sort of a truth-functional example
right return data
sure you feel about like going to the next level like you know there's nothing
special powers coming all animals return data
and so how you like the next level against you
sorry I missed the last sentence i'm going for functional again
well I wouldn't consider changing from returning water system returning
stomachs as more or less betrayed stomach eat late structure this animal
with a distraction right well if you look at the code i use the word walrus
but really there's nothing especially wallasey about the code you could
replace that with animal and it wouldn't know the difference right just knows
that there is a stomach in there is inside of the stomach is is an array of
various foods so it's not tied to go to the walrus nature of the walrus the the
user has walls right you walked into class
it's not
randy was an example well no I never mentioned a walrus class I could have
used the word animal it would have been the same thing right as long as it right
as long as it has a stomach that code work on it i just used waters to make it
more concrete equipment are you struggling just 30 days values of the
name then like their values are boundaries about objects are data if
they're if all if all the the methods on an object are pure functions then the
object is data and it's indistinguishable from an object that
struct that has everything really bound right late binding only matters in a in
a system with mutation in it
this is why for example Haskell is lazy well Haskell's weird
yeah I don't know how to say that I feel like I'm failing to understand some part
of your question okay yeah things like both
we do that
the square
dance for man all right so yeah so well if you go if we go back to the place
where actually did that where i merged way back here
there it is this was actually the functional example right if you look at
the the functional 00 example i just did Wallace . new which is a little more
natural there's not an easy way to say i want new object with only this field
change because ruby is not designed for that but that is easier to build in than
it would be to build in to replace all your core types
the nice thing about the Ruby core types is that the the really scary things have
bangs on them usually the mutation it's not true for like delete but but the
names are usually very obvious that they're mutating or they have a bang on
them I've actually not found a problem maintaining maintaining functional data
structure manipulation code in Ruby your mileage may vary
yeah in the back
read that last operator
write your function
follow exactly what happened
it certainly could you have to spend what i found is that the the choice of
which classes you have in the core is extremely important the names of them
and the the way that the responsibilities are divided up so
actually I could pull up part of the twitter client and show you guys a
larger example let's see
wait where am I
yep so for example the cursor cursor this is one of this is a piece of the
functional core it has state that includes the tweets in a list of tweets
and then selection is the currently selected tweet right so this encapsulate
all the behavior of the cursor actually is my keyboard not working part of some
of this is gross like it's actually quite a large class this is one of the
largest classes I've written since i started programming Ruby it's almost a
hundred lines but that's because it's really like a very small module and dude
laughs it's like a very small module of functional code that's just sort of
self-contained and then if we look at the actual imperative shell this is the
entire shell it's a hundred and fifty three lines that says you guys read that
they're sorry about that
so let's see where cursor . something with tweets now starting index the shell
is sometimes a little bit awkward
here we go so here is the cursor actually being manipulated when you hit
j-just reassigns the current cursor in the shell to the result of doing cursor
. down and if we look at cursor . down all it does is constructing your cursor
so the fact that i chose cursor to be one of the boundaries and the functional
core is very important if i had had a tweet list and then was maintaining a
selection separate from that this would have been awful
it's very important to find those boundaries that make very small cohesive
functional components but not too small i mean i showed you like three line
examples in the talk but that's because it's a talk
really you want peace is larger than that but smaller than a whole subsystem
does that answer your question at all those Chuck right yeah I can't see but I
can hear
what does yep that's the hard part i mean it's always the hard part right but
separating separating things that do mutation from things that don't give you
a starting point and I it's the best starting point i've found it's not an
absolute rule but if you start there as opposed to some other arbitrary rule i
found much better results for design other questions
there is no library the the twitter client is not online because I stopped
working on it because it turned out that twitter twitter evilness is growing much
like test run time of a integration sweet
and III lost confidence that I should build software that interacts with it
sorry Twitter employees I assume there's something here
yeah so none of its I'm sorry
fair enough fair enough at least it scales he's pretty much you always why
many forms that you look like the starting well yeah i mean the the
Twitter clients doesn't really have many performance concerns i mean it does when
it comes up it's sorting through thousands of tweets that remembers
everything all the way back and so it has to emerge of like what it has versus
what it sees from the API but it's not doing anything really big in an MRI your
life may not be especially good if you're doing tons of tons of allocation
if you're in the jvm it's much better right and if you are you in a vm that's
designed to have constant object creation and destruction it's going to
be even better than that a vm designed for functional programming i would guess
that the Erlang vm would would handle this very well for example because
interline you're constantly making small objects and letting them be free so yes
doing doing this on the one on MRI if you have performance concerns is
probably going to be a little difficult but you can do certain types of caching
right if everything's a value and immutable you can always cash things
because they don't change so there's their ways their ways to to work around
the the unfortunate nature of your vm i saw hand back there yeah yeah what's the
what's the biggest thing you built this style and you do have concerns that as
against big the related organized both good question is what's the biggest
thing i built him and drive concerns about scaling this into a larger
projects the biggest thing I've built is the twitter client it's not that big
it's about 600 lines and i would not be up here talking about this if that was
why i thought this is good
the reason i think this is good is that it it it has a has shades of both the
actor model built into it the idea of functional pieces that are communicating
by passing values back and forth and it also is a lot like the haskell idea of
using the IO monad to encapsulate state which is a wonderful idea the scales
wonderfully up to about 500 lines of code and then everything falls apart
right you look at 20,000 line Haskell program that does a lot of i/o and
you're not going to like life that this is why i say i think that the larger
program is smaller ones built in this way communicating via via channels
external to the process but what I'm really trying to do is merge merge this
idea of actors emergence idea of the IO monad and bring them into the OH world
using our terminology right I didn't talk about monads I only talked about
actors at the end as an example
I'm trying to read rephrase that stuff and terminology that we use so that it
that it seems more directly accessible but to get back to your question about
about larger systems some of the largest most well some of the most reliable
large systems in the world are written in erlang and probably probably most of
the reliable large systems in the world are written in our line lots of lots and
lots of nines not not like Twitter's 394 talking about like 8-9 right and the
fact that they can build large systems that are that reliable using the actor
model even not even knowing what those words mean tells you that there's
something there right so there's a long-winded answer to a very simple
yeah area
it's an approach that you might recommend in one were creating a new
rails app lets say they were creating a user model it was
subclassing face an approach that one might take try to experiment with with
techniques talking about basically right
what sorry if if if you're building a new rails application and you're doing
things like you have a user two subclasses active record bass how do you
how do you go about doing this
I haven't gotten that far yet i have opinions about how you should be
building that application but they don't involve this
that's a different talk called deconstructing the framework but yeah
it's not clear to me yet gimme gimme a year or two others
yeah case where the extraction for example would be super
capacity at all but it turned out the databases really fast building that that
expiration yep one of the reasons of my talks to take half as long as when i
practice i forget to give all the qualifications like for example you
don't actually do that right you wanna call user all then filter in in Ruby the
most of the complexity of your application is not database . right i
mean there's there's plenty of clearing in a complex app but but it is not the
fifty percent of your application it's a fairly small percentage and I think that
probably depends if you're using a using postgres or my sequel or or sequel light
that goes in the shell if you're using something like the atomic which is a
database where everything is immutable that can go in the functional core i
think it's just data structures date comic is just data structures so it
depends on the nature of your database and the more your components are
designed to work in this way the more can move into the core but it doesn't
mean that pieces
it doesn't mean you can't do this if you have postgres it just means chris has to
be relegated to the scar tissue which i think is fine
eighty percent functional is a heck of a lot better than zero percent you don't
have to get to ninety-nine percent yeah from you
what keeps me in Ruby inertia to a small extent also i just don't like any of
those languages I i have this this problem where I can't I can't not care
about syntax i really like syntax and I've written i wrote a lot of list in
college and I just never really enjoyed it that much
python and ruby or what I like syntactically this is why I want to go
crew live on a cruise ship and write a new language how we doing on time is 310
do a couple more guess yeah
ways to fix these problems contribute to romania's for about a year until you
know how it works and fork the Ruby language i'll tell you how to do it i
mean you want persistent core types right you want to you want four types
they're designed to be used in this way and from that most of this will fall out
for you pretty naturally you probably want actors and lightweight processes
and you're gonna have to build a user lands scheduler but it's not that hard
that's what airline has and if you have a user lands scheduler with lightweight
processes if you can for 10,000 hundred thousand processes easily and you have
immutable core types for most of the way towards doing this
ninety-nine percent of time or ninety-five percent of time ya back
right already sort of asked us for someone who very well with people
Twitter guys I would still encourage you
ask you this example this style
yeah the question is why won't you answer my question
now that's a legitimate I do i do plan on putting this up eventually even
though i kinda am NOT happy about Twitter I just I i struggle with the
idea of encouraging people to write software that interacts with something I
don't like vs demonstrating something that I think is good so yeah
also it's a little bit embarrassing like the shell is not actually tested at all
there are 0 tests around it even though 250 lines along which i think will give
people the wrong idea i mean i have reasons that I did that but but they're
very hard to articulate in like a readme that anyone will actually read so I'm a
little torn about encouraging bad things and middle right i think this is a
little bit more related question but since
what if you look at great length
their artistic insurance right vs
and because I idea
red level for long are from the future just wondering whether right so the
question is have I looked at array languages and and dude believes that
thinking explicitly about threads or assume you mean processes as well like
any kind of explicit yeah out of control
ya think about those explicitly isn't it is not the the right long-term thing
the first the first answer is no that's easy I i mean i'm familiar with like Jay
and all those languages i don't actually know any of them
I've seen small snippets but I don't understand them the to the the second
part about threads and raise your threads and and processes not being the
right primitive I guess would be the word right there very primitive to build
I'm not convinced that's actually true i'm not i'm not convinced that the wrong
thing I assume the alternative you're thinking of it is things like a parallel
map right like like implicit parallelism that if you're still writing sequential
programs just have parallel pockets
whereas in the actor model everything is inherently parallel I mean if it's even
remotely reasonably be composed right as long as you don't have one process
that's doing a ton of work so i'm not totally not convinced that that the
threads of processes around while i'm convinced that threads are wrong if
you're sharing the state but I'm not convinced that independent threads of
control independent processes of control are the wrong thing
yeah we thought about writing your twitter application using a more open
for calling
writing the twitter app against a more open protocol like Oh status i guess i
could doesn't sound very interesting that's the problem I huh
I already wrote it once i don't want right maybe I'll put it on github and
I'll accept your request but that put it on a more open protocol i think yeah at
that it is time thank you guys very muc