00:00:16.320
all right so uh simple and elegant rails code with functional style is the name of this talk
00:00:22.560
i've been working professionally for three years now i spent eight years in the dotnet space there's
00:00:28.960
a little bit of a feedback can you help us with that thank you can you guys hear me
00:00:34.239
cool so i spent uh eight years in the dot-net space and i i was lucky and fortunate to switch over to ruby and
00:00:41.280
ruby on rails i was laid off to uh two months ago from my previous job
00:00:46.640
and i found a new job in chicago so i'm moving from northeast ohio to
00:00:52.559
to chicago
00:00:59.199
are we cool okay anybody here from chicago all right see you guys there hopefully
00:01:05.680
soon um this is the company i work for i am the only developer right now we are
00:01:11.360
looking for other people um we are really big in the franchise space and we make um
00:01:17.759
we actually give numeric results uh for hiring decisions so instead of
00:01:23.360
just making a instead of a gut feel you basically have a numerical results and you can pick
00:01:29.119
your best candidates based on that i'm not going to
00:01:34.560
teach you functional programming in this talk and i'm not going to try to bend ruby to be a functional one either
00:01:42.079
hopefully i'm going to show you some simple and elegant rails code
00:01:49.680
in my previous job shouldn't move right
00:01:55.600
all right i won't i promise you uh so at my previous job i had uh 25 minutes
00:02:00.719
commute um to work and i listened to the radio but i got sick and tired of the
00:02:05.759
of the commercials and i decided to listen to audiobooks and the book e-myth revisited was recommended to me by a
00:02:12.480
friend of mine and i remember the moment when i heard that sentence the work you do is a reflection of who
00:02:18.239
you are you know when i see somebody does a crappy job i i don't think about the job he does i kind of think about
00:02:24.480
what kind of person he is or she is if you can translate it to our own profession
00:02:29.680
the kind of code you write it's it describes what kind of person you are
00:02:35.200
two weeks ago i went bowling with my son and i drove through um this road and i thought
00:02:41.200
uh i'm going to lose my one of the wheels on my car i stepped out and you see the car is passing right there but i
00:02:46.560
took a photo i think it took more than one or two years to end up a road like this and you
00:02:51.920
can see that they try to try to fix it but how successful that is right i call
00:02:57.280
this road refactored you know they they put the tar in it you know and it's
00:03:02.800
good probably for like a winter half the winter and then the spring comes and and this fix is going to be um pretty much
00:03:09.040
as big or maybe bigger this pothole is going to be bigger uh than what it was before
00:03:14.239
uh late last year i went through the uh the news and i i found this story from from china
00:03:20.239
the person refused to sell his uh his apartment and the government just couldn't wait to
00:03:25.760
build the highway so what they did actually they built a highway around it
00:03:31.840
yeah no kidding uh two weeks later i think they agreed on some kind of price and they they
00:03:37.200
finished the highway property but still so i think this is an awesome story and i thought nothing could nothing could top
00:03:44.080
this but i was wrong i actually a couple of weeks later i found this a family refused to remove the remains
00:03:50.400
of the relatives and they had to build this building they put down the foundation well they couldn't wait you
00:03:56.480
know they just started to do it around the graveside here's another angle
00:04:03.599
do you remember what your room looked like when you were 15 years old you know mine looked probably something like this
00:04:08.799
i spent i spent probably hours looking for my textbook my jeans or whatnot
00:04:15.599
yeah this is this is what this is what it looked like when i grow up and i'm not proud of it but that's what it is
00:04:22.160
so let me show you this puppy here this this is a model from
00:04:27.360
one of the rails apps that i had i had the privilege to work on this is actually an e-commerce
00:04:32.400
application this is the orders model 2700 lines of code
00:04:39.360
i'm not uh kidding the calculate shipping method in it it's uh i unfortunately don't have my notes
00:04:45.600
it's on my cell phone uh but the calculator chipping method is is somewhere around 206 lines of code uh
00:04:52.240
and right below it there's actually a recalculate shipping method 197 lines of code
00:04:58.400
untested yep so we tried to tackle it uh we
00:05:05.120
looked at it and like just screw that it's just it's just too much too big of a work
00:05:11.360
when you see code like this think about companies actually that has code like something like this i was laid out from
00:05:16.960
this company because of financial reasons this code actually can bring down a company think about it that way
00:05:23.280
and it and i i would like to give them the excuse that actually this code was written by contractors no actually it
00:05:29.120
was written by employees but before i got there so i wanted to find a tool a good tool
00:05:34.800
that i could use to analyze code complexity and i bumped into the flock jam does anybody know the flock jam here
00:05:41.680
awesome um i talked to actually jim weirich at a different conference early january and he said hey i use actually
00:05:48.240
flog to run it against a project that i haven't seen i don't even have to crack open the classes it just gives me a
00:05:53.919
value and based on that i can tell how big of a mess or how clean the code is so
00:05:59.120
the way it works is that you run it against a class or a group of classes and you're going to get
00:06:04.160
you're going to get a number and what you need to know about the number is that the higher the score uh the more pain the code is in or i
00:06:10.639
could say uh the higher the higher the number the harder to test it okay this is really central in my in my talk
00:06:17.759
so uh please check it out installing it is super simple you you
00:06:24.240
have to add it to your gem file i usually edit in my rails app i add it to uh development or the test group
00:06:30.000
and um you can install it through rubygems jams running it is super simple it's going to
00:06:37.120
give you a numeric results you can run it against one class or a group of classes what i usually do i just run it against controllers and
00:06:44.000
and models and i 95 i can tell what kind of code i'm looking at
00:06:49.680
so uh the video that you saw earlier in in in the previous slide
00:06:55.360
it has 25902 flock point
00:07:01.039
imagine that so just just so you can you can you can the the number hopefully that i'm going to show you here is going to have some
00:07:06.960
kind of sense to you or it's going to make sense um the ideas that i'm going to talk about
00:07:12.400
here um were born um through working on different uh rails applications uh in order to kind of
00:07:19.199
retell the story i wanted to come up with uh one application and this is a tracking application where you can
00:07:24.880
provide the category the amount and description it's key that it's not just a simple save you know just get the
00:07:30.319
value and save it in the database it has to do some kind of parsing logic right so when you provide running 3.2.12 it's
00:07:37.120
going to save it into a category table with the value of running and then the
00:07:42.160
track amount and the json data basically with the amount and the kind of description
00:07:47.759
around it it's going to file the track with that with today's date if you want
00:07:53.199
to override that that date you can actually use you can actually use the uh the date
00:08:00.479
prepend it to your input let me ask you a question um where do
00:08:06.879
you put your domain logic do you put it in controller raise your hand please if you if you put in your controller
00:08:13.039
come on guys how about models what do you do you put domain logic in the models
00:08:20.319
okay so that's like one third of the room how about you get how about the two-third of the room where do you guys put domain
00:08:25.440
logic okay all right
00:08:35.519
yes yes so i i thought actually this is history but
00:08:41.440
the the code base i inherited from contractors uh or consultants actually i don't i don't call them consultants i
00:08:46.959
call them contractors uh the code base i inherited from uh from contractors at hierology uh it's controller heavy
00:08:55.040
so uh 1750 lines of code actually in a controller is not uncommon
00:09:01.200
yes oh and by the way i when i was interviewing i asked the contractor hey how many units do you
00:09:07.440
have you can guess the number right zero i'm sorry
00:09:14.720
i i did because yeah good point i did join them because the business idea is great and i think
00:09:20.560
they have a future yeah we just have to clean up that uh clean up that application and i'm i hope i can come
00:09:26.399
back and tell you guys the story how what we did about that so basically uh what i try to do is i
00:09:33.040
try to code this parsing logic into the controller action and this is what pretty much what the code base i'm
00:09:38.720
working right now looks like i don't want you to spend and understand basically what it does um it basically
00:09:46.000
just has the stamp on it right this 48 lines of code are really bad
00:09:51.680
this is how the flag looks the flag values actually are trending uh this is our initial state i'm comparing black is
00:09:58.240
the controller in case you can't see it you cannot see it and green is the model right the controller has a higher value
00:10:04.000
because it does the parsing right the the model has some additional logic but but not all that much
00:10:09.920
all right so what i did i used um our favorite refactoring pattern extract method instead of using uh comments i
00:10:17.360
use the method names to describe that particular routine what it does i went from 48
00:10:22.560
lines to 25 lines and
00:10:27.760
yep this is actually how i ended up with the refactoring and this is what the flock
00:10:33.040
values are after this refactoring exercise flock total went up slightly you can see it's 71 and it was around
00:10:39.600
65-ish however the method with highest flog in the controller dropped down to health
00:10:45.200
right so instead of looking at that huge action you know with like 40 something flock value 46
00:10:51.279
point it's not 20.6 just by using extract method a pretty good sign
00:11:00.560
and uh this is uh this is where we went right we figured out that uh reusing logic from the controller is not all
00:11:05.760
that easy so what we did we went from fat controller to fat models
00:11:11.040
um i tried to follow this trend as well i moved the parsing logic from the controller action put it into uh the
00:11:18.000
model and you can see now that the controller looks pretty nice pretty clean you know instead of doing the logic itself i'm
00:11:24.480
actually doing the parsing in the model and i'm just sending the message to them to the model
00:11:29.600
and look look how we are trending here the model went up to 84
00:11:37.360
and and then the controller actually dropped down to 25.6 pretty clean you know i i can tell you
00:11:43.600
that the class with 20 30 flock point you can you can pretty much grasp and understand
00:11:49.600
what it does and always think back you know that that example that i showed you that was 2500
00:11:54.959
right 2500 points
00:12:01.040
and this is where i joined the party three years ago when i when i started working on the rails application that i
00:12:08.160
that i had the pleasure to work on it was a by that time it was a four year four-year-old app
00:12:13.200
and when i joined the company i asked the fellow developers uh how many unit tests do you guys have oh we have zero
00:12:18.880
that's why we hired you we wanted you to help us with that that's it's cool and why don't you guys running it and the
00:12:24.720
answer i got was is that it takes forever to run it it was 17 seconds actually on that code
00:12:30.399
base to run one spec so imagine doing tdd by that
00:12:35.920
so what i decided to do early on is move my business logic out into services and uh i had a blog post out there on it it
00:12:42.800
got uh quite a bit of hits um
00:12:48.000
and i was i was stubbing actually a whole lot of stuff out of rails that i don't do anymore but with these
00:12:53.040
techniques i was able to go and run execute extra specs under one second it was a totally
00:12:59.440
different feeling all right so the the code really doesn't
00:13:04.560
change all that much after this change instead of calling the the the model i'm calling the service
00:13:12.320
and the service itself is a poor object it doesn't inherit from any kind of active record or action controller
00:13:18.399
anything anything rails related so i can easily test it as just like a pure plain
00:13:23.519
old ruby object do you guys do you guys actually write services this way
00:13:30.079
using poros raise your hand if you if you ride those sweet
00:13:36.320
all right so i'm switching extra gears here with my um uh the graph that i'm using actually to
00:13:41.839
represent the flag values instead of comparing the controller and the model now i'm actually comparing model to
00:13:48.160
services because that's where i'm shifting the code you can see that the tool for the model
00:13:53.279
went back to 38.4 uh where it was before and uh and this and the service actually
00:13:59.680
is around 71 points and i'm using only one service class so that's why you see
00:14:04.880
that the floc tool actually and the flock class average are the same
00:14:13.040
this is how i wrote service classes at the beginning i had an entry method in this case actually it's four track
00:14:19.440
um that red reddish kind of circle represents the controller and
00:14:25.120
that's the service the four track is my entry method it calls other methods on the service
00:14:30.800
itself and by the end of the call chain i have an instantiated track object available
00:14:36.560
and this was beautiful because i was testing actually all the methods i made all methods private i killed many
00:14:43.279
unicorns i'm proud of it but basically what happened was that uh this was one object and when i changed
00:14:48.959
the signature let's say the builds category for the builds category method went from two arguments to three arguments all of a sudden my unit
00:14:55.120
started breaking like why i mean this shouldn't of course because i was testing uh private supposedly private
00:15:00.800
methods i made them public just to just so it's easier to test so i changed it back i'm gonna i use
00:15:08.000
actually a one public method on the service class four track everything else was
00:15:13.680
private and i was able to change now the the signature of the method however uh
00:15:19.920
setting up the test were really really hard just because that service object was violating single responsibility
00:15:26.079
principle and it was really hard for me to test those and the question comes what do you do
00:15:31.279
when your business customer or your customer comes back to you with additional requirements where are you going to put
00:15:37.279
that code how are you going to grow this service right are you going to add another method are you going to increase
00:15:42.720
the the effort that it takes actually to run one single test yep just think about that
00:15:49.839
i was sitting at this coffee shop a year and a half ago in january helping a co-worker actually with the problem
00:15:57.360
and um we called it a service this way and it took me i remember 10 minutes
00:16:03.120
trying to understand why i cannot run as a spec why spec is failing what is the dependency there it was obvious
00:16:09.440
that the specs are telling me something and i wasn't listening
00:16:15.040
before i continue the story i'll take a look at how i name my service instead of using objects physical
00:16:21.199
objects like user or employee or door or car i'm using actually verbs they define action
00:16:27.920
and what i've what i learned is that i can follow single responsibility by naming my services this way so when i call a
00:16:35.120
service parties feed i know exactly what it's going to do i know it's not going to save a category into the database
00:16:40.480
table i know it's going to send it's not going to send an email to the customer or anything like that it's going to do one and only one thing called uh
00:16:48.000
parser's feed it's just going to parse that feed that i'm i'm passing to it i attended code retreat um pretty much
00:16:55.040
at the same time when i was sitting at that coffee shop and somebody recommended reading this blog post
00:17:00.480
please do yourself a favor and read this this is actually written by a java developer it's called execution in the
00:17:05.679
kingdom of nouns read that blog post and you're not going to name your uh your
00:17:12.240
your object the same way or your service is the same way
00:17:23.679
so as complexity grew i saw that my methods actually grew from five lines of code to eight lines to ten
00:17:30.640
lines of code instead of doing that what i did i created sub classes as i went and i created subclasses for
00:17:37.600
all these methods that i refactored early on and used extract method for
00:17:43.360
what i gained with that is that it was so much easier to test it because all i had to do is just stop and mock the dependencies i didn't have to go and set
00:17:50.160
up all the requirements that it needed what i what i cared about is that they were called in order uh so i was it was a whole lot happier
00:17:57.600
experience but still i didn't feel it wasn't perfect what i was striving for actually was
00:18:03.280
this i really wanted to have a code that looks like something like this i wanted a uniform interface i wanted a i wanted
00:18:09.600
a method actually with context as an argument to add it to it and uh the reason i wanted to do that is
00:18:16.400
because it was super simple to test this right it was only one argument that it had to take in it was only the the context
00:18:22.880
method that i had to stub out so this is what i was striving for
00:18:28.640
as i mentioned i spent eight years in the java.net space and i learned design patterns or tried to learn design
00:18:33.919
patterns quite well which design pattern is this
00:18:39.360
there you go chain of responsibility i loved i love this design pattern the reason i loved it is because uh
00:18:46.480
whatever i had to do my work it was uh i had it was not only one thing that i had to do it was like five things just like
00:18:52.320
in this case you know i received the arguments i had to split it i had to sparse it i had to check if data was best in front of it i had to validate it
00:18:59.600
i had to save it in the database every kind of test that i do has at least six steps five or six steps to it
00:19:06.080
um and i and i i believe actually the chain of responsibilities is a pretty good solution for it i tried to build
00:19:11.520
chain of responsibility in ruby but it was just too heavy it just it just took too much effort i think chain of
00:19:16.960
responsibility makes a lot of sense in java you know in the statically typed languages but
00:19:22.160
but in ruby it was just an overkill so as i as as i went through this exercise and i showed you what i was try
00:19:28.640
striving for uh two types of objects emerged one was actually the organizer object that you see here in in blue
00:19:35.520
and uh little actions that i'm going to talk about later so the the role of the organizer object
00:19:41.520
is uh telling you a story so when you look at an organizer object you can you can pretty much figure out what that
00:19:46.799
particular process does in my case it starts with the splitting the feed to parts apart sorry
00:19:53.200
parts is the recorded at validate speed so on and so forth and when you put code around it
00:20:00.480
you could still read it you see that's what's so beautiful about this you can still read it out you don't have to kind
00:20:05.600
of hand down what it really does it has step one step two step three step four so on and so forth
00:20:13.039
so the organizer object tells you the story that's what it does nothing else it doesn't execute business logic or
00:20:18.799
anything like that it just tells you the story however the actions the actions are the
00:20:24.160
the atomic building blocks of this process or series of actions i call them
00:20:30.559
and what they do is uh one action represents one business logic right in there
00:20:38.320
the actions are called in order they are called by the by the by the organizer object and data
00:20:46.080
is passed into it through the context so let's look at one of these actions
00:20:51.520
one of these actions this is what my class looks like you see it has an execute method that
00:20:57.360
takes a context in it is a guard condition it pulls the data out it has to work on it runs the business logic
00:21:04.320
puts the shoves that's the data in back into it and at the very end it returns a context
00:21:10.799
so after i refactored that large service class with multiple multiple private methods this is what i ended up with
00:21:17.840
look at how my flock last average for the service i should drop down from somewhere around 70 to 13.9
00:21:26.799
i can tell you you can understand a class actually with with a log value of 13.9 very easily it's just super simple
00:21:33.760
to understand you could ask me what is so functional about this well i'm not maintaining
00:21:40.799
state all my actions are stateless and functions are wrapped in a class object
00:21:48.000
i could have used module but i to be honest with you sometimes i do use actually a little bit of a private class
00:21:54.400
i'm sorry private method and and that's that's pretty much it you know it cannot be simpler than that
00:22:04.080
the context itself is like a conveyor belt in an assembly line it's um just
00:22:09.120
like the the way uh cars are being built goes from one station to the other there
00:22:14.159
are workers adding stuff to it or altering things on it that's exactly how the context works
00:22:21.120
and the objects actually has a well-defined structure
00:22:29.200
yep the context actually you can see that it's instantiated by the organizer object
00:22:36.640
and they are being used actually to pull the data out just like i i use the analogy
00:22:43.120
with the assembly line and they are pushing
00:22:48.320
they are pushing uh the contacts into a failure state because i need a signal if something failed i don't want the third
00:22:54.880
and the fourth step for example to execute so in this
00:23:00.159
slide i'm describing that the first action passed the second one failed and then the third and the fourth did not
00:23:06.400
even execute as i was going from one job to the other
00:23:11.840
and one project to the other i ended up copying files and
00:23:17.039
referring back to david's keynote necessity actually brought me almost to a framework or some kind of gem and that
00:23:22.960
gem is called light service i didn't sit down and just write you know light write service i extracted it
00:23:29.039
out and it's very simple and the reason i call it light service is because it has only two classes in it and i'm proud of
00:23:35.600
it and i don't want to make it more complex than that i want to give people the freedom to do any any way they want want to use it
00:23:42.640
the organizer object has its own structure feeds the data
00:23:47.919
builds the data actually uh with the in the form of context uh iterates over the actions uh and
00:23:54.400
calls the execute method on it and then injects in the context into it and
00:23:59.440
return the returns the context at the very end um the action itself has um an execute
00:24:06.480
method returns the context if there's a failure there that's the guard condition
00:24:11.520
extract the data out of it this is where you put your business logic basically and at the very end you
00:24:17.440
return the context so a friend of mine a friend of mine who
00:24:24.080
was working with me at the time asked me you know it's really annoying that i have to remember the guard condition and the execute method at the very end
00:24:31.120
sure very good uh observation what we decided to do instead of uh using and
00:24:36.400
make you know you have to remember that you have to edit the car at the car condition instead of doing that what we
00:24:41.760
did we actually created a macro so you don't have to remember to add the
00:24:47.360
guard condition return the execute at the very end executed is going to give you actually the execute method and then
00:24:54.159
the block is going to be called whatever you pass in there yep hopefully it's so much
00:25:00.480
easier to use you can go ahead and take a look at it install it through rubygems or
00:25:06.400
download it yourself and clone it the question comes though is what
00:25:12.400
happens when you have to grow software you see every project starts out so beautiful the first two months everything just flies so fast right and
00:25:19.120
two years later it's like one tiny change that would that should take half an hour takes three days right
00:25:24.480
so the question is how are you going to grow your software i think that's that's that's a crucial question here
00:25:30.240
in order to uh kind of see how i could progress to a model that that has 27 lines of code
00:25:36.559
in it uh i decided to make an experiment what i did i actually had the controller
00:25:42.080
action with you know with the extracted method in it and i'm comparing the services with the
00:25:48.240
organizer and the actions so that's what you see left hand side is the controller with the with the parsing logic in it
00:25:55.039
and then on the right hand side with the red color you can see the series of actions right there
00:26:00.480
and this is our initial state uh the the complexity uh on the right hand side for
00:26:06.080
flog class average is 71 and the actions are at 14 points
00:26:12.240
all right what i did actually i since we were talking about growing software right what i did i duplicated the methods so and i uh appended the
00:26:21.120
one to the very end of the method names so i had not only parsers feed but i had parsers feed one parser's feed
00:26:27.520
and you get the picture and i did the same thing for the classes i just duplicated the classes as it is
00:26:33.120
you know so instead of having six actions i had now 12 and these are the numbers i had uh it
00:26:39.200
went to 124.2 uh for the for the controller because i had only one controller right
00:26:45.679
uh and the method i'm sorry the flag class average was around 13 still
00:26:51.520
and i tripled that and this is what happened you see how it starts growing and i believe if i if i'd
00:26:57.520
if i'd done it long enough i would have probably ended up with a vlog value of 27 or 2500
00:27:04.240
but the key point here is that the class average is at 13 point
00:27:12.960
so this is the trend that i noticed uh if you keep growing your software just in one class you know that even if
00:27:19.200
you had multiple methods in it it's going to be on you know and uh and and the class average flag class
00:27:26.960
average is going to be around 13 or 14 if you keep and stick to that style
00:27:34.240
what a warning um when would you use this i found in my ass so would you do actually a series of actions with light
00:27:40.159
service all the time uh no actually i wouldn't if the complexity or the
00:27:45.279
business logic doesn't require it i wouldn't do it i would actually take advantage of rails i would use it for
00:27:51.120
that and i don't do it you know i mean whenever i have update attributes and it works perfect just do it
00:27:56.640
but as soon as i have a conditional maybe i keep it in the controller as when i have the second conditional or
00:28:02.640
maybe a conditional and an iterator i'll break it out into a service and if that service actually is doing more than one
00:28:08.399
thing i'm breaking it up into two actions and one organizer object
00:28:13.760
so that's the principle that i've been following in the last couple of months and this is how i show you that take
00:28:20.240
advantage of updater attributes if the case is simple please use please use rails it's pretty
00:28:25.760
good at pretty good at that what if you haven't worked on this code for let's say six months and uh and the
00:28:32.960
customer comes back that hey um the babies initialize the the category i want to do something else there as well
00:28:38.880
what do you do well since i'm not using observers i'm not using concerns
00:28:45.360
basically what i have to do is just look at either the routes or just execute the action
00:28:50.880
figure out which action and controller i have to go into i find the controller and in the controller i see that okay
00:28:57.120
the logic is not coded there actually it's externalized into a service very good i follow that and i easily
00:29:03.360
follow the service i go into the rails independent service and i notice that the logic is not there it's an organizer
00:29:09.039
object from a series of patterns a series of actions sorry and i look at since it's really easy to
00:29:15.840
read i look at the actions and i find actually that the category is the fourth action
00:29:21.520
i open up that action and from the 13 lines of or 50 lines of code i can easily find the line where
00:29:26.640
the category is being initialized super simple actually to find the code i remember actually pairing with a
00:29:32.880
developer at a shop in chicago and they had a build failure and we stared at the code for an hour trying to find why we
00:29:39.919
can initialize an object through a factory how's it going
00:29:45.919
the other advantage that i found was actually code reuse this was about a month ago i had to work
00:29:51.760
on uh one of our interview guides when we load it we have to go through a
00:29:57.520
series of different tasks and i uh put it in into this code this is actually from our
00:30:03.600
production system you can see how i built an organizer object with seven different
00:30:09.600
actions and admins actually can edit the same questions they can delete questions in
00:30:15.919
order to load it for edit in the admin section i was able to reuse four out of those seven actions easily
00:30:22.960
huge reuse all i had to do was just create a new organizer object and i was on my way
00:30:28.480
beautiful code reuse and that's what i ended up with
00:30:33.919
and unit testing it i didn't have to unit test you know the actions i was able to unit as just the organizer object boom done
00:30:42.240
and i also found out that i'm not alone with this kind of this kind of thinking i paired with a developer at hash rocket
00:30:48.000
in chicago and they were using actually strategies they didn't have a gem or didn't have a best practice for this you
00:30:53.440
know but i noticed that they are actually weaving actions together here in this particular code
00:31:02.320
so my summary um get out of the framework that's what i try to do all the time and put my
00:31:07.679
business logic outside of rails so i can unit test it really fast and i can reuse it anyway i want i can move it from
00:31:13.120
rails to a background worker anywhere i want i can put in a gem if i want to the coach should tell the story you
00:31:19.200
you'd look at it and you should it should read it like a paragraph in a book don't use state if you don't have to i
00:31:25.440
think it gives you complexity and it's just going to make your code more complex that's what i found
00:31:31.760
behavior from the data my data is actually the model in the context and that goes and flows through
00:31:39.120
the commands or actions and grow your code horizontally instead
00:31:46.320
of adding another method to a class to a model or a controller
00:31:51.519
create a new class please just grow horizontally what do you do when you have a change you encapsulate that
00:31:56.559
change actually in a new class and most of it will make it simple
00:32:03.440
so when you remember um this this actually a 2500 lines of code that i try to represent with this messy
00:32:09.760
room i'd like you to think about this hotel room in japan this is actually a hotel room without a tv without a
00:32:16.320
furniture or anything like that look at the simplicity of this hotel room so when you see actually an action like
00:32:22.080
this i want you to imagine that hotel room without any access any access furniture anything
00:32:27.200
anything anything unneeded here are my social links
00:32:32.399
i'm gonna have it up there in a moment thank you for your attention
00:32:38.000
i actually you can find the slides it's an older version but you can find it actually through this link if you want
00:32:44.159
to write that down it's bitly ad at railsconf i constructed that link this
00:32:49.519
morning and thank you for your attention
00:33:30.960
you