RailsConf 2016 - Get a Whiff of This by Sandi Metz

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
(pop music) (train horn) - I'm Sandi Metz and I am the last but one speaker which means you've almost made it. (laughter) You get a break after this and then there's another keynote, If you stay for that. It's really bright up here, I'm gonna have to look at you some. So, yeah you've almost survived. Even those of you who are new have almost survived an entire railsconf, so I think we should all, let's do this, sponsors, pay the bills, they do, we're glad. (claps) Thank 'em. But even more than that, human people organize this conference and if you see, this is your job before you leave today, find someone in one of those red shirts and say "Thank you". Aight, let's thank 'em here. (claps) Thank 'em in person. Start my clock, I have about, I really do have about 40 minutes. I don't have 500 slides of code this year so (laughs) it's not gonna be that bad. Yeah, let's just go. So, I'm Sandi Metz, I'm really happy to be here. And I haven't talked for you this year, this talk is about code smells. This is a term invented by this guy so, really, we did not plan that I would follow Katrina but it's the perfect talk to follow her talk. She just mentioned this guy's name, it's one of the last things she said. This is Kent Beck, this is Martin Fowler, he's the man who wrote this book. Which is the book that teaches us how to do refactoring. They collaborated together on the third chapter of that book and that's why they want, it's like naming things wins, and the name code smells they wanted. And so the reason you know that term today is because of what these guys did back in the 1990s. Now, I wrote a book a couple years ago, before that I wrote code for 35 years, I went to my desk everyday and I wrote code. And now I don't do that, I teach, I teach classes in object oriented design. And in my class I have occasion to ask people if they've heard of code smells, and just like I suspect all of you, everyone in my classes they always say, "Oh, yeah we know what code smells are." And then I ask them to list five and no one can. Alright, okay I can hear you trying, but really most of you cannot. (laughs) I know that, okay. And so we all think we know about this term but it doesn't mean I don't like your code and I can't tell you why (laughs) that is not what a code smell is. There is some opinion involved but really it's not just, it's not just that I disagree with how you wrote your code, the standard is higher, these smells, these 22 different smells all have very precise meanings. And the power, the magic, if you will, of this list is that they've given things names. Once you give a complex idea a name, if we could all just learn what that name stood for it means that we could talk to each other in a unambiguous way without having miscommunications. And so, one of the things they talk about, very often when people talk about code smells, they prefix code smell with the word bad. They say bad smells. As if, but really the definition of a code smell is that it might indicate a problem not that it does, that it might. And so, you don't have an obligation to filter out all the smells, it's actually important that you not. And it's worth, it's also worth getting through with code smells because they have such great names. Okay, look at this list, feature envy, that's cool. I like this one the one that needs a code of conduct, inappropriate intimacy, shotgun surgery that's another favorite, okay. And so, the problem with this list, well, first of all, okay I'll confess, I had that book for a really long time before I read it. I had a really hard time with it, right? It's one of those books, it's like a recipe book and I've heard it described as a cookbook for people, it would be like reading a cookbook if you did not eat. (laughter) And so I really need the story arc and I had a very hard time following along, like persisting with a bunch of recipes that were just like shrug, shrug, shrug, shrug. Alright, but it turns out it was really worthwhile when I finally did it and actually Katrina made me, Katrina made me. So, this, there's 22 things on this list, I had a stack overflow at 22. It turns out there's a guy named, whose name I can't pronounce Mantyla, it will be in the credits, he wrote a paper where he grouped them, we'll throw those two away, he grouped them in five different categories. And through the magic of keynote, I can do that. This is the only reason we make talks, so we can use the effects. (laughter) And so here, let's just talk about this set. Okay, this is a list of things that just do not need to be that big. Long method and large class are probably self-explanatory, data clumps is when you have two or more pieces of data that always appear together, pass them around over and over again together. Long parameter list is obvious, it might only occur once but if it's long enough, there's probably an object in there somewhere. And this thing, this other wonderfully named thing called primitive obsession (laughs) we saw an example of that in the talk Katrina just gave, this is when you have like, an instance of a base class, like a string or a number or a hash or an array and you pass it around to a bunch of objects and they look at it and decide what to do based on something they know about it. So, you say "Oh, I've got a number and it's six, "so I'll do thing x." Or "It's eight" or "I'll do something else." Right, that's just it, if only the thing you got was smarter you could just send it messages so primitive obsession is when the objects are too dumb that you're passing around. These things are groups in a category called bloaters. They make code bigger than it needs to be in the places where you use 'em. The next group, this one, these are things that, these are ideas that are available in object oriented programming, that you can misuse. Switch statements, you know they're conditionals by, in normal people talk, that's conditionals. Refused bequest is when it's an inheritance problem, you have a sub class that overrides a method that it inherits from a super class and like throws an exception and says "I don't implement that thing, I refuse the bequest." Alternative classes with different interfaces is pretty obvious. The other thing is temporary field, it's interesting that temporary field is on this list, right, temporary fields can be really handy but sometimes they mean that you should've made a method with that name, right? Why are you giving it a name? What is it about the code that you have now that feels like it needs that name? And so these things are all grouped in a category that he called tool abusers. I have a lot of bikes, I work on bikes, I have a garage full of bikes and I'm a amateur mechanic which means I have amateur tools which sometimes involves a very short wrench, a long pipe, and a hammer. (laughs) Right, and I can tell you it almost always turns out badly, if you abuse your tools. Alright, next, this group, this is stuff that makes change hard. So, divergent change, shotgun surgery, which we've talked about, parallel inheritance hierarchies, which is pretty obvious, sometimes you have a couple of hierarchies that each have two sides and every time you change something you've gotta go add or move in both sides of the hierarchy. These are the kind of things that keep you from wanting to change code, or make code hard to change. Now, notice that, almost everything I'm talking about if nothing ever changes, it's probably okay. Like, code that, really embarrassing code it's fine to keep really embarrassing code, you should be brave about your ugly embarrassing code. Because it is not costing you money if it's not changing. And so just because the smells exists, you know, sometimes you should like own 'em, be proud, walk away. Don't let people make fun of you about having bad code. This next, this next category lazy class, (laughs) speculative generality, okay on top of the effects, finding the pictures is also fun, (laughter) classes that don't enough is a lazy class, right? Doesn't justify it's existence. I'm gonna skip speculative generality for a minute, data class, you know we're object oriented programmers, classes oughta have data and behavior. Duplicated code is pretty obvious. Let me go back to speculative generality, I'm gonna ask you to raise your hands, who in here has ever written some code for a feature you thought might arrive in the future? Keep your hands up for a minute, alright, I'm gonna out myself with you here. Who in here has ever, after many months of working around that code, ripped it out and thrown it away? (laughs) Okay, we are bad guessers. And you know I love object oriented design, it's a thing that really interests me, but this thing of speculative generality where we say "I'm gonna do something really cool "in my code for some feature "that I think we might need later." This is why people say bad things about OO, alright, this is what they blame us for, it's primarily things in that category. You have to be right so the few times that you're right have to be really big wins to outweigh the enormous cost of being wrong. Code is read many more times than it is written. The cost that we, the reason that we cost money is the time we spend reading code and if you add generality, you increase the level of abstraction of code. Very often that means adding levels of indirection which humans are terrible at and it means that every time someone looks at that code it's harder to understand. So, we should really try to restrain ourselves and not speculate about the future. When the new requirements come in they'll tell us how we wish we'd written the code and we can do it then. Dispensables, sorry here, ah see I did that thing with the clicker, dispensables, you've all seen it now, okay, so we'll move on. So, the last category here is this group, feature envy, inappropriate intimacy, message chains, and middle man. Feature envy is when I have an object, Joe down here, Joe's an object that I know about and I send him way more messages than I send myself. Could be that I'm more tightly coupled to Joe than I know, right? Inappropriate intimacy would be if Joe had a bunch of private methods and I reached in and got them, okay, that would be bad (laughter). I really (laughs) I really am sort of pushing the code of conduct aren't I? Sorry, I hope no one was made uncomfortable by that. Message chain is the logged enter, those violations, right? You got dots, you have you send a message to something you know about and you get a response back and you send another message to that. If the types change across those dot chains that's a message chain. Middle man is if you have an object that you send messages and its sole purpose in life is to forward those messages to somebody else. Maybe, you don't need that object. These things are called, they're grouped together in a group called couplers because the effect of this is that it binds the objects together such that even if they're beautiful, even if you've tested them, even if they're little works of art, you can't ever reach in and get one out and use it in another context. They come as a bundle, all or nothing. And so there you go, 10 minutes and 34 seconds, everything you need to know about code smells. Okay, but we're not done. (laughs) We're not done because now I'm gonna talk about refactoring. But not very much 'cause you just heard a talk on refactoring. But there's a thing here that people don't know. That those guys discovered in the 90s that I want you to go away today understanding. And it's this, refactoring, just like code smells have names and they mean very specific things, refactoring have names, refactorings have names they're very specific and they come with recipes. Not hand wavy recipes, very, very specific concrete recipes. Here's one, this is page 149 of Martin Fowler's book and it looks like a recipe right? It has numbers down the side, there's little optional clauses here for situations that might be different in your case. You notice that it refers to other recipes. Here where the things are in capital letters, that's another whole recipe by itself, it's recipes within recipes within recipes. And so all of the refactorings work in the same way, this is not something, we don't just wave our hands and say go refactor. Refactoring has a very specific definition, it's to rearrange code without changing its behavior and all the ways in which you can rearrange code are already written down with instructions by people who really thought a lot about this. And so now you know that code smells have names and they're real things and refactorings have names and they're real things and they come with recipes, I can give you one last bit of news, every code smell maps to the curative refactoring recipe. Ponder that for a minute, what does that mean? Here's a cheat sheet, this one is provided by the guys at Industrial Logic. Notice on the top, the code smell they're talking about is data clump, this is a little tiny definition of data clump, that F 81 is a reference to page 81 in Martin Fowler's book. The three things on the bottom are the refactoring recipes that are curative for that code smell. So this slide, I just blew it up so you could see, I extracted it from this pdf, which is a couple pages long, it cross references all the code smells and refactorings in Martin Fowler's book, the refactoring book and also a book by another guy named Joshua Kerievsky called Refactoring to Patterns. And so, it turns out that this is all you need to know, the problem is solved, you do not have to reinvent this wheel. (laughter) And so, it turns out if you just learned all you need to know is a few things. And many of you, at least in my experience, the reason I wanted to give this talk is my experience from teaching is somehow I think a generation has passed since all these books were written and that people who are new to programming in the last 15 years, I'm a woman of a certain age, you can tell, if you're new in the last 15 years you may not have this information. I'm gonna show you some code, now. I'm gonna give you, I'm gonna use the last, I don't know, we're gonna spend about 15 or 20 minutes looking at code and I'll show you the practical effect of recognizing code smells in your code and doing refactorings. My class sale is a subclass of persistence you can think that as active record. If you're in the back it will not hurt my feelings if you get up and come forward. That's the font size of my code. (laughter) I didn't know I was gonna be in the key note room it just happened. Okay, so we have that and let's say I have my class foo, it has a sales total methods takes params and maybe this is control like thing or something that will control calls. It knows the name of the sale class and it knows some other things, right? It knows that sale understands where and it knows that thing that comes back is a response from sending an aware message, it knows sum. It also knows two attributes that are in the sale class and it knows the name of date and the name of cost and it knows that the, it can pass a date range as an argument to where and the query will work. Okay, well, that's fine. And then someone else comes in and does this, later, someone makes bar and bar's a lot like sale but they want weekly totals, here, it takes params and you only need a starting date to do this, so I can calculate ending date, right here, and then there's another thing here that knows where and sends sum to the thing that comes back, it knows date and cost, takes date range. Then, later so this is like agile, right? People are taking stuff off the backlog this is what happens when you don't have code ownership and don't have oversight, I love agile, I'm not saying agile is bad but I'm saying I see a lot of code that looks like this 'cause people solve the proximate problem and no one has the big picture. So, here comes, oh yeah, of course now I have expenses, if I have sales that's gonna happen. Now we've got baz and there's expense total it takes params, does this, that looks a lot like the other stuff and then this method blows up. 'Cause someone passes in a date, a bad date, a bad string for dates, kaboom. And so someone comes in here they get that bud report and they come in here and they fix it. So now I got this code. Let's just stop a minute and try to identify all of the ideas in this one slide of very simple code. There's the idea that I can calculate a week, I know that. There's the idea that dates might, they might be pass bad dates and I can set defaults. There's the notion that start and end date go together as a group, always, when I need it. There's the idea that I have, I know messages that I can send away to sale and that other object. I know the name of that attribute and I know the name of this attribute. So I got all this stuff, it's morphed up a lot in different ways here. And it's still not so bad, right? If nothing ever changes, I don't know, maybe you should walk away. But here's what happens in my life, this is when I go out on the wad I often, I spend time at businesses very often that have been successful, so that means they're five to six or seven years old and they have enormous code bases that they hate. Right, that's why they call me, that's where I go. I mean, you can imagine, right? So if your code bases at home feel big and embarrass you it's probably because your business has been successful. It's just the way it is, if we live long enough the chaos accumulates. And so here, what happens, in these situations is after you have a foo and a bar and a baz and someone comes and makes a Larry, Curly, and Moe. And they do kinda the same thing, right? And then, someone does a fee and a fi and a foe and then your code looks like this. And eventually, through the power of keynote, (laughter) you have duplication and message chains and data clumps and you have to do shotgun surgery and if you get that long something breaks in production and all the validation is different in different places and all the defaults are different in different places and you find yourself unable to understand this code. It feels like the accumulation of simple problems has created an overwhelming mess. And it feels like you need to understand everything in order to fix anything and I can tell you from personal experience that if you try to attack all of the problem at once you will never finish, it is not possible to clean up the whole mess at one time. You can't tell 'em "Shut the doors, "we're gonna go a big two month refactoring, "it will be fine." That goes over really well with the people that pay the bills. So what we need is a way to reach in here and somehow see, we need a way to pull one problem out and fix it, in confidence that it will work and that's where code smells come in. We're gonna do data clump, we're gonna find a data clump and we're gonna fix it with extract class. It's gonna remove those three colors. Here's the data clump, this is behavior that goes with that data, this behavior does not belong in bar and baz it belongs with whatever object I should make here. And I'm gonna skip the, I'm gonna spare you the refactoring 'cause really you can look it up. And my name sucks, sorry. So, here's date range, takes two arguments and those have set defaults, has two methods one that returns a range and one that returns a week rage. This is an object that stands in for the data clump, I could use it in that place. And they way you use it is like this. So, in foo, I'm about to make this method more complicated which is why people complain about OO, let's do it, okay? I'm gonna get an object, temporary variable, I know that temporary variable that's a code smell. And then I'll just plug it in right there. If you run flog on this it got worse. I introduced a whole new class and this method is longer. But watch this now, this one, okay, well I don't need that anymore I can just do it, now I got this, and the other one, I don't need that anymore, I can just do the same thing, now I got this. And so, these three methods, there's the data clump, right there, the cool thing about data clumps is that if you take it, if you find the data clump, you isolate them, you make objects for them, the behavior will coalesce into the object, it's like a Field of Dreams kind of thing, alright, if you build it, they will come. And what that means is that you can use date ranges everywhere and get consistent behavior throughout your apps, the weekly range, all the validations work the same in every place, all the defaults work the same in every place, if you change it, the change goes everywhere. And everyone in your app knows to use this they would prefer to do this rather than to roll their own in every situation. You guys have tons of data clumps in your app, if the only thing you've learned from this talk is to come and make objects out of them it's a big win, alright? But let's do more. There's a message chain here, oh I hate this message chain. I so hate it and I'm gonna have to get back to my notes 'cause I wrote a lot of things down about it. So, what, I see this everywhere, right? I am way out in my own objects foo and bar and baz, and I have a message chain that reaches into my persistent object and then send messages to stuff it gives me back. It's okay for my class to know things about sale but it is not okay for my class to know things about things that sale knows about. And you know, it's really hard, I find it hard to convince people about how bad this is. And I drew you two pictures, two completely different pictures to try to express the same idea, here's the first one. This is about the message passing, so I got my guy foo, there's that sale thing over there, and I send where to sale and then sale inherits from persistence, the active record for you guys, you can fill that in, and so that message chases up the hierarchy chain and then, but behind persistence is this whole big enormous cloud of code that somebody else wrote and gave us for free. Right, we love them for it but up in there somehow there's a list and there's a bunch of other stuff there's all kinds of things that happen back there. Eventually, somehow, persistence sends some message on, I don't worry my pretty little head about what that message is. And then, some comes back, I get this list back. It comes back to sale and then it returns it back to foo and the next thing foo does is send a message, alright, that's what the message passing looks like. Now, I'm gonna show you this picture in a different way, this is how I think of it, so that's how I think about it when I'm thinking about messages. Here's how I think about it when I think about testing. Trying to test foo, foo has collaborators, it knows about date range and it knows about sale. These are the immediate things, I can put a ring around these objects. When I'm writing the unit test for foo, I have to get instances of those collaborators and set them up in order to make my test run. Alright, that's how I set up different contexts. However, here in this case, foo knows about that. Something that's not a direct collaborator, it's the next ring out, it's in the next circle. It's where the dot is, every dot jump a ring, here. And so what I did, what's happening here is I know about my collaborators' collaborators and if you do this, you probably seen the effects of this in your code, if you don't wanna run a database query here you have to create, stub, you have to stub in stubs, or mock in mocks. Or in any situation where there's a message chain, sometimes you get in this situation where you're trying to set up a test and you have a million objects, right? You have instantiate a bunch of things, it's this kind of message chain thing that's the problem. If you do that, you're gonna hate yourself. And I'm gonna go a little bit more into testing about this in a minute, but first, I'm gonna just fix the message chain, it's really easy to fix this. So I got that problem, all these things they look just about a like, the problem here is that there's a concept that doesn't have a name. That's what happened, I have a stupecation and there's an idea that underlies it and I haven't given it a name. Now, one of the things that happens a lot of the times when you see this is that there's a method name with a repeating prefix or suffix. And when you see that, what you know, almost inevitably you have an object that's trying to get out. And so what this means is that I can hide the delegate by putting a total method on sale. It's as simple as that, right? I'm gonna write my own method, you would probably use a name scope for this. Alright, I'm gonna write my own method, I'm gonna put it on that class and then I'm just gonna change this to synto and it's gonna happen on expense, also, of course. So, once I'm done that I end up with this code and there's no law of demeter violation here, I don't have a message chain up there and so we fixed it here, we've hidden the delegate. Now, I wanna talk a little bit, Justin Searls, who's somewhere, bless him, gave a talk a couple years ago, I don't know how long, about how much reality you want your test. And I can recommend it to you if you haven't seen it, it's a couple years old, now, he can probably tell us what year, 2013. Look up Searls and what's the name of it, he doesn't even, (background chatter) bludgeoning reality, okay. So, let's look about, let's look at a kind of test you could write for this code, you could do, well okay, so I know, I'm sending total the sale, right? Foo is really my sale is sort of part of the framework and sort of mine, right? It made a devil's bargain when it inherited it off persistence, for the benefits it would get to pay the price of that dependency. Alright, I'm happy with that bargain. Here's a test I can new up a new foo, I can send a message, I can check the output that comes back. This runs the database query, I'm a long way from the database, foo is not a subclass of active record of persistence but it still ran an entire query at this point. And if you do this, in enough of your code some of you probably already had the experience, I'm gonna look at your faces and see if I can tell who, you've had the experience of your test suite running more and more and more slowly as you get more and more and more code and then finally, here's what happens, it falls down. If you can quit using, if you want to refactor, if you wanna do the kind of refactors that Katrina was showing you, you must have unit tests that run quickly. And if you couple the unit tests for these objects that are far away too, if you have a couple unit tests for your objects to behavior that you don't own that's far away that's very slow, you're going to be unable to refactor with gree-se-wall at your back. And so it's really, really, really important like we want your test reach to run but even more than that I want them to run quickly. Okay, well let me just go on. I was about to diverge from my presenter notes which is always a bad idea. So the problem here is I'm glued to this class, I'm glued to sale, I know the name of this constant inside my method. And I could, instead, depend only on the name of the message I want to send. I could do that by injecting a model. Now, I am not unaware of the dispute that we sometimes have about dependency injection. But I think it's great and I'm gonna try to convince you that you should be using it more. If I do that, then I can now do this, I don't really think, I'm not very attached to sale as a class anymore, I don't really care, I think I'm talking to a totalisable and if I decide that I'm gonna do real OO and think of objects in terms of the roles that they play instead of the class they are, what it means is that I'm very comfortable with this idea of decoupling myself from constants and injecting player's roles. If I do that, I can make another player of that role and it in my mind it is equally valid, it is just as good, all people, all things, see I polymorphize, everything that influenced this message is equally good, the same thing in my eyes, and so in this case what I can do, I'm just gonna clear a variable there and make that a little simpler, what I can do is get an instance in that model and inject it in my test and then I have to assert that the right answer comes back. This is fast, it's really fast. You know, what does it prove? I know people, many people are uncomfortable with this so let's talk about what it means to do this test. This test proves, that my method, if it's injected with a totalisable, somebody implements a total method, we'll call that method and return the result it gets back that's what got proved here. What it does not prove is that database cruising rails work. Okay, it does not do that. But let me ask you, the rails framework has thorough and exhaustive tests for whether or not their database queries work. In addition, my sale class, the sale class is a subclass of persistence, it may be that I have a test on total over there that actually runs a query but it is not necessary for foo to jump across this message chain and do database query, jump across the network and do database queries at the other end. I see, when I travel around slow running tests are killing people and I think the tests that I see are running slow for two main problems. The first one is this message chaining if you have message chaining in your code if you commit demerol violations it means that you have to new up the whole network of objects and run all those messages when you run your test. And that's gonna be slow, it's gonna be hard to understand and hard to maintain. So, you should hide the delegates, you should hide the message chains with delegates. The next thing is even after you've done it which we did here, it's possible that you are tightly coupled to something that's really slow. It's really slow and if you tightly couple yourself to slow things and don't give yourself a way to substitute other faster players of those roles, you are doomed to slow tests. Now, I realize it is possible, here to stub in sale, right, I could stub that method but, and it does work, but I prefer this and it's for, I have a reason it's not just that I like this code better, it's that this makes you think of those objects as players of the role, not as instances of their class. I can use this totalisable double any place in my test where I want, I could use it over the expense test too, it's a really different, it is not the same thing to inject this object and break the coupling, stubbing in your test is not equivalent to injecting the object and breaking the stubbing. This is a very much more powerful idea that will improve all of your code not just make that one test faster. So there's one more thing, let me see how we're doing on time, we're doing great. Okay, so I'm gonna do one more code refactoring before I finish. Once I'm done that, now, that I'm here I have the duplication here, there's thing called pull up method, pull it up into the super class, I'm not gonna break open active record and monkey patch it with total, seems like a bad idea, doesn't it? But we can use a module, here. We can put that right there, and then, notice what I've done, the code that I've put in the module does not look exactly like the code that I am promoting from the sub classes. I did, I added some indirection, I injected, this is just like what I just did with model equals sale, in the last example. The things that I had concrete dependencies on my class I am now injecting as variables and setting defaults. This is so it's exactly the same idea, right? This gives you flexibility without adding much complexity, now, there's a name for this code smell, and it's called speculative generality, right, I just did it and I know I admit it. But here's the thing, if the methods are short, so that, what we want, the problem with speculative generality is you're wrong and it costs you money because it increases the complexity of code, in the mean time, when you try to read it. And I assert to you that at least for me, I know it's partly what you're used to, for me my methods are short and I routinely inject the dependencies. And so I do not find, I find that the increase in flexibility is, more than outweighs the increase in complexity. This does not feel very much more complex to me and it's way more useful. Now, anybody can call this method on a date, on any attribute, and sum any value and so we would use a module. Okay, wait I just put that in this morning which is why I didn't know it was in the slide. Dependency injection is awesome and you should be using it. So we can do that use the module just like there, so there we go. And so that's it, if you're not intimately familiar with code smells you can move yourself, if you're waiting to move up to that next level of programming, to make that transition to being to the next level of proficiency, the way to do it is to go on code smells and to learn those recipes for refactoring. These ideas are not new, they've been around, that book was written in the 1990s and I know that many of you here probably began programming since then, for some of you this book is older than you are and so you might have a sense that it is (laughs) part from The Old Testament of programming. (laughter) But it's a body of work that is practical concrete advice about how to write code. And if you're unaware of it you should go learn it. Many problems that we have, that feel insurmountable can be solved by purely mechanical operations. And the cool thing is it doesn't take the fun out of writing code, it's not like there's nothing left for you to do. What it does is it removes the tedium safely, so that you can concentrate on the harder problems. So when you learn code smells it's like putting on glasses, right, it turns that mess into something like this. And following the smells lets you make straight forward easy to understand objects, that are easy to test and a pleasure to reuse. (laughter) Wait for it. (laughter) So, while you're learning code smells you should look at Reek, is Peter here? Maybe not, okay, this is, notice the wonderful icon, is that cool or what? So Reek is a static analysis tool that you can run against your code that will tell you what code smells you have. So you don't even need to really go figure it out you can just run the damn tool on your, (stutters) sorry, I have a policy never to do that from stage, you can run this tool on your code and it will tell you what to go look at. So smells aren't a bad thing, they're actually great. And they're all over our code but you have to kind of lean in to them, like I okay, I have a new puppy and if that were my puppy he would reach in and bite off one of those petals and you should do it too. It's time to learn more about smells. They're not bad, they're just information. And many of, much of the information is neutral. If you're trying to lose weight maybe you should avoid pizza if you've been on a long bike ride it's the best smell ever. So, when I look back at my old code, code I wrote three years or four year or five years ago, it's really common for me to look at the code and say "What fool wrote this?" It's a wonderful thing about our jobs, it's the very best thing. What job can you imagine having, can you imagine having a job where you were no better today than you were five years ago. It's such a depressing thought. I love looking at my old code and hating it, 'cause it means I'm better, it means I've learned something since then and what a wonderful thing that is. So, I started this talk a cup of coffee and I'm gonna end this the same way, right? It's late I know you're tired probably not the best time to go drink coffee, right now, but tomorrow morning when you get up, it's gonna be a great smell. Go learn the code smells and level up your game. Thank you. (clapping) Oh stop it. Oh wait, I swear this book is so close to being out of beta, I know that you've been very patient with me but it really is coming, it's at the editor right now, it's going to be great. I have to say, writing is very, I find writing tortuous, I'm to the point now where I'm really proud of it. So, you may want or may not enjoy it. (pop music) (train horn) (train horn)
Info
Channel: Confreaks
Views: 39,248
Rating: 4.9862227 out of 5
Keywords:
Id: PJjHfa5yxlU
Channel Id: undefined
Length: 38min 14sec (2294 seconds)
Published: Sat May 28 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.