LA Ruby Conf 2014 – Write Small Things by Mark Menard

oh good afternoon my name is Mark Menard and I run a company called enable labs in Troy New York so a little bit about me I’m my wife Silva I’ve got two boys as her own avi I’m from and they still reside in Troy New York i’m the owner of enable labs for boutique consultancy doing web and mobile development and I’ve been doing rails for about her Ruby for about five years and I’ve been doing software development for a long time and in prep for this talk someone on my Twitter feed came by with this quote I really love it because it really sums up why writing small clean well designed code is really important because as he says great thing about writing shitty code that just works is that it’s too risky and too expensive to change it so it lives forever become zombie code it’s it stuff you don’t even want to open the flower if you do open the file you open the file you’re looking to go home I’m not going to touch that then you go elsewhere and write your own code duplicating some of the functionality that’s in that code so this talks probably going to focus on code go to the class code the method method level because having smoko to the at the class level the method level it is the fundamental building block of creating small code that can be composed to create systems that are loosely coupled I want to initially dispel a few concepts that you might have about what clean code or what small code is it’s not actually about less lines of code it’s about smaller method small classes and a smaller surface of your object that you have to understand to get your work done fundamentally writing small code it’s a design discipline I was talking with the guys yesterday workshop and it’s kind of a bait and switch you can’t write small code from scratch at least I can I’ve been at it for a long time I still suck at it it’s an iterative process of refactoring and tactical design at the code class and method level so this really about design and refactoring as much is it about writing small code because design and refactoring is the way to write small code we don’t just sit down from scratch and write it you evolve to it it’s iterative it’s process it’s emergent so what do I mean it’s not about total wine count well factor codes probably going to have more lines it’s not about meth account you’re probably going to end up with more methods it’s definitely not about class counters almost assured we’re going to end up with more classes it’s about small methods and small classes that you can compose together because the class is the fundamental building block that we’re going to work with is the thing that we do as object oriented programming us to take concepts and separate them and compartmentalize them so we can compose them together to make systems that will live a long life so why should we strive for this the most important one is we do not know what the future is going to bring if your software succeeds and I have some system been out there running with clients when I started my business 10 years ago we still have our first client they’re still running the piece of code that we put out there for them and they live long if you succeed it’s going to live and it’s going to change you want to raise the level of abstraction it’s easier to wait raise the level of abstraction if you have small code small methods and small classes you want to create composable components because you want to get that functionality that’s buried in that shitty code that’s in that big huge file and get it out so you don’t keep reduplicated it and then end up with two versions three versions and four versions that are divergent from each other and how they actually function and fulfill the specification and you want to prefer delegation over inheritance do it once don’t repeat yourself sorry I was looking at the other side so the challenge that we have with small is that you’re going to end up in dependency management hell if you don’t do it right it’s really important that you get this right because if you have as many small components and they’re fitting together and you have your dependencies go in the wrong direction it’s going to become a rat’s nest you don’t want to be there and you’re gonna have to manage the context within your objects run and you’re probably already doing that if you’re doing test-driven development because your code actually has to run into context already the test context in the actual production running context but if you’re using a mocking framework and you’ve ever used class

named any instant stub you’re not context independent so the goal with small units of understandable code that are amenable to change that’s what we’re doing trying to do today our three main tools are extract method extract class and composed method longer methods are harder to understand than short methods longer classes are harder to understand then short classes you can’t fit it on a screen you have to keep scrolling up and down up and down it’s hard to keep in mind what you’re working on what did it stay up there oh I’m already been all the way down at the bottom of the file the other thing is you have argument if you have methods that take lots of arguments you’re in trouble those are hard to extract they have a lot of context around them the other thing work on is a composed method the composed method is a great way to write self documenting code that when you come to when you open it up hopefully up near the top of the class there’s some method it’s got a few lines on it it tells you what the thing does in English not comments but actual code so let’s talk about methods I love this quote this is from refactoring by field Harvey Fowler in black if you don’t have a copy of this book you should get it it’s the tactical day-to-day skills that you need the object program that lives best and longest are those with short methods the operative word here is best remember that shitty code it also lives forever but it’s not good short methods short classes composable those are the best code that’s what we want to get to so the first rule of methods is do one thing do it well and do only that thing yet we achieve that every time we write code every time I sit down every time I’m doing something no but that’s the goal that’s where we’re pushing for every time or where you should be pushing for every time that you sit down and you create code and there’s one that’s hiding in here about the do only that thing is don’t have side effects object-oriented program is imperative programmers we love having lots of side effects in our code if you can avoid side effects you’re going to have a better long-term relationship with your program use a descriptive name this one’s really important naming is one of the hardest thing we do but you gotta work at it the fewer arguments the better my goal when I’m writing code is no arguments 0 not at nil one maybe two if I have to three if it’s really necessary but I really try not to have three arguments pretty much anything except for a constructor when I’m setting up the context for a piece of code to work that’s what I will have more arguments or I’ll pass in an option hash separate queries from commands if you want to ask your object about something it shouldn’t be twiddling the internal state of the object it she was giving you something if giving a commander should be twiddling the internal state of the object in doing something don’t do them both at the same time and of course don’t repeat yourself as soon as you repeat yourself if you have to change that you’re going to have to go find it in the code no matter where it is and eventually you won’t be able to find all the instances of it and then you’re going to have divergent behavior so let’s build a command line option library and I got to tell you that part of doing this talk that was the hardest thing is coming up with an example that people will understand the domain that’s me d enough that you can do in 21 minutes that’s what I have left so my buddy says hey I’m doing some command line programs I really if you do you know of an option library can you do an option library for me I just need to set some flags on the command line so I go and say well with something like this work for you got my command line options new pass at the RV and configure in there what options i’m looking for here i’m looking for an option c option vian option e and then down the code you can do something with it if options has see if options has be of options has ian do the things that i need to do in my command line in my command line program pretty easy right

so let’s write a spec describe cam command line options the options are true if they’re present so if i set the flag on the command line it’s true it’s not there it’s false pretty easy right so run my spec I’ve got two failures which I should have because I don’t have any code yet and when I got done here’s the code that I have a little explanation I’m storing those options that option C option B option am storing it in an array I’m storing the RV’s and where I’m and I’m also if the person has it or not I’m just checking to see is it in the allowed flags and was it actually in the come in that RV array pretty easy because I have to do anything there’s no validations no nothing just is it there and the way this gets can figure it up is the command line options new take the block and I instance eval that so we end up calling this option method which just takes the flag and shoves it into the array voila run my spec no failures I’m done then my buddy comes in and says hey do you mind if I have one of these that will take a string and validate that the string is there make sure that my options are valid not by okay that should be pretty easy that’s how I’m going to define it in the dsl there that’s how I’m going to use it options dot value give it the thing for the value pull it out so let’s write a spec there’s my string option spec it must have content it can return the value it returns nil if it’s not in the RV so if you didn’t put on the command line I just give you an ill so you’ve got a faulty thing so you just do what you want to do run my spec three failures and I’m failing on undefined method for command line options valid because I don’t have a valid date method yet and I wait to in my spec just right the way I want to consume the object and start evolving the interface of what that object is and I want a valid method the other one I got is is options value saying undefined method value for command line options that’s my other thing so my command line options now has to have a value method and a valid method time go to work so I write my options here that’s my valid method to go over all the options that the person wants to have their I’m now storing the options as a hash so I’m putting the the thing I’m looking for in the command line into the hash and then I’m looking at the storm whether it’s a boolean or whether it’s a string in the value in the hash so I’m going through that and saying okay well let me get that value out go find it in the RVs and if it’s there and it’s in its length is a less than three and it’s a string than oh it’s bad we’re invalid run my spec I’m green got one example passing still got to go do that value so we’re now we’re going to go do that now we’re iterating over the thing looking for the value and we’re we’re indexing into the string to try and get it but you know only to deal with the boys and strings this is two things not a big deal I’m going to go do it run my specs five examples zero failures so let’s look at this code there’s problems here first off we’ve got duplication we’re going through and digging the value out of the RV’s in the two different methods so you got duplication there and this one I really don’t like is I’m seeing that option type equals string that’s starting to smell to me like I might be missing some concept here there’s an abstraction that I’m missing here so it’s time to do a refactoring I want to get that digging into the RV’s out of there so if we’re extracting method the way we do it is we identify the code that’s at a lower level of abstraction and a method we move it to another method and then we reference it and the method we moved it out of so over here in our code here we extracted a wrong value for option method that digs through the RV so we only have to do it in one place and we reference it in the two other places and the code where that used to be run our specs and we’re green here’s my code I got 38 lines of code

including white space it’s okay it’s not great because i still got these option types equals string hanging around but you know if i only need to deal with boyens and strings not such a big deal the other thing i see going on is I got those magic numbers whether the length is less than 3 or the wrong option values I’m taking the index of 2 to the end of the string that’s really detailed kind of stuff but you know it works and my buddy says he’s done with it so I’m done then a week later comes in and says hey you know we do integers and the guys are in the workshop yes you will tell you at this point the code explodes if you start doing the value you start doing the valid the validate method you start getting into it you start having complex logic in here you start having lots of this unless ha’s and nesting we’re going to go through and take a look at it so right my spec there’s my integer must have content must be an integer can return the value as an integer returns nil if it’s not in the RVs if the person didn’t pass to me it’s just nil run my specs they’re pending so I implement my first example must have content just checking to see there’s content there so this is my valid when I started and I’ve got that option type in there and I’ve got a new option type integer so i guess i need to do some logic on that this is really starting to stink I don’t like what I got here I’ve got a concept here of an option and I need to start thinking about getting that out of this class because this class is getting too many responsibilities and this method is definitely getting too many responsibilities especially when we say it’s got to be an integer here’s what our code starts to look like does that stink it does I’ll go through that later but we’re in one respects and it runs must be an integer is green now it’s not too bad it’s gotten worse so it’s time to look at that valid function I got two returns I don’t typically like to have two returns from a method it’s not an absolute rule but I don’t like it I’ve got that checking on type here on a symbol don’t like that still got those magic numbers a lot of red on there and if anybody digs into the code and says why my rescuing falls from the integer passenger string just type food to I and you’re an IRB gives you a zero so it’s broken so I do little refactoring trying to make the code at least a little bit more readable now I’ve got a switch statement a switch statement screams to me polymorphism and it’s definite I’m switching on the type very very clear so I’m going to add in that boolean type so now I’ve got all three of my types of my switch statement kind of a place I can keep track of it run my specs and I’m green but I’m going to get some of that code out of there and create some methods with the idea that I’m going to be moving these to another class I know they’re going someplace else they’re going to a string option or something an integer option option or something they’re going someplace else so I’m going to get them out of that case statement we just reference them in the case statement and I’m going to add one for boolean option because bullying options are always true they can’t be they can’t be invalid so now this is what my valid function looks like return false and less send option type doing a string figuring out the method passing it the raw things and getting that stuff if you start doing code like this and you’re you’re putting together methods like this and trying to get methods and one part of it is just changing you have a polymorphic relationship that you haven’t identified yet that’s ugly but I mean we extract it so the person who looked at this nose return false unless the option is valid so it’s at least a little bit more readable run my specs I’m still green my file is getting big there’s all my private methods and there’s the stuff that I know really shouldn’t belong in this class it’s time to get it out but the actual public methods that people are looking at are pretty small it has valid and value I’ve actually kept the interface and the exposure of this class pretty small so let’s talk about classes how do we write small classes first you got to write small methods then talk to the class and ask it what it’s doing have a conversation with your class anybody here have a rubber duck on their desk sometimes you don’t have someone around your office to talk to about a problem just talked to the rubber duck it’ll tell you the answer well mine does

find a good name isolate responsibilities this this class now is responsible for digging values out of that RV and figuring out whether these things are valid you want to find a cohesive set of variables and properties and package those up into something you don’t want them hanging out without a home and then extract that class and move the methods so a well-designed class is a single responsibility cohesive properties small public interface prefer with handful methods at most let’s not talk about active record bass implements us you a single use case if possible the primary logic is expressed in a composed method if you can do that and the dependencies are injected so let’s get a spec for our string options it has a flag as valid when it has a value can return this value when president returns nil with the flag is not there on the command line I run it and I am all yellow because I’m still pending you notice that I haven’t touched the integer options 1 i’m leaving that alone because I’m now in a refactor at the moment I’m going to go get that class out of there and dig it out so here’s my string options class it needs to know what flag it has it’s going to store the wrong value that was on the command line that came out of the RV that’s pretty much about it for now there’s my spec expect string options valid to be true when I plugged in a value and there’s my command line options my original class on the left-hand side we’re going to take that method out of there and move it over to the valid method in the string options class that’s moving over there and I had to bring over that method that digs the value out of the raw value that 2 to negative 1 index into the string because it’s Dash P foo so 0 1 then it’s 2 and beyond that’s where my string value is so I had to bring that along it’s a little bit of baggage but I got to have it there so you notice something on the extract value from raw value down at the bottom here no arguments anymore because we have cohesion around the properties of an option we’ve completely recreated place for those things to live we don’t have to pass arguments around anymore all of our methods have zero arguments and now back in our command our original class we just delegate to this thing string options new for now I don’t know what flag it is actually in this part of the code but i’m just going past in the valley the the value and ask if it’s valid i’m starting to delegate over to that class now and but don’t be don’t kid yourself we’ve created a hard dependency here on string options this class doesn’t work without that class being part of being around and we can’t sub for it here’s my integer option and here’s my string option see some duplication quite a bit of it isn’t there so we’re going to extract a parent class for these option with content because an integer has content after the flag and a string has content after the flags i’m going to we’re going to pull out that parent class and move the stuff up there and then that’s what our string option looks like pretty empty isn’t it i’m going to leave that class around because i actually have a use for that later then I got me an integer option it’s a little bit different because I actually have to parse the string and get the integer out of it and make sure it’s a valid integer so it’s a little bit different I run my tests and I’m still green so let’s talk about dependencies if you’re not injecting dependencies and you’re not breaking hard dependencies in your code they will come back to haunt you trust me I’ve been there I’ve suffered through it I’ve had to learn this the hard way dependency injection and depending upon abstractions not concretions we have an abstraction in our code we haven’t identified yet I know what it is that you probably a lot of you do we have that command option container we’ve got a string option we got internet your option we’ve got a boolean option the option is the abstraction and we’re going to make this code now depend upon the option abstraction not any of the concretions so this is what the code looks like to refactorings here this is up in the parent class where we’re building those options instead of sticking just whether it’s a string or an integer or a boolean into that that hash I’m now sticking the actual objects into it first I started out and I started out and I’ve got this switch case this case statement but I know using using convention I can get rid of that case statement and completely break the dependency on the type of the object I go privative option in here if I say option type and stick underscore option on the end camel eyes it and constant eyes it I now have the string option integer option or boolean option class i can just knew it and

shove it into the hash that’s the first version hardcored dependency on type here on all those classes and notice all the class names are gone we have gotten rid of our dependency on string option boy an option and integer option so how do we separate abstractions we separate the one from the how string option integer option boolean options they know how to get their values out I just want to depend upon whether I need options the option is the what I need the how is in the concretions those particular implementations samurai my tests I’m pretty red at the moment this is my old method for doing the valid and here’s my new method I just iterate over the values and an option tasks which are my objects that are the those containers and just ask them hey ro you guys valid I don’t have to depend upon that anymore I run my tests and I’m mostly green eyed I can’t get that value out of the string yet that’s right there so I got to rewrite this value method now I can tell you how I go on to the point of actually engineering this thing and putting in all the integer and switching in here this thing gets really complicated but I like my one-liner at the bottom option what if I you looking for tell me your value done but i’m still failing because i haven’t implemented that value method on my my my integer option and my string option so i’m going to go do that so i implement those two things run my tests and I’m green done right there’s no class my command options class there’s my public methods valid and value that’s it but I actually moved my adder readers for my options are to be down in the private section because no one should really be mucking around with the internals of my class it’s not theirs to talk to but the core of its these two methods def valid all it does is it ER eight over the the option objects and see if all of them are valid done I want to get a particular value out just go pull that object out and delegate to it and say what’s your value then he walks in again he wants to do a raise well it’s actually quite easy I write my spec at the top that’s my array option class only needs to know how to do is to get the to take that string that foo bar baz split it on commas and send it back as an array I add my spec I add in that class I run my spec and there it is it’s green now I’m done for the moment my name is Mark Barnard that’s my company and able labs if you’re interested about this I would love to talk about it any questions thank you very much member