Aloha Ruby Conf 2012 Refactoring from Good to Great by Ben Orenstein

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
good afternoon Aloha Ruby how's it going yes everybody doing well good lunch raise your hand if you're in Hawaii right now not bad right I've been to worst conference locations I got to tell you so it's interesting I realized earlier this is the first time I've given a talk twice in a week so on Thursday I gave this actually this exact sample very similar version this talk at magic Ruby which is in Disneyworld so I fluid roughly from Orlando to here so my life is rough you can send sympathy cards to my address so just a little bit of administration before we get started my name is Ben Ornstein I work at thoughtbot in Boston and this talk is refactoring from good to great and this is basically about things I've learned in the last year or so that I think improve the quality of my code so I'm just going to share that with you guys now I don't want you to think of this as a lecture this isn't me standing here and telling you all these things that are absolute truth think of this as pairing I'm now pair programming with all of you so as a result of that if you have questions say something if you disagree you say something you get suggestions say something I love that back and forth during the talks don't be shy about interrupting I love diving into stuff so so go for that now let's dive right into this I want to show you my first example take a second and read this code now this is based on some code I wrote recently it's a slim polite version this is basically a very simple report that takes a collection of orders a start date and end date and return the total sales of those orders order has an attribute called placed at that we used to check the date range now about a year ago I would have committed this pushed it up and been done with it now when I look at this I look at it I think it's about B ish it's about a B B - it's decent if I if I was pretty confident that I would never come back to this code and change it or extend it I'd probably just say whatever good enough push it up and let's move on to the next thing but these days I actually there's some stuff I would do to it to improve it so the first thing I'd like to do notice we've got this temp variable right here we're figuring out the orders within range we're sticking him in a temp and then we're doing something with it I'd actually do a Strack this into its own method I'm gonna pull this into a private method I've recorded a macro that does this for me don't freak out so here's the before temp is in that method here's the after I made a private method with the same name and I'm just referencing it from up here so this is something I actually do a lot these days pull out these ten this is this is a factoring name for this called extract temp to query and this is something I do a lot now why do I do this why is this worth it well the first thing to notice is we've gone from one method with two lines to two methods with one line each now I'm not going to tell you that that's always an improvement but it usually is I'm starting to think these days that methods longer than a line or a code smell and I should define what code smell is just in case a code smell is something that indicates there may be a problem not that there is a problem that there may be a problem these days I tried really hard to get down to methods that are one line and it usually results in really good code because my methods are focused so that's one win the next is that we can reuse this so I think it's reasonably likely given that we have total sales or the date range the next thing that the stakeholder asked for is something like average sales within date range now when the code looks like this you have the logic for selecting those orders within range locked up in one method it's more likely I'm going to duplicate that later whereas if I have like this I think it's more likely to for me to reuse it so I think that's another win finally the nice thing about this is when the code looks like this for whatever reason because we're programmers because we read code when we see code like this we read it so the first thing your eye does when you see okay orin-san range equals okay let me figure out what this is let me figure out what this is doing when it looks like this when it's its own method my eye is more likely to see or does it in range okay this is private method I'm just gonna assume that selects all the orders that are within the date range what's it do next I'm more likely to ignore those details and in fact by extracting this method and moving it into a private method I've given you a hint and the hint is this code is not important this is an implementation detail that you don't really need to care about if you care about exactly what's going on in that method you can dive into it but it's not super important to what this report is about so I think the winds are sort of small but in the aggregate they're theirs they're worth doing so let's keep moving though I think we can K make this better let's look at this method we've created now oars within range and now within this method we're asking order about things about itself we're saying hey you place that after the start date and before the end date and then we're using that information to make a decision has anybody heard of a concept called tell don't ask okay cool so this is it this is an idea it's not a law but it's something that can sometimes lead to better code and what tell don't ask is is it says it's generally better to send a mess that send an object a message and have it perform work rather than ask that object about its internal state and decide what to do on its behalf not a law but it's a maximum it tends to lead to better code this code actually violates tell don't ask you can see I'm trying to select some orders and to do that I asked order about things asked order things about itself and then make a decision on its behalf so I'd rather actually change this code to look a little bit differently so what if instead you did something like this so now this sort of looks like an ask but the logic has moved I'm actually telling order something I'm saying tell me if you're placed between these two dates as opposed to pay order what's your internal status what are the what kind of attributes do you have and then I'll make a decision based on that so this is actually closer to following tell don't ask so I have specs for this which I'm going to run right now and that blows up because I use local variables when I meant instance variables let's do that again okay there's the order there's the error we want undefined method placed at we're calling a method on order I'm effectively doing TDD by writing the code I wished what wish were there so let's actually add that method to order now and we actually want not placed at we want place between that's a better name all right so let's define that place between takes a start date and an end date and then we're going to say is my start is start date after is it before placed at and is end date look got it backwards so I let's do this over placed at this will be easier to read is place that after start date and is it before end date right so there's our place between method let's run the test again we're back to green so the question was what about a range include and that's a great idea and I get there yep we're doing little steps but this guy is totally right we will end up there eventually but not quite what you said something a little bit slightly better look good question so okay so is this an improvement yes I think it is we've moved this logic over to order we've stopped pulling out interior pieces of order and fiddling with them understand just sending messages this is a good old principle to follow don't let the internal details of something like order leak out into code surrounding it that's the that's the core idea behind tell don't ask so I think we have a nice win here again I'm happier with where this logic is living but now we've sort of I see now a new problem a problem that's made evident now that we have a couple places where I'm passing start date and end date so notice I pass start date and end date into the initialize of this report and then I'm doing it again down here and I have start date end date here this is another smell when you have a pair of arguments at least two that you're passing together all the time there's a name for that that's called a data clump and now a data clump is a great hint that you should have tracked an object instead to hold those values a good way to test if you have a data clump by the way say oh these two pieces data have started an end date if I took one away with the remaining one makes sense not really right what would it mean to pass it just create an orders report with just an end date does really makes sense so if these things are always going to live together there's an implicit reliance on each other right it is implicit that I need a start date and an end date whereas if I made this thing into one object like a date range it becomes explicit that I need both of those that's another great Maxim to think about when you're writing your code imagine you have to show explain your code to somebody else any line they have to go okay well we're always going to start did an end date anything that's implicit in the code that you can take out and somehow make explicit and more obvious that's generally going to be a really big win so let's do this and we'll start in the spec here's my spec it's really simple I have an order within range and then out of range and then it's then this date range and then I make sure that the total sales number is correct so let's pull out a date range right now and again I'm going to write the code I wish I had come on baby oh my gosh I'm getting too hard there we go and then here I'll pass in the range cool so far we're going to run this it blows up uninitialized constant date range as expected because I just referenced a constant that's not real let's go make that error go away okay now there's gonna be a handful of errors as I run this right because suddenly raw number of arguments this actually I'm calling date range new and passing an arguments but it doesn't expect them so let's just make a quick struct to hold the start date in the end date and now I have roughly the error I want which is wrong number of arguments in two orders report I'm passing two arguments right here it used to expecting three up here so now I need to thread this new date range through I'm gonna do this in sort of a compressed series of steps so again don't freak out let's pass in the date range now there's no such thing as start date end date it's just date range and same deal here in that method we wrote an order it's just a date range and now we need to ask the date range about it start in an end date see if we're green again boom okay so is this a win yes it's a win I think it is I think this is worth doing now Bob Martin has said he thinks that most intermediate object-oriented program are too reluctant to extract classes you should be fairly aggressive about willing being willing to extract small classes like this look at date range it's super simple right it's very basic but again it's made something that used to be in plus it in our code it's not better better or worse all right it's made something that used to be implicit explicit now now date range you know is a pair of values this class doesn't have any behavior on it but I think this is still worth doing I've created a name for something I've pulled out an explicit name that's almost always an improvement but there's another one here which is we've reduced coupling now what's coupling coupling is the degree to which two components in a system rely on each other so if component a and component B have zero coupling you can change a as much as you want and in any way you want and you'll never break B vice versa right so that's with no coupling let's say that a and B are extremely coupled that means it's really hard to make changes to either one without breaking the other now as you might imagine low coupling is good high coupling is bad because couple low coupling makes change easier and that's what's hard about software is responding to change I saw a keynote by Dave Thomas and he said the only thing worrying about worth worrying about when you look at code is is it easy to change so low coupling makes things easier to change and let's look at a quick example of some coupling so there's different types of coupling this is called parameter coupling so notice that notify user of failure passes in an object called failure into another method within that method within print to console we call two-sentence on that parameter now if I passed nil into print a console this would blow up right no method error two-sentence is not defined if I passed if i pass something else let's say it an integer into printer console this will blow up right because two-sentence is not defined on integers at least I hope it's not so there's actually coupling between these two methods notify user of failure has to know what print a console is going to call on it ammeter if I change print a console I could make notify user of failure blow up because they're coupled through the parameter now parameter coupling isn't bad but less coupling is almost always good so something to notice is methods that take no arguments are superior to methods that take one because they do not have parameter coupling first time I heard that that blew my mind also if we keep using induction methods that take one argument are better than ones that take two and methods to take two arguments are better than the ones that take three because in each example we're lowering parameter coupling so notice what happened here we just slimmed down our argument lists from three to two and that's a win so coupling is reduced that's one win we've made something explicitly used to be implicit that's another win but also we now have a great place to hang behavior in object-oriented programming it's a really good idea to group behavior with the data operates on and now that I look at this figuring out if a date is between two and two bounds is not actually really good responsibility for order but it's a great responsibility for date range I can imagine wanting to know if other objects have a date place between two two end points and we can reuse date range so what other to do now is move this logic into date range so why don't we say what we want this to look like so why don't I ask date range hey does this include my place that that looks good to me that blows up as expected because this method doesn't exist date and then we'll say is date after the start date and before the end date let's see if that works for us it does so now order just knows how to ask something else if its place that is included and I like this because order should know about place that I'm okay referencing this bit of data which is on order within order and I'm okay with date range knowing how to find if a date is between two dates perfect exactly where I want this logic to live now lets this guy asked about a little refactoring so let's do that right now there's actually a handy way of writing this so I can ask if start date end date the range if it includes date right back to green good but a little thing that that I gave this talk somewhere maybe Scottish rubyconf and Jose valium told me this cover cover or covers let's see no cover yeah so when you ask a range if it includes something Ruby is going to instantiate every object within that range and then check if the object you pass it to include it exists in there if you ask cover it's just going to figure out it's going to stand she ate the two end points and then use some logic to figure out if the thing you passed in is in between this so if we had a date range that was three hundred years long this actually could be a lot faster performance wise yeah question that's a great point his point was that my tests aren't really thorough enough I'm not testing the edge conditions in there and that's actually a really good point I should go back and improve those tests I think you can probably that it works enough for now but yeah that's it that's a good thing I should I'll be the coverage on that guy that's a very good point other questions yeah No yeah feature in good point yeah so the code smell that motivates this kind of refactoring is called feature envy and feature Envy is when one class seems very concerned with the internals of another class when it's asking a lot of questions about its internal data and working with it that's usually a good hint that you want to move that logic on to the class itself the the code the client code has envy of what that other class knows and so it's asking a lot of questions and fiddling around with the data thank you that's good so a couple little quick things I would do now tree fat to finish this up I'm going to move on to a new example so this is kind of ugly right this is pretty janky when I read this yes I'm mapping the amount and I'm doing this and I'm summing this way but if you read this you're just really calculating the total sales right so whenever I have a bunch of kind of ugly code that I wouldn't just wouldn't use the words oh I'm going to map the amount and then inject what 0 is the default and add the sum what I'd really say if I would describe this to you is then I'll add up the total sales so when you look at your code and it doesn't read like you would say it make it read like you would say it so what I really would say is something like that oh we're my type of sorters within range all right back to green so now take a look at this top level method the total sales here's the name total sales within date range are the total sales of the orders within range that is how I want my code to look that's like brain dead simple right and this is my only prime only public method I'm extra aggressive about making my public methods read like this because it's really likely that someone that comes into this code mostly cares about this method these I'm slightly less aggressive about that but people want to know about your public API your public API should be super super clear your private API should be as well but it's a little bit less important it's less likely that people care about those details but even so I'm gonna change this guy right here just to be a slightly quick little hack with Ruby 1:9 I don't need the ampersand symbol plus oh my goodness so it calls to proc on that for me oh that's wonderful that's cool okay so apparently we don't need to you don't need to call to proc out you can just pass in a similar argument which is wonderful I think else I heard some murmuring sakura-san adobe the zero but he is only partially right if I don't have any orders this will blow up and funny enough I didn't have the zero originally and then in the middle of a talk Jim why rick is like what happens if you don't have any orders within range and I was like map will bring up an empty array and then I'll checked over it and what do I get if I don't have it I guess I'll return an empty array as opposed to zero right if I inject plus on zero yeah right if I just have this that's going to blow up right nil as opposed to zero so Jim where I rec beat you on that one Cory sorry you should see my commit message look Jim Wyrick found a bug in my talk I was really excited okay so we've been working hard so I want to show you as a quick means of a break my most important Finn plugin mmm this is the only vim plugin I use obviously not really but hey alright let's move on let's do something different there's another bit of code I like you to look over now this code represents a job site as in the place we're doing some construction work we're cutting off the top of the screen a little bit let's go up here there you now all job sites have a location because you're always doing work somewhere but not every job site is going to have a contact contact could be no that's optional we might not know who the contact is at a particular job site so notice I've just described something implicit about this code right it's not obvious from looking at this that a contact is optional but you can start to see it at these ugly conditionals look what happens if I want to pull up the contact name I've got to check for the presence of contact otherwise I provide a default likewise with contact phone and if I want to email the contact I have to make sure he exists first before I try to call a method on it so how is this code well his codes okay it's not great what's what's the problem well it turns out in a slightly more hidden way we're still violating tell don't ask vital until don't ask again so we're actually every time we ask contact something we say hey do you evaluate to a truth eval you and if you do I know what to do and if not I'll do something else so what we'd rather do is just send contact contact name tell me your name and if you do exist return what your name is and if you don't exist tell me no name so what's actually happened here is we've co-opted nil because when content doesn't exist at contact will be new and so I'm actually passing around the nil object the nil singleton as my contact that's not a very good idea and at least this ugly conditionals like the one on 12 so how do I prove this well oh and one other bad thing this obscures the point of the code right contact that name really just cares about the contacts name but I have this annoying handling in here it's making it harder to actually see what this code really does so the way around this is with the pattern reasonably common one called null object pattern so rather than having nil stand-in to mean when there is no contact I'm going to actually create an explicit object to stand in for that case and since this uses the null object pattern and I believe it's a good idea to actually use pattern names in class names which will some people want to fight to the death about that one I'm gonna call it Mel contact so if we don't actually have a contact passed in assign a null contact that new let's run our tests oops get their own test going boom and things blow up the first error was that there's no null contact so let's make that happen now we have more errors and now what's happening here is I have tests that don't pass in a contact they just pass in passing nothing and so it's assigning a new null contact here but then no client it doesn't respond to things like contact that name it's just a brand new class got nothing on it so let's add these things so we're gonna add name we're gonna add phone then we're going to add deliver personalized email on to our adult contact class so here's name just when there's no contact the thing I want to return is no name or no email deliver personalized email takes a email body but I'm just gonna leave a blank I'm not gonna have to do anything so there's not a contact just do nothing so if I run this oh I'm gonna find method phone up phone right phone yeah okay back to green and now we're green but what can I do now I can do what every programmer favorite thing is which is what delete code no one ever fails to know what that is that is so universally the programmers favorite thing everyone gets that so let's lay some code oh yeah oh yeah oh my god ah and we're still green how great is that right yeah thank you fit that guys yes like I like snot contact a lot me too okay so for the cost of this stupidly simple null contact class I've blown away three conditionals you ain't add about twelve lines of code made these methods more obvious and more direct all for the cost of one little class also notice we're no longer valid until don't ask we always tell some sort of contact yo dude I need your name we never care about whether it's an actual contact or a null contact the client code doesn't know and it doesn't care so that's awesome this is actually a great win this pattern it's simple but once you understand it you see opportunities to to work with it all the time and it's great now there's a downside now right what's the downside that's now I basically have to keep two api's in sync right if I add new methods to contact I'm going to need to add them to no contact as well that's a bit of a pain in the ass but it turns out it's generally worth it a lot of code ends up with these big hairy nasty conditionals and null contact just like destroys them like that by the way this refactoring is called replaced conditional with polymorphism which means rather than doing ifs just send that same message to multiple different classes that's polymorphism right you just always send a message to varying different types of objects and objects know how to respond to it in different ways so it's a bit of a cost to this so you have to weigh that to see if it's worth it nothing I'm teaching you today always works there's no referring that is always a great idea you always have to say is this worth it given the components of my system as they are so that's the downside we talked about the good signs there's a lot going on how many people by the way have code in a rails app that looks like if current user yada yada yada here's your hand yeah can you see how this would apply to that so rather than have current user returned a user object or nil and then constantly need to check if current user is nil have current user returned user or a null user yeah yes yeah yes it's a great question the question was Mel content is defined in this class do I leave it in the class or do I pull it out and make it sort of a first-class citizen in my business logic and the answer is it varies usually with something like a null contact I will pull this out I'll put it in at models I'll call it a null contact are B it will live as a top level important class in my app occasionally I will define classes that only live inside the context of like one other class right so like if you are being aggressive about extracting small classes like Bob Martin says you should be there are times where you'll find that you've written a small class that's really just like a little data container or something very basic that's only used in one class and in those cases I'll just leave that class inside the original parent class I'll even make it private so I know nothing will ever talk to it it's just for that that top-level class by the way in that case I wouldn't read explicit tests for that class if it's private to another class I'm not going to test it I'm not gonna test private methods ever actually nothing with private but if I do promote it and to be a top-level class then I'm going to write separate unit tests for this to make sure it works it's a great question other questions about this or anything else all right we got one more example and then a quick wrap-up and I got some recommendations and things like that so onward and upward let's go to this guy take a second and read this code okay so let's talk about an idea called depend upon abstractions now most programmers are aware that's a good idea to depend upon abstractions so most people will use for example active record to have it generate sequel for them rather than write sequel by hand unless you're in a horribly ugly situation where sometimes that's the only way out but hopefully you don't get there also most people won't just shove bytes into a socket they'll use a library like net HTTP so most programmers are aware of this idea in general like you want to you'd rather keep pulling up a level of abstraction and you'd rather depend upon those abstractions than particular implementation details for instance that's why you pull a lot of stuff to be private inside an object you don't want other things outside that code to depend on your internals you want to depend on an abstraction that you're providing the thing that a lot of people don't realize is that abstractions are fractal you can keep going higher and higher and you should be relatively aggressive about creating abstractions within your application one great rule of thumb is that you want the hole to be simpler than the sum of its parts that's a great rule I took from the book called growing object-oriented software guided by tests which has the longest book title I've ever recommended I'm going to show you a link to that later cuz it's an awesome book that's a great rule of thumb the sum should be simpler to work with than its parts so if you've got a few models or a few classes in your app wrap a class around that bad boy make a simple API that's easier to use create an abstraction that your other things can depend upon rather than the low details within your app one place I see this violate a lot is ideas like this so I have all this code here and this code is concerned with charging people thing for things braintree by the way as a payment processor so I pull down the Braintree gem which is good it's better than writing direct calls to Braintree as API shoving bytes down a socket I've extracted a bit it's using an HTTP API but my code doesn't know about that it doesn't know that this is an HTTP API which is good we've gone pretty far this is nice it's not great notice that user is concerned with things like how do I find my own Braintree ID and then once I do how do I charge for a subscription and how much should I charge or how do I create myself as a customer with inside Braintree and then refund is concerned with other problems how do I find the transaction ID of the thing I billed for and then how do I refund that so we've depending upon the Braintree gem as an abstraction but we can go more abstract than that this has some this to have some weaknesses right now if I wanted to change which gem we use to bill with Braintree I suddenly need to open up user that seems like the wrong thing right oh I need to change which payment processing gem I'm using therefore let me open up the user class right that's a great smell there's this idea called shotgun surgery where if you need to make a change in your app I need to open up 30 files you're doing surgery with a shotgun regular blow and stuff code everywhere you're affecting everything you're breaking stuff it's so much more likely that you're going to break things you're going to do it wrong wouldn't you love to just open up one file and change your payment processing gem there yes you would isn't it likely that you might change payment processors yes it absolutely is I've done it before here we have to open up all these classes so how do we improve upon this well we do something like I would do something like this I make a new class as you might have guessed so I love classes called payment gateway I've moved that constant inside payment gateway it's a nice place to hang it and I set up my gateway which by default is Braintree gem and I move that logic in there and then my client code this stuff only knows about payment gateway and the method names and it just passes itself in now all that logic lives inside payment gateway it hasn't leaked into my application if I want to change payment processors there's only one file that needs to change that's the power of depending upon abstraction one file needs to change when I'm going to change not shotgun surgery that's actually a really big win it makes it easier to change stuff which is the thing that really matters finally notice now if I want to test this guy thoroughly I have to stub methods on Braintree which is a great way to make yourself wanting to have a bad day you're going to have a bad time if you stub other people's methods you're going to have a bad time Braintree gem hit API is reasonably likely to change you update versions your tests are stubbed out you don't realize those methods have been changed until you run this thing in production and it blows up and you can't build people for stuff and people are really upset in this version you can stub your own methods if you stub your own methods you're going to have a good time I'm totally fine stubbing out charge for subscription or create customer because I control them so this thing just got easier to test with the introduction of a new abstraction that's a great sign that's a positive code smell when you're writing your tests pay attention they're telling you things if it's hard to test something if you have to do something that makes you feel dirty don't do it listen to those tests and instead figure out how you can test it and figure out a change you can make to it to test it in an easy and straightforward way I don't always do things like this but when I notice that I've got the concerns of billing spread out through the app I'm more unpretty likely to do it I don't like to see things like gem names popping up or gem class names popping out through all my business logic I'm just concerned this is a payment gateway I'm not concerned that I'm using Braintree to do it depend upon abstractions okay so we've talked a bit about some different ways of refactoring so when do you refactor well the best time to refactor is when you want to make changes to the code it's actually rare for me to just be like wake up a Monday morning like you know what one or a fact or some stuff there's that user class that sucks I'm gonna refactor it now part of that is because I'm a consultant right and consulting code is a little different than product code if you're a product company guy versus a consulting guy like at the end of every week I need to point to stuff that I've done and that justifies the value that I've just charged for so there's there's a bit of a a bit of a paradigm situation there which maybe doesn't match yours but I don't just wake up and say I'm to refactor stuff but when I go any money to change something I am very likely to go refactor it so Kent Beck had this great tweet which is if you need to make a change refactor the code so that the change is easy note this part might be hard then make the easy change it's a great way of thinking about it when you get to some code and you think oh man I got to change this widget to take a foo widget instead think about how you can make the change that you're about to make really simple and straightforward refactor it that way and then make your change so don't just refactor willy-nilly especially if your consultant okay so that's a great time to refactor what are some good things to refactor what are good candidates for a factoring well the first my favorite things to refactor are God objects that's a god objects a God object is a class in your system that everything seems to rely on or everything seems to interact with and a great rule of thumb is that rails apps almost always have two god objects the first one is user and the second one is whatever that app is about so if it's a to-do list application the other god object is what to do if it's an e-commerce application the other god object is what order exactly - god objects at least some apps have more the bigger they are the more level you've got a handful of God objects so how do you find these guys how do you be aware of them well a great way is to walk into your app models directory i've anonymized this one to protect the guilty let's get a word count of lines of every object every every model of ours and then let's sort them and you'll see that I'm not totally crazy this is an e-commerce app how can you tell well user is a god object order is right behind it and this one actually kind of has three merchants is arguably a god object do you think a 600 line class has only one responsibility probably not you've heard of the single responsibility principle right every class should only have one responsibility a singular responsibility the first rule of classes is that they should be very small the second rule of classes is they should be even smaller than that this app is violating that user is huge and because of that it is a pain to work with user so when I'm working with user I refactor it if you want me to change something about user I'm going to make damn sure when I push up those changes user is smaller than when I started I'm extremely aggressive about refactoring responsibilities out of god objects I don't want user to get any bigger I want to get it smaller same thing with order same thing with merchants it's a great way of thinking that these things be aware of your god objects and be completely reluctant to add additional lines of code to them it's going to make your life a lot better whereas what else is a great time to refactor I turn files what's churn churn is when you're changing a file a lot I keep having to come back to user and change it and change it and change it and change it pay attention to that how do you how do you notice that well maybe you just notice it but maybe you use a gem like this it's a gem called churn this will look through your git history or SVN if you're crazy and it will tell you the files that change the most if a file is changing all the time it's because you don't really understand it it's a great candidate for refactoring if change it want to make it easy to change that file in the future so give it a good a good happy dose of refactoring another great place to look for refactorings our files in which you find bugs and you know why because bugs love company if there's a lot a bug on line 10 chances are there's a bug on line 11 and the reason is the code was too complicated for you to understand it that's why the bug is there it was too hard for you to see the bug so if you've got a file where bugs are showing up all the time refactor it make it easier to understand give the bugs fewer places to hide so that's when I like to refactor so a couple recommendations before I go first is if you ever read this book read this book this is about the best like intermediate to advanced to sort of advanced beginner ish book for general programming knowledge like it it's just great read this book after you've read that book read this book there's basically nothing I'd talked about today that isn't in this book this is the Bible you've got to know this book you should know the names in it you should know the techniques in it it is wonderful also these two guys Bob Martin over here and Martin Fowler over here are just the best damn software authors there are no one writes about software and programming better than these guys in my opinion finally this is a great book this one is like the least known of those three books the other two a lot of people have read or at least I've heard of this book is sort of an unknown it's awesome it's a beginner book it's an advanced book it talks about the ideas in oo programming and TDD that I sort of roughly knew implicitly but very cogently very explicitly it made these ideas make a lot more sense it presented them in ways I've never thought of and gave me a lot of really good rules of thumb so check out those books refactor when you got to do it right some good code thank you you
Info
Channel: Confreaks
Views: 80,860
Rating: undefined out of 5
Keywords: aloahrubyconf2012, aloha ruby, refactoring, ruby (Programming Language), software development, Ruby (Software), Code Refactoring (Software Genre), Hawaii, Software Tutorial
Id: DC-pQPq0acs
Channel Id: undefined
Length: 44min 19sec (2659 seconds)
Published: Fri Oct 26 2012
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.