00:00:13.880
okay welcome thank you for coming uh this is a talk that we call a brew guide
00:00:19.000
to filtering out complexity and churn or you can call it the coffee machine talk um our goal today is to show you uh
00:00:26.039
how to remove the bitterness caused by complexity from your application uh over the next 30 minutes we're going
00:00:32.480
to show you how complexity sneaks into your application uh how to recognize it before it becomes painful and how to get
00:00:39.040
rid of it permanently so we're going to introduce ourselves and then we'll get going hello again I'll go first my name
00:00:45.719
is Alan rle Hoover I use the pronouns he him and I have 13 years of experience
00:00:50.800
with Ruby also I grew up in Seattle so there's coffee like in my veins um and
00:00:57.000
my favorite is a sugar-free vanilla oat milk latte which is very
00:01:02.760
Seattle hi everyone can you hear me well you can hold that thank you um I'm Vito
00:01:09.159
F sastro I use the BR him um and I've also been using ruie for um a little bit
00:01:16.920
over 13 years now I'm from ason parai originally but I live in the San Francisco Bay Area now um and if there's
00:01:24.240
one thing I love as much as I love Ruby is coffee my favorite is a dark chocolate
00:01:29.360
mocha um now Al and I work together at a company that you might not expect given
00:01:34.759
though this is a conference for Ruby developers we work for Cisco Mari we call it the largest rail shop you
00:01:40.840
probably never heard of um but we've also been friends for uh over 10 years
00:01:47.600
now yeah and we've worked together at three different places um we also like to um get together and Cat on the
00:01:55.079
weekends and drink coffee oh I have to say we've seen over the like years that we've work together with code bases of
00:02:01.520
different sizes and different amounts of complexity but we'll get to that um you
00:02:07.920
grew up around coffee didn't you uh yeah kind of um grew up in Seattle so um and
00:02:14.599
in fact when I was a kid I was fascinated by these mechanical coffee machines that my dad had in his office
00:02:21.480
you drop in a coin you listen for the clink you make your selection and then the machine would just spring to life
00:02:27.360
hissing clicking and worrying and when that that whole automatic
00:02:32.480
ballet ended the final sound that you would hear was the splashing of that black aromatic liquid into the cup say
00:02:40.680
magnifi now these days I'm more fascinated by the inw workings of software we both are uh and like that
00:02:47.800
coffee machine there are all kinds of hidden complexity inside code but software doesn't start off that way does
00:02:54.000
it how many of you have worked on a Green Field application wow most of you awesome how
00:03:00.840
did that feel lovely love it um how about a
00:03:07.159
legacy application how many of you worked on Legacy C just about as many how did that
00:03:13.799
feel rough challenging um we agree like in our
00:03:19.680
experience Green Field development is completely enjoyable like there's nothing in your way it feels fast you
00:03:25.480
just move quickly but developing in a legacy application does feel harder why is that we believe it has to do with
00:03:33.159
complexity we think that there's a CR like a threshold which you cross at some
00:03:38.680
point where the complexity becomes so much that you have two choices either you can live with the complexity as it
00:03:45.480
grows and development slows down more and more until you just halt or you can
00:03:51.319
pause temporarily to reorganize the code and speed up development again now we've
00:03:56.599
seen organizations go down both paths and when you take path of living with the complexity what do you think happens
00:04:03.879
developers get frustrated and they often blame the tools and so you'll hear people say I
00:04:09.840
don't want to use Ruby anymore it's just too messy um but it's not Ruby's fault
00:04:16.400
it's the complexity and we did that to ourselves um so what we're going to do is we're
00:04:21.880
going to show you how to take that second path take the red pill uh and remove the complexity and then fall back
00:04:28.800
in love with Ruby okay are we ready want to build a coffee
00:04:34.000
machine let's do it right um so how does complexity get into
00:04:41.120
your code base well the answer of course is it happens one commit at a time uh so
00:04:47.039
let's take a look now I'm going to move through uh the next uh slides pretty fast just to show you the shape of the
00:04:53.880
code as it grows and as it as the code gets longer uh the font size will get
00:04:59.400
smaller so don't try to understand that code it's made up anyway um and also and
00:05:05.120
this is important we're skipping tests here for the sake of time but in reality we would not do any of this without
00:05:10.160
tests so let's get started all right here's the first commit in in our coffee
00:05:17.240
machine at this point the machine does one and only one thing it serves coffee first it will dispense a cup then
00:05:25.039
it hits the water It prepares the grounds then dispenses the hot water and
00:05:30.600
finally it disposes of the grounds now this works great but turns out not
00:05:35.840
Everyone likes coffee so to increase our sales let's add
00:05:41.000
te all right here we've added a conditional to determine whether to serve coffee or tea and in the process
00:05:48.319
of doing that we added some duplication that dispense cup heat water
00:05:53.840
and dispense water steps are all duplicated between the two beverages so naturally at this point let's let dry it
00:06:00.600
up here's the dry version of the code now with both coffee and tea um in
00:06:06.919
production we are starting to get more feedback and turns out the most frequently requested feature is to add
00:06:12.639
sweetener so let's do that here we've added sweetener just
00:06:18.759
after dispensing the hot water now of course not everyone wants sugar so we're
00:06:24.000
going to make it an optional ingredient here okay we push this out customer like
00:06:29.919
it and now they want cream since we already have a pattern for optional ingredients let's just
00:06:36.080
dispense the cream right after we dispense the sugar all right and for our next feature
00:06:41.240
it turns out that some folks don't like coffee or tea let's give them something else like
00:06:48.120
Coco all right and so here we follow the existing pattern and added Coco to the
00:06:53.560
main if statement um but there's no need to add milk or sugar since the C mix it's
00:07:00.240
already Sweet and creamy so let's exclude those optional ingredients when the customer is requesting
00:07:07.720
Coco all right and finally who doesn't like whipped cream on their cocoa and
00:07:13.440
heck I didn't like it on my coffee the Baristas look weird at me but I really like it so let's add
00:07:19.800
it okay so whipped cream is an optional ingredient that no one wants on their
00:07:25.440
tea so let's add it after the other optional ingredients and exclude it when
00:07:31.240
the customer is requesting T okay so here we are seven commits into
00:07:37.599
this code base and we've already got nine conditionals in one method now at
00:07:43.120
this point this is still relatively simple to understand and work with if you're the only one working on it but if
00:07:49.319
you're part of a larger Team Code like this one scale the reason for that is
00:07:54.680
future developers will just keep adding like following the existing patterns
00:07:59.800
adding more conditionals with each new feature and that's going to cause the complexity to
00:08:05.680
Skyrocket and our little coffee machine has been so successful that it was just
00:08:11.599
purchased by a big National soup chain they want us to add soup to our
00:08:18.800
machines now that's going to add a lot of complexity to our code so let's pause
00:08:24.520
here and evaluate where we are before trying to add any more features Alan can you take a it
00:08:31.839
yeah so uh we've reached an inflection point in our little coffee machines life
00:08:37.719
how can we tell uh what is it that tells us that we need to pause and
00:08:42.760
reflect well the first thing first hint is that we had to keep reducing the font size to get that method on the screen um
00:08:50.120
method length is definitely an indicator that things are getting complex uh Sandy Mets author of practical object-oriented
00:08:56.440
development and Ruby has a rule about it she says methods can only have five five
00:09:02.399
lines of code in addition to Method length we also look at method complexity
00:09:07.440
this is a quantitative measurement of how difficult it is to understand a piece of code uh our preferred metric is called
00:09:15.240
the assignments branches and conditionals metric or ABC metric uh the higher the number the harder the code is
00:09:21.160
to understand we use a gem called flog by Ryan Davis to help us calculate this
00:09:26.680
number flog actually is a little bit more than ABC it's got some Ruby
00:09:32.040
specific stuff in it like it penalizes metaprogramming for example
00:09:37.320
um and uh it calculates those scores for every method in the application so we
00:09:42.760
end up with this long list of scores but how do we know what a good score is from a bad score so way back in
00:09:51.200
2008 a guy named Jake Scruggs who happened to write the metric food gem wrote down these numbers for the fog
00:09:57.560
score of a single method now over the years we've used these numbers as our
00:10:02.600
guide and they're actually really effective at helping Drive our code toward Simplicity um so how does our little
00:10:10.760
coffee machine Fair these are his strings not
00:10:16.079
mine so let's go back through the commits in the in the code base and look at complexity over
00:10:21.720
time so our first commit weighs in at a complexity of 5.0 that's in that awesome
00:10:27.360
Zone the Churn number you see see here is the total number of commits to this file that'll become important
00:10:35.399
later all right so adding the conditional Logic for t with all that duplicated code really shot up the
00:10:41.959
complexity now we're at 13.5 we're no longer in that awesome Zone but we're still below 20 and that's
00:10:47.839
good enough so after removing the duplication the complexity dropped way back down to
00:10:54.800
10 which seems like a good thing but this is really where things
00:11:00.160
started to go wrong notice how we've intermingled the two algorithms now it's
00:11:05.720
harder to tell what it takes to brew coffee or steep tea you can't just look at it and say that's what that's what it
00:11:12.519
is so but from fog's perspective the algorithms perspective it's just doing
00:11:17.720
math it can't tell that we intermingled these algorithms it doesn't know that it actually got worse this is a valuable lesson what
00:11:25.200
this tells us is that there's no magic metric that can light the way in every situation
00:11:30.560
um rather there are tools that can inform our decision making so pay attention to how hard it feels to add
00:11:37.079
new features to your application if your intuition is telling you that it's getting harder that it's slowing down
00:11:43.680
it's probably time to pause and reflect on your design all right next we added sweetener
00:11:49.680
this was our fourth change complexity Rose back up to 12.3 we added creamer that took us to
00:11:58.240
14.6 Coco pushed us all the way up to 19.6 that's just under good enough let's
00:12:04.560
see where that last feature puts us all right to top things off we added whipped cream and that pushed the score
00:12:11.040
to 23.4 now if we look at the trend line we
00:12:16.440
can see that complexity has reached a point where it's curving upward that's not a good sign um plus we are over that
00:12:23.199
20 good enough line so there you go there's three ways
00:12:28.399
to know when it's time to pause and reflect on a piece of code method length
00:12:34.240
anything over five is forbidden by Sandy so keep it short method complexity
00:12:40.000
anything under 20 is good enough but anything over 60 is getting dangerously
00:12:45.320
complex and then how does it feel if new feature development is slowing down it might be time to pause and reflect on
00:12:51.600
your design so that's how we knew we'd Reach This inflection point it's time to
00:12:56.920
start thinking about reorganizing this code uh before we try to add any new features to it and that's what fito is going to
00:13:03.360
do right now so we broke sand this rule we
00:13:08.959
crossed over Jake's good offline and we also intermingle three algorithms there that all sunspray dire but is it can we
00:13:16.360
turn this code around yes absolutely let's look at how all right so here's
00:13:22.800
the method as we left it a moment ago now code that's dry too early can lead you in the wrong direction
00:13:29.800
so let's unwrite this code or add back a duplication to see if there are any
00:13:35.000
missing abstractions hiding in plain side now we call this U practice
00:13:41.240
rehydration um but before I show you what that looks like it's important to
00:13:46.680
know that you can't do any of this without tests it's dangerous for the
00:13:52.120
sake of time again we won't be writing them here from scratch but ensuring there are there's good test coverage for
00:13:58.040
your code is the first step towards reducing complexity we really like this tool
00:14:03.920
called Simple go I'm sure a lot of you have seen it before we use it to ensure
00:14:09.040
that we've tested every line and branch of code in our applications as you can see here we have 100% line coverage and
00:14:16.720
that's great but we also have a 100% Branch coverage which means that we're testing both sides of every condition
00:14:24.040
and that is very important when you're going to rehydrate code to make sure that you're not accidentally changing
00:14:30.160
the conditionals it's going to give you that confidence that um you're safe to push
00:14:36.800
your changes up all right so this is where we left the code since we've confirmed now that
00:14:43.800
our tests are backing us up we're ready to rehydrate the code and that looks like
00:14:52.199
this all right obviously this increases duplication but that's what we need to
00:14:58.040
do in order to find this missing abstractions now we can clearly see each
00:15:03.079
recipe and since there's no overlap in the algorithms anymore we can safely extract each one into separate
00:15:10.519
polymorphic classes and that looks like
00:15:16.519
this now as you can see we moved each recipe into its own class one for coffee
00:15:22.240
one for tea and one for Coco the structure has a couple of big
00:15:27.279
advantages each algorithm is now separate from the others that means that if you should ever need to modify one of
00:15:33.240
them let's say to fix a bug or add a feature that's specific to one beverage
00:15:39.800
there's a much lower risk of you introducing a regression um that would affect the
00:15:46.560
other ones that you're only changing that one beverage plus the vend method is much simpler
00:15:53.759
now now you might have noticed that there's duplication between the classes they call to dispens cup heat water and
00:16:00.959
dispense water are all present in every class we actually want that duplication
00:16:07.160
it makes understanding each of the algorithms much easier since the whole algorithm is there for each beverage so
00:16:15.440
we do not want to dry up the algorithms per se rather what we want to do is we want
00:16:21.399
to ensure that there is only one implementation of each of these methods that's really what's meant by
00:16:27.399
don't repeat yourself it is perfect perfectly okay to call a method multiple times it's preferable though to only
00:16:33.199
Implement that method once now Ruby provides multiple options for doing this
00:16:39.120
we could introduce a module put all these methods there uh we could use composition have a class that handles
00:16:44.720
all these and pass them in or we could introduce um inheritance and put the
00:16:49.839
methods in the base class now in this case because we're using these
00:16:54.920
polymorphic classes and because we're unlikely to need these methods elsewhere in the application we would probably go
00:17:01.519
with inheritance just put it in a base class all right we're almost done um
00:17:07.559
there's two remaining problems though the first one is that the vent method has multiple
00:17:13.160
responsibilities and second it's not open closed meaning that you have to go
00:17:18.439
and modify the code in it in order to extend it or add more functionality so let's let's take a look
00:17:24.799
at the responsibilities issue first it's only real responsibility should be to prepare the beverage but right now it's
00:17:31.880
also picking which class should instantiate so that it can prepare the beverage and that's the job of a factory
00:17:39.360
so let's introduce one all right so here we've pulled class
00:17:44.600
instantiation out into a factory class now its only job is to choose which
00:17:50.320
class to build based on what drink was selected now the V method only has the
00:17:56.559
one remaining responsibility which is to repair the Beverages and it is now open closed
00:18:03.559
meaning that we'll never have to modify the V method in order to extend the functionality of the coffee machine the
00:18:11.159
vent method is now open for extension but it's closed for modification however you probably notice
00:18:18.200
that we just move the open close problem to the factory and we introduce another issue
00:18:24.240
there the build method in the factory might return nil ing the coffee machines V method to
00:18:30.760
throw an undefined method error so let's solve that first we're going to do that by introducing the No Object
00:18:37.559
pattern like this so as you can see the factory returns a n beverage by default the N
00:18:44.440
beverage is just a class that um has a prepar method that does
00:18:49.720
nothing as for the second problem with the factory it's still not open close if
00:18:54.960
we wanted to add a new beverage we would have to go modify the if statement and add another
00:19:00.400
one um we're going to solve that by using a different kind of
00:19:05.600
factory so here we've converted the if statement into a hash Lookout now the build method is open
00:19:14.120
close and adding a new beverage only requires us to add an entry to that beverage is
00:19:19.840
Hash plus because the factory is not hash based we actually and this is a
00:19:25.280
nice side effect it goes from 0 then to 01 uh when looking at the beverage class okay so let's take a look at where
00:19:32.960
we are now with the complexity and let's start by revisiting this graph so here's where we left off
00:19:40.240
after adding Whi cream and then the next thing we did was to rehydrate the code now look at how much more complex
00:19:47.760
that was than the dry solution but remember the dry solution
00:19:52.919
was hiding the fact that there was a missing attraction so this is just intermediary
00:20:00.320
complexity so next we pulled the algorithms out into their own polymorphic classes and this dropped
00:20:07.000
complexity significantly and finally we extracted a
00:20:12.440
factory object and now the complexity is lower than it's ever been we're now well back
00:20:19.840
in the awesome range and the V method will never need to change
00:20:25.159
again now let's take a look at all the other classes in the app there are six now the coffee machine has
00:20:32.440
settled down to a very low complexity of 2.2 now coincidentally the factory also
00:20:37.679
weighs in at 2.2 and there are three beverage classes
00:20:42.880
that are all more complex but they're well within the good enough zone so there's really nothing more to do
00:20:49.600
there except that there was a reason why we did all this we needed to add soup to our coffee machine and we wanted to do
00:20:57.200
so without making it more complex X so here's where we left off let's add
00:21:04.000
some soup there you go I'm going to pause and let you take a look at it um so adding
00:21:11.240
soup did not requires to change any of the existing
00:21:17.279
methods you probably notice that we added a new class all the way
00:21:22.320
there and we had to um add it to the list of averages here in the hash
00:21:29.039
so now some people consider this open closed because the only change the factor to the factory was to add the new
00:21:36.279
class to the beverages hash which is configuration if you're not changing uh
00:21:43.440
logic now we're a little Squamish calling this open close because you did have to go and
00:21:49.440
change uh code in that class so we have a preferred method of
00:21:55.240
doing this um and that is actually to have the beverage class register themselves with the
00:22:01.520
factory that looks like this so here we've extended the Beverage
00:22:08.039
Factory class so introduce a register method that the beverage classes can call when they are loaded and this will
00:22:14.799
add the class to the factory and now there's no longer a separate hash that you have to manually
00:22:21.679
maintain in fact this solution is not truly open closed we can expand the functionality
00:22:27.960
for cof machine without having to modify any existing code you just need to add a
00:22:33.640
new class here we added apple cider and nothing else
00:22:39.919
changed now if you wanted to we could also hide that registration bit behind a
00:22:45.120
little DSL let's take a look at what that looks like so here's the little
00:22:52.400
DSL um we just introduced a base uh class we call a beverage and it defines
00:22:59.159
a prepares class method that does a registration for you and now the
00:23:04.240
individual Children of the beverage class can just call prepairs instead of uh calling the beverage factory.
00:23:11.720
register method directly now we really like this pattern first and foremost this is more
00:23:17.880
declarative you can look at that class and it tells you I prepar this um it's
00:23:23.200
also a little easier on the eyes Okay so that was a look at a very
00:23:29.679
small green field application but you're probably thinking all right that's a toy
00:23:35.000
example your applications are obviously a whole lot bigger and a whole lot more complex so how would you know where to
00:23:41.720
start when you get back to work I'm going to hand that over to hours thank you I'm glad you asked um so
00:23:51.279
we've really only looked at at method complexity so far and watching how it grows as the file changes over time and
00:23:59.320
paying attention to it so that we can prevent complexity from becoming painful and slowing us down but you can also use
00:24:05.000
complexity combined with churn to find problems across your entire code base so
00:24:10.400
as we mentioned complexity is the measurement of how hard it is to understand a piece of code churn is the
00:24:16.039
measurement of how many times that bit of code has been changed so we like to think of it like this uh complexity
00:24:22.960
represents how much pain you're going to experience the next time you touch that file and churn represents how often you
00:24:29.240
are inflicting that pain on yourself um so let's take a look at how
00:24:35.720
to use churn and complexity together to evaluate your whole code base to find the areas that need the
00:24:41.600
most attention in your application plot complexity and churn like this using a tool like code climate or the Ruby
00:24:48.760
critic gem uh this kind of churn versus complexity chart was first proposed by Michael feathers who's the author of
00:24:55.039
working effectively with Legacy code uh and we use this kind of chart
00:25:00.320
ourselves to locate the areas in our code base that need an intervention to understand the chart let's break it into
00:25:06.559
quadrants so that we can look at each one down here in the lower left are is
00:25:12.200
the painfree Zone these are files that are easy to change easy to understand
00:25:17.600
and in a healthy application most files live here the upper right quadrant is the
00:25:24.240
painful Zone these are files that are hard to understand hard to change change and prone to
00:25:30.159
regression being aware that these files are in this quadrant will help you make decisions about where to add new code
00:25:37.039
you probably don't want to add new code to these files in fact if you do need to
00:25:42.679
modify these files prefer extracting code out of them over adding code to
00:25:47.880
them when you extract the code you're creating a new file with a turn of one so that's going to pull that down into
00:25:54.279
the painfree Zone um this will create simpler classes
00:25:59.559
throughout the application um so down in the lower right are the low complexity files that
00:26:06.559
change frequently it's possible that these files are actually just configuration data ma masquerading as code like Json
00:26:14.679
hiding in an RB file or something so if so try to move that everchanging config
00:26:20.919
data out of the code into a file that the code can then read as it
00:26:26.960
needs finally the upper left quadrant is uh High
00:26:32.880
complexity files that rarely change uh this is what likely what Sandy Mets
00:26:38.039
refers to as an Omega Mass an Omega mass is a big is a file with a big scary
00:26:43.559
algorithm that never needs to change uh sy's advice in this case and
00:26:48.919
we agree is that you should just leave these things alone don't touch them they're not
00:26:54.200
causing you any continued pain because you're not touching them and if you do screw around with them you're likely to
00:27:00.600
introduce a blood so just leave them alone these quadrants are helpful to think about but reality looks more like
00:27:10.720
this now the red line represents the pain threshold anything in that pink zone is going to be resistant to change
00:27:17.840
and prone to regression this file is in need of the most attention it's super
00:27:24.080
complex and it's being modified all the time extracting hid abstractions from
00:27:29.200
this class will simplify the entire application but there's no need to
00:27:34.399
tackle all that complexity at once try improving the code a little bit each time you touch the file by extracting
00:27:40.840
something also you may want you may not want to start with that file it's super
00:27:46.519
complex and uh maybe it makes more sense to start over here this will give you a chance to practice some of the
00:27:52.399
techniques we showed you like rehydration um and self-registration uh
00:27:57.600
without having the pressure of working on that most complex file in your
00:28:02.640
system so that's the story of our little coffee machine how complexity snuck in
00:28:08.600
how we recognized it and how we removed it let's wrap up with some key takeaways
00:28:13.640
and a bit of homework so there are three things we want you to take away from this talk
00:28:19.360
first complexity will sneak into your application you you gotta it happens one
00:28:24.559
commit at a time so you've got to be vigilant pay particular attention to conditionals in your code they could
00:28:30.919
represent objects trying to escape your method and remember dry is about method
00:28:36.640
implementation not invocation as my friend Josh Clayton says don't make your code so dry that it
00:28:46.440
shaves second you can recognize complexity before it becomes painful
00:28:51.559
keep methods short watch your complexity and pay attention to your intuition if
00:28:56.840
methods are longer than five lines or your flog scores are over 20 or it just feels slower than it used to it's
00:29:03.159
probably time to pause and reflect on your design third you can back away from that
00:29:09.399
painful complexity leverage polymorphism and factories to enable you to add new features to your application without
00:29:16.320
having to change any existing files rehydrate your code or reintroduce some
00:29:22.519
duplication to help identify missing abstractions that can be refactored into the polymorphic classes
00:29:29.840
so those are the three takeaways now here's what we want you to do with that information first find out what your
00:29:36.600
average method complexity is using flog it's a simple gem it's got a command line you you guys can figure it out not
00:29:44.240
going to show you how second find out which class has the most churn in your
00:29:49.519
application it's a churn it's a gem same thing you can figure it out uh and then
00:29:55.760
finally we want you to figure out which class needs the most attention in your application now show of hands how many
00:30:03.039
of you already know which class that is I bet more of you that actually know that's the one that's the problem class
00:30:10.480
um but go ahead and confirm your suspicions with the tools and then finally let us know what you find here's
00:30:16.519
how to reach us feel free to write tweet or toot uh actually you're more likely to get an answer if you to we don't
00:30:22.840
really do much Twitter anymore uh you can also subscribe to our blog if you're so inclined
00:30:29.240
um uh also if you want to walk your way through the little coffee machine application you can find it with tests
00:30:35.120
on GitHub here uh plus you can check out our other personal projects while you're there including Ruby flog which is a vs
00:30:43.240
code extension that'll put the fog score for the selected text the current method or the average score for an entire class
00:30:49.880
down in your footer all right one last thing before
00:30:55.000
we go we did mention that we are from Cisco morocc and that we are probably the largest
00:31:00.399
rails app you've never heard of um we don't build coffee machines but we do build internet machines for coffee
00:31:07.799
lovers both Starbucks and Pete's Coffee use moroi devices to put their customers
00:31:13.320
on the internet uh our 17-year-old rails monolith has over two million lines of
00:31:19.240
Ruby code it's very old yes is also super complex yes and it handles
00:31:26.399
billions of requests per day and it supports a multi-billion Dollar
00:31:31.639
business um if you're interested in solving really hard problems related to code complexity software design and
00:31:38.919
large scale rails deployments you should come chat with us we're always looking for more great
00:31:44.600
rubyists all right here's a list of our references and influences uh feel free to take a
00:31:50.600
picture uh or the slides will be up soon I'm sure uh if you have any questions
00:31:55.919
come find us or drop us a note and that's it thank
00:32:01.840
you thank you so much to Becky and
00:32:08.279
SP yes is there like a a DK algorithm or some way of like if you have a very old
00:32:14.480
uh code base like the one I just mentioned 17 years old you're going to have some files that just have tons of
00:32:21.600
commits um the way uh we usually run this analysis is we look at the last six
00:32:27.399
months and that gives us a better picture of what code is changing right now if something doesn't show up in that
00:32:33.639
window of time but it has like tons of turn it's probably an Omega M probably was changing at some point and now it's
00:32:39.840
settled but you can change the the window of time depending on your code base yeah so the question was uh is
00:32:47.840
there a tradeoff with um focusing on method complexity versus the overall
00:32:53.200
application complexity uh and I will say uh when you look at the method complexity like what
00:32:59.519
am I holding in my head right now right now I'm focused on that method that I'm writing so that's where I want to focus
00:33:05.320
on the level of complexity when I get to understanding like we we broke those
00:33:10.399
classes out into polymorphic um beverage classes each one of those was easy to understand in its
00:33:17.039
own right and overall the application the total complexity went up because we added like code around those things
00:33:24.039
instead of an if statement now there's a method and a and a class declaration and all that so the total complexity of the
00:33:29.320
application if you measure it with flog went up but the the thing I'm holding in my head right now that I'm working on
00:33:36.399
right now is always a method it's maybe a class uh and in those particular cases
00:33:43.880
um we find it really a lot easier to understand uh when we focus on the method complexity in fact we don't even
00:33:49.720
look at total complexity usually we look at average method complexity within a class that gives us the abil the ability
00:33:55.960
to um like focus on what we're actually thinking about right now admittedly more
00:34:02.919
classes more smaller things than your like we have this argument at work sometimes with some of our
00:34:09.119
um less um I don't know there's folks there's
00:34:15.119
Folks at work who are very much interested in seeing the entire application in one method like they just
00:34:21.040
want to see the whole thing I just want to see it all and get the whole thing in my head well there's two million lines of code you're not going to do that it's
00:34:27.399
just not not going to happen so I'd much rather be able to get the class in my head first so I want small classes and
00:34:34.480
and really the thing that I'm working on right now the method so yeah that answers your question one one thing I
00:34:40.240
would add is that uh like we mentioned this is a tool uh that gives you information on your code like it
00:34:47.200
it's it's not the only metric that you should look at so if it if you find
00:34:52.800
yourself writing small methods and you have multiple classes but you still feel like making change is hard then you
00:35:00.040
should listen to that intuition and maybe think about how the the objects are organized there are other tools that
00:35:05.520
you can use to um graph like a dependency uh tree of your objects and
00:35:11.359
maybe take a look at that like do they have too many dependencies um you're right there's a
00:35:16.480
whole other aspect of like the system at large and how it can become more
00:35:22.800
complex one more so the question was are there any tools that would help you identify
00:35:29.000
complexity that's coming not from the the method complexity but from the the multiple layers of abstraction that you're introducing um I think the
00:35:37.200
dependency graph is helpful um I don't remember the name of the I I'm trying to
00:35:42.280
to remember the name but I'll putting this SL Channel later there is a tool that we've uh used fun fact it doesn't
00:35:48.079
work with our our application is so large that when you try to it just explodes like it literally it
00:35:54.599
has an animation where it tries to like be cute and move around around the classes ours just goes
00:36:01.079
like so we've had to like section off code and see like okay what are the business or here but I can post a link
00:36:07.800
to the tool we've been doing this a while like I said we've been working together for 10 years we have over
00:36:13.800
abstracted things it has happened more than once we we didn't learn um and
00:36:20.160
usually the best indicator of that is when the coworker who doesn't who didn't write it with you walks over and says
00:36:25.400
what the hell were you thinking so that's always the best indicator um anyway um thank you very