Summarized using AI

Writing Solid Ruby Code

Jim Weirich • September 29, 2011 • New Orleans, Louisiana • Talk

Writing Solid Ruby Code is a talk by Jim Weirich at RubyConf 2011 that focuses on enhancing confidence in writing code, specifically in Ruby. The talk begins with a disclaimer that it will not cover the SOLID principles of object-oriented design but will instead center around techniques for writing more reliable code. Here are the key points covered in Jim's presentation:

  • Confidence in Code: Jim starts with a provocative question about the audience's confidence in their codebase, prompting reflection on how developers handle the pressure of production deployments.

  • Influential Literature: He highlights significant books that influenced his coding practices, particularly "Writing Solid Code" by Steve Maguire, which offers insights into developing software with fewer bugs.

  • Assert Yourself: While asserting conditions in code is crucial in languages like C, Jim suggests that Ruby's exception handling negates the need for traditional asserts, advocating instead for the use of unit testing to ensure program correctness.

  • Testing as Specification: He emphasizes viewing tests as specifications that should be both sufficient (covering all necessary behaviors) and necessary (not covering redundant aspects). Effective unit and integration tests are presented as critical to developing robust software.

  • Fortifying Subsystems: Jim advises caution with data from external sources, emphasizing that developers should not trust inputs that originate outside their systems (e.g., user inputs or database data).

  • Debugging Tools: He advocates for utilizing debugging tools, such as the Ruby debugger and Pry, to explore the state of applications during testing, enhancing understanding of code behavior.

  • Candy Machine Interfaces: He relates the concept of user-friendly APIs to candy machines, warning against creating overly complex or misleading interfaces. Simplicity in design and function is key to preventing misuse and frustration.

  • Risk Awareness: The talk stresses the importance of considering risk during code development, including refactoring complex methods to reduce cyclomatic complexity, thus improving maintainability.

  • Addressing Bugs: Finally, Jim closes on the notion that ignoring bugs only exacerbates issues. Developers should prioritize fixing root causes of defects rather than merely addressing symptoms.

In conclusion, the talk serves to remind Ruby developers that regardless of the language, the principles of writing reliable and solid code are universal. By adopting the right practices and fostering a culture of quality, developers can instill greater confidence in their code, enhancing both their productivity and code quality.

This presentation aims to equip developers with actionable insights to improve their programming practices, fostering a focus on reliability and maintainability.

Writing Solid Ruby Code
Jim Weirich • New Orleans, Louisiana • Talk

Date: September 29, 2011
Published: December 12, 2011
Announced: unknown

Do you always seem to be fixing bugs in your software project? Are you spending more time fixing defects that actually implementing new behavior? If so, this talk is for you. In the mid-90s, Steve Maquire wrote a book that strongly effected the way I developed software. Primarily writing in C and C++ in those years, the struggle to deliver bug free software was especially a challenge. In the book "Writing Solid Code", Steve gives sage advice on the problems of developing large software projects and the challenges that go with making sure your softare actual does what you think it should. Although as Ruby developers we are no longer using C to deliver our large projects, the challenge of writing solid, reliable code is still before us. Based on Maquire's advice and my own years of Ruby experience, this talk will show developers tools, techniques and practices that they can use to improve their software and begin writing solid code.

RubyConf 2011

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
Explore all talks recorded at RubyConf 2011
+55