00:00:17.080
I'm Jim W I'm the chief scientist for Edge case and I am here to talk to you about writing solid Ruby code but first
00:00:25.320
I have a disclaimer this talk is not about s so
00:00:31.239
ID after I made the I made this talk proposal many many months ago and as it
00:00:37.280
was accepted and as I was doing the the work on the talk I realized um about two
00:00:42.760
or three years ago I did a talk called um writing solid Ruby or or solid R
00:00:50.800
solid Ruby was the name of the talk and now this talk is called writing solid uh
00:00:56.440
Co Ruby code so this is not about the solid principles uh single responsibility open
00:01:03.600
close list cough interface segregation or dependency inversion this is not about this so if you came here to hear
00:01:09.960
about the solid principles you might want to give your seat to someone in the back who's
00:01:15.240
standing sorry to disappoint this is about something entirely different but
00:01:20.400
I'm going to start with a question actually I'm going to start by starting my timer
00:01:30.520
since this is the first time for this particular talk I have no idea how long it's going to run so I want to carefully
00:01:36.240
monitor how much time I have left going to start with a question I want to ask you how confident are you in the code
00:01:42.320
that you write in other words if uh your manager came up to you and said um
00:01:47.479
they're going to deploy the code tonight into production and you knew it was coming up
00:01:53.640
you're ready for that how will you how well will you sleep at night knowing that your code is going into uction
00:02:00.799
overnight are you going to have your phone right there by your bedside uh just in case they call are you going to
00:02:06.920
sleep soundly um I hope you're sleeping
00:02:12.879
soundly but I know that I don't always do that and I want to strive to have
00:02:19.160
more confidence in my code that I write so I thought well let's let's do a talk about how to do that this is kind of
00:02:25.319
inspired by some recent projects that we've taken on some some rescue project some other just inherited the code base
00:02:32.760
from somewhere else and it's a code base I'm not familiar with I don't know the
00:02:37.959
tests weren't quite running everywhere and and we just didn't have a lot of confidence in the code and and and I was
00:02:44.080
wondering how can we fix this how can I get to a place where I am confident in the code base that I'm working with
00:02:51.200
now this is from the preface of the book the uh Tech the program by Donald nth
00:02:57.680
you might have uh heard of n maybe um he was writing an
00:03:04.959
essentially an encyclopedia of all computer knowledge and about then it was
00:03:10.040
a second or third book into it he decided that he didn't like the way uh books were types set and he took off
00:03:16.239
like 10 years to write a types set setting system for technical books
00:03:21.519
called Tech he wrote the book wrote the program then he went back to writing his Encyclopedia of software knowledge so
00:03:27.120
he's back to doing that again um in the preface to the book he says I believe
00:03:32.159
that the final bug in Tech his type set setting system was discovered and removed on November 27
00:03:38.799
1985 but if somehow an error still lurks in the code I shall gladly pay a
00:03:43.879
finder's fee of $20 48 to the first person who discovers it
00:03:50.159
and this is twice the previous amount I plan to double it again in a year you see I am really confident wow
00:04:00.280
now being a programmer you recognize that number $20.48 as he probably paid a penny to
00:04:07.879
the first bug two cents to the second bug 4 cents to the third 8 cents 16
00:04:13.720
cents so this is uh so we can calculate how many bugs
00:04:19.479
he's found in his code right and that's what would be what 10
00:04:25.639
yeah 10 bugs so he doesn't think there are 11 bugs and he's willing willing to put money down on it and he's willing to
00:04:31.680
double it um on that so wow that's uh that's impressive I would love to get to be
00:04:39.320
that confident in my code so think about that question think about the level of confidence in your
00:04:45.160
code I'm going to do an aside for right now I have found that in my programming career there are a handful of books that
00:04:52.440
I can just rattle off that have radically changed the way I develop code
00:04:58.520
and it has varied over over the years from the very Basics to more modern and you know how many people can do that
00:05:04.520
right now how many people have read a programming book that really changed the way you develop okay um give me
00:05:11.720
examples M talk best practices I heard refactoring camel book The Camel book
00:05:18.280
The Pearl book okay yeah robust practices robust practices the pr
00:05:23.680
pragmatic programmer book I heard someone say code complete code complete oh remember that one remember that one
00:05:29.400
cuz I'm not going to talk about it going to mention it but we're not going to talk about
00:05:36.840
it testen development test driven development okay very good um there are
00:05:42.199
a handful of books and here are the top five in my mind the pragmatic programmer
00:05:47.400
should be a footnote on this as well as well as a very early one I remember called elements of programming style has
00:05:53.400
anyone ever read that one yeah Glenn has excellent book yeah yeah um that one
00:05:59.639
probably should be up here as well but that was that's a little little bit older but these are kind of four or five books that have really really changed
00:06:06.360
the way I develop programming first one was software tools and I got to tell you a little story about this one um I was a
00:06:13.599
very new programmer just out of college maybe working in the industry for about a year or two and I had a mentor named
00:06:21.120
Sheldon Jordan and Sheldon was want to come by my cubicle and plop a book down
00:06:26.240
on my desk and say here read this and I remember remember reading an very early Grady Bush book on um adaah at that time
00:06:35.199
frame and he dropped off this book one day called software tools I said okay this is interesting so I started reading
00:06:41.599
this wasn't much later that Sheldon moved on to greener pastures and left the company I was working with so we
00:06:47.000
were kind of on our own um someone was going through Sheldon's office and he said hey there's a tape back here and
00:06:54.840
it's called rat four um now we named named all our
00:07:00.479
programs at this particular job with fourl names and a number so there was
00:07:06.000
raid three uh Trace without the e five you know so rat four was almost like one
00:07:12.800
of our programs but not quite because it only had three letters in a number instead of four letters number so they didn't know what to do with this tape
00:07:18.599
and they said Jim does this ring a bell with you I said rat four rat four what
00:07:23.840
software tools is about is taking your programming environment and changing it
00:07:30.319
to be good for you these guys wrote in Fortran and yes I was doing Fortran at
00:07:35.599
the time by the way that is a deep dark secret that doesn't appear on my resume so you're sealed to secrecy
00:07:43.800
okay I was doing Fortran how many people have done Fortran in here okay okay
00:07:50.720
really wonderful modern language maybe not so much especially when I was using
00:07:56.159
it uh what they did is they took Fortran and wrote a pre-processor that changed essentially
00:08:03.720
what was C like code and compiled it down into Fortran they called the pre-processor rational Fortran or rat
00:08:11.199
for uh ratf R the tape was labeled R the
00:08:16.599
number four so that uh that's where rat four came from rational Fortran and they go and then they develop all kinds of
00:08:23.039
tools to use uh to help you program they wrote essentially grap or and um not a
00:08:29.720
but grap and and some uh directory man manipulation things and that inspired me
00:08:35.000
to take charge of my environment and start modifying it to work the way I wanted it to despite the fact I was
00:08:41.120
working on a huge Mainframe machine it didn't really didn't have a a decent file system and we were working in
00:08:47.720
Fortran and but by using the ideas in that book really changed the way I approach software going to skip the next
00:08:54.200
book uh jump down here to object-oriented software construction um this this one really
00:09:00.600
really opened my eyes on a lot of different things about object-oriented design Bertrand Meer is a brilliant guy
00:09:07.200
and I don't agree with everything he says in this book but where I disagree I always make sure I stop and think very
00:09:13.920
very carefully essentially this book is all the reasons he developed his own
00:09:19.360
language called Eiffel and anybody program an Eiffel not very many I
00:09:24.880
actually was doing Eiffel on the side right before I picked up r Ruby I kind
00:09:30.560
of stopped doing Eiffel and start picked up Ruby right about the same time but eiffel's cool feature was concept called
00:09:37.920
design by contract and where you specify the preconditions and postconditions of
00:09:44.120
every method you write and it's code and when you generate the documentation for your library it pulls out the the method
00:09:51.360
name it pulls out all the arguments and it pulls out the preconditions and postconditions for your library
00:09:56.480
documentation a well-written Eiffel Library it's a wonder to read its
00:10:02.000
documentation because it's very clear and very succinct on exactly what that method does great programming idea uh
00:10:09.680
this is easily the most expensive book on this list it's nearly $100 even a day
00:10:15.120
for paperback um early 2000s I put refactoring and extreme programming
00:10:21.440
explained kind of together because this really changed the way I developed again for the first time I was excited about
00:10:26.720
the process of doing software not just just about the writing software but the process involved in it and it really
00:10:32.760
changed the ideas I had on that um I'm not going to go into that we still talk
00:10:38.720
about XP and and test driven stuff so I'm not going to go deep into that today because I think that's kind of saturated
00:10:44.720
I want to go back and talk about this other book called writing solid code
00:10:49.839
this book is um there's some interesting facts about this book that I want to share
00:10:55.519
with you okay um first of all it's written by Microsoft
00:11:04.880
press yeah I I really just was really clearing my throat that had nothing to do with
00:11:11.200
Microsoft in fact is there a glass of water back there someone I would really appreciate if someone could get me a glass of
00:11:17.800
water back there that would be awesome I appreciate that written by Microsoft and and I'm not a big fan of Microsoft but
00:11:24.200
I'm also not a big hater and it turns out that Microsoft is actually pretty good at finding good books to write in
00:11:29.880
fact there are two books by Microsoft press that are kind of a Forefront in in
00:11:36.440
in in my knowledge here oh thank you very
00:11:43.079
much the other interesting thing is these both of these books were written by Steve one was Maguire and the other
00:11:50.200
was McConnell they were both published in
00:11:58.000
1993 and one of course is writing solid code which I'm going to talk to you about today the other one was code
00:12:04.920
complete and it wasn't until I put these two pictures up here I realized that's the covers of both books are amazingly
00:12:13.560
similar the main difference between these two books are the number of
00:12:21.279
pages when he said code complete he meant it writing solid code in fact I have it
00:12:28.880
over here here let me see if I can pull it out of my bag writing solid code is probably about 200 Pages or so quite
00:12:36.839
digestable very readable and it was written by Steve Maguire here it is
00:12:42.600
written by Steve Maguire and it was inspired by the fact that when Maguire came to Microsoft he came
00:12:49.320
in a time when the development group was smaller and the practices in place were
00:12:55.760
really tuned towards writing good solid code with few bugs I don't know how he
00:13:01.399
found that spot in Microsoft but evidently there was this Enclave right there and he discovered that as new
00:13:09.279
developers came on the team that they were not adopting the habits that the
00:13:15.199
original team had and they were losing out on a lot of the knowledge that the original team had and he decided to put
00:13:20.440
together a book upon those practices and kind of call them out and we're about 250 Pages that's
00:13:27.560
what it is so he put together a book and there's
00:13:34.880
seven chapters and the talk is going to be structured around these seven chapters as I Wasing this book for the
00:13:41.480
talk I just thank you as I was rereading the
00:13:49.040
this book for the talk today I discovered that a lot of his specific
00:13:54.279
advice just is not applicable to Ruby programmers he was a CA developer and a lot of the things he wrote were specific
00:14:00.839
to C because man if you're not careful in C you can really dig yourself into a hole so he has lots of advice on how to
00:14:07.839
make sure your code is working correctly uh how to make sure you don't have memory leaks how to make sure when
00:14:13.440
memory moves around your program doesn't change um so a lot of the programming specific stuff is a little out of date
00:14:20.000
for this crowd however his general advice and his General attitude is really right on so the talk today is
00:14:27.199
going to be a little bit of his advice a little bit of Mind advice and a little bit of community community advice that I
00:14:33.120
got some feedback from some people so let's go ahead and hit that let's start with assert
00:14:38.680
yourself now um he makes a big deal about this in the book and I remember when I was doing C this was a big deal
00:14:45.600
to me too and adopting it really changed the way I did what is he really talking about is if you're writing a
00:14:51.040
method you want to make sure that the program is working correctly so they
00:14:56.199
have these macros called assert that just asserts that something is true and
00:15:01.320
if you reach that point in the code and that condition is not true the program dies fails horribly and that's a good
00:15:08.399
thing in development because if you ever call mem copy and you have null pointers
00:15:14.480
in there you want to know about it because that is a bug and it must be
00:15:19.800
fixed um the other the second assert is more about a relationship make sure you're not overlapping memory copies
00:15:25.720
there that's a little bit different but the key is that that is a m and when you compile it for production
00:15:31.079
mode that macro goes away and doesn't affect the performance of your code so your code base in testing and in
00:15:37.639
development have a lot of these consistency checks in them make sure things work
00:15:45.399
right so do asserts make sense in Ruby and I'm going to claim not so much first
00:15:51.440
of all let's kind of change this to a ruby is kind of assert and I made it a block so that possibly that in
00:15:59.000
production mode you wouldn't even have to execute the block um but what are we doing we're
00:16:04.959
checking to see if something's nil Ruby kind of does that for you and if you let Ruby do the check
00:16:11.880
it'll give you a nice exception that tells you exactly where the error occurred and and where it is now you
00:16:17.880
might not get it at the top of the routine but it will eventually happen if it matters so the certain not nil kind
00:16:24.199
of tests are not nearly so important um and even if you come into
00:16:30.160
that or if you make it so you don't execute the block at runtime you still got to build the block and you got to
00:16:35.399
pass it in you got to make a test to see if you're uh in production mode or not so there's there's runtime overhead even
00:16:41.639
in this assert version here so let's say we do something more
00:16:47.120
than just null checks let's say well okay we don't have to check for null Ruby does that but but but checking to
00:16:53.839
see if we got the right type of argument that's still a good thing I'm going to say not so much if
00:16:59.759
you put checks like this lited throughout your code you've really limited the way that
00:17:06.679
um other people can use it for example here we're checking to make sure that this target object is a string uh I I
00:17:14.480
wrote XML Builder and it takes a string argument but the only method I use on it is the uh Double Arrow insertion
00:17:21.720
operator so I don't really care if you give me a string or a file or anything
00:17:27.400
else you can even pass in array and that will still work so explicit type checks
00:17:34.120
inhibit the flexibility of Ruby in duct typing and people say okay that's true
00:17:40.440
you want flexibility that's what Ruby's good for so you don't want to do explicit type checks but maybe maybe we
00:17:45.480
can just check to see if it responds to the operator you want I call this chicken
00:17:52.520
typing because you're afraid to let Ruby do what it wants to do so I'm not a big fan of chicken typing either
00:17:59.360
so asserts not so much but let's go back to the principle right what is the principle behind putting assertions in
00:18:07.360
your code base essentially you're doing unit tests
00:18:12.640
as the codes run now remember this book was written back before XP became popular before unit testing became the
00:18:18.799
universal thing that everybody does right everybody does right sometimes I we talk a lot about
00:18:25.679
testing but I'm not sure everybody actually does testing but that's another topic so what uh what we put them in is
00:18:32.960
to ensure program correctness especially when we change and refactor we want to make sure the code still works so
00:18:39.440
there're they are there to ensure correctness we write tests I was so
00:18:45.760
excited I got to write this in like a 180 Point font because I think this is important
00:18:52.480
the number one thing you can do to ensure correctness is to properly test your code with repeatable unit tests
00:19:00.400
with um do TD or bdd that's the number one thing if you're not doing that at
00:19:06.039
least write unit tests write integration tests to make sure your entire system
00:19:11.400
works M write functional tests that ensure your code does what the customer
00:19:17.000
wants it to do that's the difference between functional and um integration
00:19:22.600
tests um who's heard of mutation testing yeah I know you
00:19:30.360
have there's a uh wonderful Ruby Library called with uh heck all right yeah yeah
00:19:37.120
heck all that goes into your code base and modifies your code and then runs a
00:19:42.679
unit test the theory being that if you can change your code and the test still
00:19:49.000
pass then your code isn't well tested enough so it goes in and it will change
00:19:54.360
like constants to different constant values it will invert the value of a uh
00:19:59.840
if test to be an if not test it will uh replace values with nil and see if it
00:20:05.280
still works and if your test still pass then your tests are not robust now the problem with Heckle is that will tell
00:20:11.360
you one of two things either that you have poorly tested code or well if you if you pass Heckle in other words any
00:20:18.360
change you make breaks the code that will tell you that either a you have well tested code or B your code is so
00:20:24.799
interdependent that everything breaks whenever you change one thing one of those two things so that's mutation
00:20:30.720
testing fuzz testing is similar but instead of changing code you're changing data you are um if you're like a web
00:20:38.400
server and you're accepting outside web requests you can't trust the data coming at you so fuzz testing is taking that
00:20:45.080
data and changing it kind of random ways and just hitting the server with all the wild and crazy variations that you can
00:20:51.480
possibly think of you know extra long packets Too Short packets uh wrong size packets where the size of the packet and
00:20:57.600
the actual data mismatch all kinds of bad stuff throw it at your server and see if you can still uh survive that's
00:21:03.960
mutation testing all good things to do and if you want good robust solid code
00:21:09.159
this is number
00:21:14.559
one I have used 20 minutes of my talk and if I stop now you will go away a
00:21:20.320
more confident programmer I'm going to just say a couple more things about testing because I don't want to dwell on
00:21:25.960
this too long some testing advice number one think of tests as
00:21:31.279
specifications now I know there's this whole rspec movement that says oh we use rspec so we're writing specs not tests
00:21:38.480
well maybe just merely using our spec isn't
00:21:44.039
enough to actually make you write test or write specs instead of tests you've changed the vocabulary but unless you
00:21:50.120
change the way you write those tests or specs you haven't really accomplished much much except you're using a
00:21:56.720
different Library the key thing is to think of them as specs and what you want to do is think of two things do the
00:22:02.919
specs cover the code in question do they cover all the necessary behaviors of
00:22:09.039
that code in other words if I were to pick up that Library if I were to look at the spec the spec has what I want to
00:22:15.960
do in it and covers all those bases are they necessary do they cover the necessary aspects of the code the second
00:22:22.600
thing is are they sufficient actually I got those totally backwards sufficient means do they cover
00:22:30.200
everything in the code necessary means does it only cover what's needed in the code um I find a lot of tests are
00:22:38.840
unnecessary they test things that you don't care about uh testing private
00:22:45.200
methods the number one thing if I'm using your library I don't care what
00:22:50.320
your private methods are and there doesn't need to be a specification for a
00:22:55.360
private method now the code has to be paave and that private method has to
00:23:00.600
implement whatever the specification says but I do not specify private Methods at all that's sufficient
00:23:07.000
necessary means do you cover everything or do I cover only the
00:23:12.840
code I get them mixed up but they're there necessary and
00:23:18.679
sufficient oh garbage slide I mentioned this book earlier and
00:23:25.960
I want to mention it again because designed by contract is exactly that idea what does your method need to run
00:23:33.039
that is the preconditions what does what must be true after your code has run that is the
00:23:39.679
post conditions and designed by contract is the most clearest explanation of
00:23:44.720
those Concepts that I have ever seen and this is the book to read to get on board with that okay the other testing advice
00:23:52.279
is is I say make the specifications or tests as readable as you can possibly
00:23:57.919
make them and I've got a little self-serving advice here I'm going to pimp one of my own libraries called
00:24:04.480
rspec given and just a little run through of what it looks like this is in
00:24:10.559
arpec so we've got context just like arpec but we also have these given things and in this particular test this
00:24:17.360
is a test from um or a spec from the Gilded Rose code Kata which is a kind of
00:24:23.440
a simulated business logic type of Kata where we got a lot of arbitrary business tools concerning items kept in inventory
00:24:31.640
and how the quality of the item in inventory changes over time so given an
00:24:37.480
initial quality of an item given an initial must sell in so many days item
00:24:43.600
and given an item initialized with a name and those two other things given
00:24:48.760
all that when I call update quality the beauty of this is this is the code I am
00:24:55.720
testing I don't have to pour through before blocks I don't have to pour through it blocks I know exactly what I
00:25:02.559
am specifying and that's in the when block the Givens are all the things that are
00:25:08.679
there that I assume are available for the testing so given these things when I
00:25:14.360
do this what comes next then so these are nested contexts
00:25:20.760
within this so this is the outer context here this is a nested context so given
00:25:27.200
those three items and when I call update quality when I have a norm ah look
00:25:33.880
here's another given given a normal item that is before the cell date then
00:25:39.799
this should be true the quality should go down by one when I update the quality it goes down by one for normal
00:25:48.120
item there's the nested given there's the then here's another context and a
00:25:54.919
look this is interesting let me oops back up so I can give new Givens in
00:26:01.559
nested contexts and I can override existing Givens in a nested context
00:26:07.960
which means I can vary only the thing that changes the only thing that changed between this
00:26:14.279
test and that test is that the sell and date is different so I can easily see
00:26:20.240
what's different in the specs I can easily see what the expected outcome is the guys in the office love this in fact
00:26:26.080
they tell me they won't do another project without this fact they thank
00:26:33.520
you bit like girkin yeah yeah it's the given and then idea came from cucumber
00:26:38.559
that this is kind of just pure Ruby no DSL type stuff just pure Ruby and blocks
00:26:44.200
and actually it's a really thin layer on top of our spec um the Givens are
00:26:49.600
essentially lets and then is essentially an IT block or specifi block and the um the W are
00:26:58.320
before blocks no it's not much before more than that so it's just a little syntax
00:27:03.480
coloring on top of that I really like it makes the test very readable let's move
00:27:17.520
on I thought I was going to run short I don't think I will fortify your subs systems in rails code you have a lot of
00:27:24.760
things that look like this this is in a application that monitors my stuff so I
00:27:31.600
have a stuff controller and in the show show action on a stuff controller I grab
00:27:37.640
stuff from pams now where does pams come
00:27:42.760
from a URL yeah so you typed in the URL so it comes from there and that three
00:27:50.240
there is essentially turned into the Pam ID and passed in but that's a URL I can
00:27:55.279
go into my browser and I can type any URL want to into my browser what if I
00:28:00.480
typed a 45 instead of three and this came in and all of a sudden I'm now
00:28:06.440
browsing other people's stuff
00:28:11.799
so what you really want to do is this you want to scope your stuff
00:28:18.320
finding to the current user if 45 is not in the list of stuff
00:28:23.640
that I have then it will not show and you will get an error and it will be displayed so fortify your subsystems
00:28:31.000
means be afraid of stuff from outside your
00:28:37.720
software don't trust things coming from the outside and that can be things like user input like we saw here URLs are
00:28:43.640
essentially user input um the database although you might be writing a
00:28:49.519
rails app that controls that database there's nothing preventing someone else from going into that database and
00:28:55.120
changing the code with a SQL statement changing the data with a sequence SQL statement and making it invalid so be
00:29:03.000
aware stuff coming in from the database is not entirely trusted either uh that
00:29:08.080
is a good source of um uh cross-site scripting
00:29:13.679
attacks by putting uh a little bit of JavaScript in something supposed to be displayed on a web page comes in from
00:29:19.600
the database you trust it you throw it up and Bam you got problems um other
00:29:25.159
software if you are writing your system in different subsystems that communicate with each other over a message bus or
00:29:31.919
through a reddis q or something else don't trust the data coming in because that data is very easily corrupted it's
00:29:38.799
outside your software you have no control over it so fortify your subsystem by checking the data very
00:29:44.519
carefully that comes in don't have much more to say about that except be aware of that think about
00:29:50.840
that when you're handling data now like I said I'm not a big one for putting a lot of checks in my code but when the
00:29:57.000
data comes from outside side that's a that's a different item that's that's when you do your checking within your
00:30:03.000
software not so much stuff coming in yeah check it very carefully
00:30:09.919
yeah actually yes if you want to ask questions that's fine unless we're running out of time I might speed you
00:30:14.960
along do you ever use the taint flag taint is a big club and I find it
00:30:22.159
hard to control and I generally don't use it so I generally get by with it it's a great idea I'm just not sure how
00:30:29.360
practical it is in in um long run although rails is kind of doing something like that today with it safe
00:30:36.399
HTML strings which I think is a good
00:30:41.799
move I don't know if you know the new rails uh I think since rails 3 or so will um Mark strings whether HTML safe
00:30:49.960
or not and Escape them automatically unless you say this string is safe to
00:30:55.679
put out so it really really goes a long way to preventing um scripting
00:31:01.720
attacks um Steve Maguire recommends firing up a debugger and stepping through your code
00:31:08.320
how many people here use the Ruby debugger regularly okay how many people feel the
00:31:15.720
Ruby debugger is a tool of the devil you know I've never understood
00:31:21.240
that now I don't use the debugger that much but when I need it I really need it
00:31:27.519
and I encourage you if you're a kind of anti- debugger pick it up and start
00:31:32.760
using it and give it a try um it works great with Ruby 1 19 today uh I've got
00:31:39.639
it set up so that in emac I can fire it up and then I get the split screen where I see my source code and the debugger
00:31:45.720
commands in the bottom and The Source on the top and that works really really nice don't use it all that often don't
00:31:51.480
use it like He suggests um Steve says run all your code through the debugger and watch a step I
00:31:57.919
feel that if I'm doing tdd I've got a sense of that already so I don't feel the need for debugging but it is a tool
00:32:04.279
to be used I give you a two piece of devices Ruby debugger is the one however sometimes your problem is not so much
00:32:10.880
which logic steps I'm doing but what is the state of my data right here there's
00:32:16.320
a wonderful Library called pry that you uh require the pry library in your code
00:32:22.200
wherever you want to see what's going on you put in binding.pry you run your test
00:32:28.480
and it'll pop you into an interactive IRB session and you can query the state
00:32:35.039
of all your objects you can CD into other objects and query their internal
00:32:40.919
State you can get listings of methods you can run shell scripts you can do all kinds of wonderful things and I'm no
00:32:47.679
expert on pry but even the little bit I know makes it worthwhile I've started using pry to do data exploration in my
00:32:54.159
running code and it's a really easy thing to use so those two things I recommend you uh getting to know those
00:33:00.360
two tools very well the idea though is to know your code know what's happening through your tests through using pry
00:33:06.880
through using the debugger make sure you know what each line of code does and how it
00:33:16.880
works I thought this would be a really fun section to do candy machine interfaces there's a
00:33:23.559
story behind this Steve says he got the name of this chapter because at their place of work at Microsoft evidently at
00:33:30.320
least when he was there they have a free pop but you have to pay for the candy so
00:33:36.240
you get to the candy machine here and you say oh I want this Twix barar here um it's a buck 25 so he goes over to the
00:33:43.600
numeric pad and then instead of entering the 147 which is the number to select it
00:33:49.159
he already has the 125 number in his head and he punches that in instead and
00:33:55.519
out pops a bag of chips jalapeno chips chips is what he called them instead of
00:34:00.960
your delicious Twix bar candy machine interfaces are apis
00:34:07.679
where it's too easy to do the wrong thing how many people have run into
00:34:13.760
those kinds of interfaces yeah now I thought it'd be really fun to
00:34:19.240
bring up some code and make fun of it and all that but all of a sudden I had a mental block and I couldn't find a really
00:34:25.480
really really good example of this but I saw a number of people raise their hands so find me afterwards and I will update
00:34:31.320
this with your examples um his examples are of course from ceve which is full of bad
00:34:38.359
interfaces a getar returns an INT get Char returns an
00:34:46.919
INT and it's important you know it returns an INT because if you put the value in a character variable when you
00:34:54.159
hit the end of file which is negative one instead of a a negative one in the character variable you
00:35:00.720
store FF hex which is a valid asky character so you lose the fact you will
00:35:08.240
never hit end defile if you store that in a character realic is an interesting one this little piece of code here using
00:35:14.760
realic realic takes an existing buffer you've maled from the Heap and resizes
00:35:21.040
it and it will return you a pointer to either the original buffer if the buffer
00:35:26.599
is already big enough or to a new buffer if it needs to re you know needs to give
00:35:32.920
you a new bigger buffer it will also okay so so so that's a description of
00:35:38.000
that what's the problem with this code it's that third condition I was
00:35:45.280
about to mention and he didn't want to give it away third condition if you're out of memory it returns nil null I'm
00:35:51.920
sorry we're C null so assuming that PB buff
00:35:58.280
is the only pointer to your existing buffer if you're out of memory you've wiped out the only pointer you ever had
00:36:04.640
to that buffer and you've leaked memory what a horrible horrible
00:36:11.760
interface candy machine interfaces yeah let's find some good um Ruby instances
00:36:18.520
of that to make fun of that would be nice um I asked on Twitter what PE what advice people had a day or two ago and
00:36:25.440
someone nailed it exactly I also designed my class so easy to use right and hard to use wrong that is the
00:36:31.200
essence of avoiding candy machine
00:36:37.960
interfaces you expected Tom Cruz didn't you this is what happens when you put
00:36:44.400
copyright safer reuse on your uh search
00:36:52.800
criteria how many people think of risk when they're writing their code
00:37:00.079
a hand full of people do I would say most developers don't stop to consider
00:37:05.560
the risk of getting their code right or wrong when they start writing it and they just don't give it much
00:37:13.440
thought so wouldn't it be nice to have a command line message like
00:37:21.680
this actually we do how many people have used this like
00:37:28.640
curo am I saying that right okay a couple of hands what sorry Cyro thank
00:37:35.319
you what this does is com computes the maab cyclomatic complexity number for
00:37:41.800
all the methods in your project now what is sounds sounds really fancy it's not that fancy it's not that complicated uh
00:37:48.720
a number of years ago I read this back in the 80s so this is an old old old metric essentially the research they did
00:37:55.400
said if we take and this was done before TR programs remember don't mention
00:38:00.720
that and you look at the flow graph through the program and here we see that
00:38:06.440
uh we got step one zero step one then two three and four that's probably an if branch and down here then between seven
00:38:12.640
and 10 there's some kind of looping thing going on with a while loop exit from Seven down to 11 so what you do is
00:38:19.720
count the number of Loops in the flow graph of a method and that is its
00:38:26.520
cyclomatic complexity so this would have a complexity of
00:38:32.160
two actually three because you count the mainline s essentially it's the number
00:38:38.280
of paths through the code base so every method has at least one and if you have
00:38:43.760
a loop that adds another one make it two if you have an if statement that's another one that you would add
00:38:50.040
surprisingly if then lse still only adds one because there's two paths whether
00:38:55.400
it's if and Skip or if and else so um complexity of this method
00:39:05.480
is one unless you get really particular and the paper says you really need to count
00:39:12.720
ores in conditions and add account for that so
00:39:18.359
the basic maab complexity thing would be oops see I told you i' trip on these um
00:39:24.680
is one if you just count the path but if you take the conditions be two most tools give you the simple version which
00:39:31.800
is okay which is good enough for the most part so this has an if else this has a complexity of two uh this is this
00:39:39.040
is from the Rome numeral calculator Kata this has a each Loop here and then a
00:39:46.440
nested file Loop in there so you get one for the main line through and then an additional one for each Loop so that has
00:39:52.480
a complexity of three okay so you can run that program I
00:39:57.920
ran it on rake and got these results um standard rake options
00:40:04.880
complexity of 27 that's pretty high but that's the thing that handles each and
00:40:10.160
every option you can pass into rake so it's going to be high anyways I could reduce that by maybe factoring out some
00:40:17.359
of the if and El's in that method uh but it's not surprising that one's High um
00:40:23.480
the other one Define is actually a package task and yeah that one's pretty complex two that could probably be
00:40:29.319
refactored pass map and string yeah that's a complex one a lot of conditions we're interpreting a a format thing so
00:40:35.960
this is really good at picking out the more complex methods in your project so
00:40:41.440
I was thinking let's run this on one of the projects I've worked on in the past that will remain
00:40:47.839
anonymous and if you go to a person working on that project you ask them what is the worst possible piece of code
00:40:54.400
in this code base and they will immediately tell you it is the dispatch
00:41:03.000
controller the number 79 there does not give you a feel for
00:41:11.720
this so here's a little terminal screen and it's a really small font not to
00:41:17.880
protect the code but to protect you and this now this is just that one
00:41:24.200
method this is not the entire controller this is the one method
00:41:43.280
song we're hitting 40 minutes here so I need to wrap this up pretty quick yeah okay there's the end
00:41:51.480
okay not only is it long it has little tidbits like this buried in it where you
00:41:57.119
have have an return statement immediately followed by a
00:42:06.119
death WTF this has got to be a copy and paste
00:42:14.079
error where they were defining a new method and put it in the wrong spot it just happens to be a spot that never
00:42:20.520
gets executed so no one
00:42:25.839
cares cuz right after that is the very next elsi for this
00:42:37.559
condition dispatch controller I have a feeling everybody's
00:42:43.160
running back to their project now say is is that is that in mine do I have a dispatch
00:42:48.200
controller the scary thing is I've talked to other people in our office and they say oh I've seen
00:42:55.760
worse okay treacheries of the trade now this photo actually isn't from Flickr it's from my
00:43:01.440
own personal Library I took this picture while in Scotland this is up on the Isis of sky and our tour bus guide was taking
00:43:07.280
us back to a little waterfall and I ran into the side I thought it was hilarious because what
00:43:13.720
you understand to reach this sign you must walk this
00:43:22.599
path in order to get close enough to the sign to see what it says it is too late
00:43:31.359
wonderful wonderful little waterfall just beautiful beautiful area back there so risky
00:43:42.839
code
00:43:53.880
what okay when I ran across this I said what is going on here cuz I remember
00:43:59.400
writing this method but I don't remember leaving it like
00:44:05.319
this evidently when I wrote it in the when branches I used a single trary operator single conditional
00:44:12.599
operator that chose one of two things and I felt that was straightforward whoever came in after me decided oh
00:44:18.359
that's a good idea let's string them all together and I talk to him and says oh c
00:44:24.440
programmers do this all the time and I go I'm not a c programmer
00:44:30.119
and this may be a styling issue and some of you might be going what's wrong with this other you guys are going oh okay um
00:44:36.119
yeah nested um conditional operators not my favorite thing to see uh we re I left
00:44:41.280
it as is for the moment but then later I had to come and add some stuff to this I said I can't add anything this this
00:44:47.440
actually turned into a lookup table much easier to read much easier to modify and the change um yeah scary stuff I got to
00:44:54.680
relate to you a little story here let's see what we're doing on time oh you're laughing you know this story yeah we'll go through it quickly then
00:45:01.160
this is from Zed Shaw he wrote a blog post in the blog post he said one of the things that's really great about agile
00:45:06.319
languages is the great flexibility to give you the power to do anything one of the bad things about agile language is
00:45:12.000
they give the same power to every other idiot to stab you in the back with a rusty Pitchfork he then goes on to relate a
00:45:18.680
story about a logger in which that standard Ruby logger is really really nice if you haven't used it it gives you
00:45:24.319
all kinds of flexibility the ability to change formats and everything someone went in and hardcoded the format so you
00:45:31.000
could not change it through this monkey patched it to do so he said not only is
00:45:36.079
code reopen a class to do something it could be done with subclassing sorry I'm getting excited
00:45:42.680
but turns off the documentation so no one knows that he does
00:45:54.200
it not currently what we like to think about as the principle of least surprise
00:46:00.079
no not at all then he found that other projects do
00:46:06.160
the same thing and he goes and he shows us the code I'm going to skip over that kind of quickly because the comment the
00:46:13.520
developer left in was
00:46:19.800
this yeah you think the upside is this don't use
00:46:25.640
complicated Solutions when some simple ones will do and I call complicated things like monkey patching
00:46:32.440
metaprogramming and even Alias method chain if standard oo subclassing will do
00:46:39.160
the job for you or shoot form the logger gives you the ability to set the format
00:46:44.559
in a standard way use that I can't tell you how many tests I've seen where
00:46:50.319
they're testing two things and they decide to metaprogram the test and they do it
00:46:59.680
wrong so don't be overly clever keep your Simple Solutions for simple problems only pull out the big guns like
00:47:06.960
metaprogramming and monkey patching when you really really need them you know I'm all for doing it but do it when you need
00:47:12.680
it not just all the time
00:47:18.160
so how do you instill these ideas into
00:47:23.240
your developers you have to have the right attitude you have to go and approach the
00:47:30.760
problem with we are going to develop solid code and we're going to set some principles talk to the other people in
00:47:36.280
your group get them to decide on good programming practices and make that kind of standard in your Development Group
00:47:42.800
encourage it bring on new people bring them in by pairing don't take a new person put them off in the corner by
00:47:49.119
themselves where they don't get feedback from the rest of the group we have that problem with remote teams that remote
00:47:54.280
person will come on and we're all working in our office and we're all sharing the good ideas but that remote person is out there clueless about
00:48:01.040
what's going on and bring them in and help them get started especially be sensitive to remote people I think I am
00:48:07.720
running out of time um so I'm going to go through the rest of these slides kind of Qui quickly
00:48:14.480
bugs just don't go away don't ignore bugs find out what why the bug was there
00:48:19.800
oh I hate heising bugs don't fix bugs later fix them now
00:48:25.640
and then write a unit test to cover the bug that you just found there's a good story here I'll
00:48:30.760
tell the story quickly there's a doctor standing on a fishing pier and he hear someone out in the middle of the river
00:48:36.040
and he's drowning calling for help the doctor swims out pulls the fellow in gives them mouth to mouth resuscitates
00:48:42.839
him and just as he finishes he hears two more people out in the river so he jumps in he drags those two people back and he
00:48:49.079
saves them and as he saves them then there's four people out in the river he swims out there and he drags all four
00:48:55.040
people back and then and then there's eight people and and it just doesn't stop what the doctor should not be doing
00:49:02.440
is saving people he should go up River and figure out who's throwing the people
00:49:08.480
in fix the cause not the symptom if you're fixing this fixing that fixing that go and find out the root cause of
00:49:15.200
why these bugs are cropping up and fix them as well um yeah testing testing the bottom
00:49:22.559
line is your code is your responsibility uh take charge of it and do the right thing thank you very much