 in the Chicago area because we don't have any customers. We just created the money that's owned by the partners and it's a very different kind of work experience and I'm loving it. And if any of you are in the Chicago area and interested in talking about that with me later, please feel free. I maintain the RSpec project recently released version 2.1. With the 2.0 release, the new thing that we got going is all these cucumber features are being displayed on this website called Relish App. And it's just a beautiful presentation of all the documentation of the code which is actually executed before we push it up there. You can't run it on the site but all of the documentation is actually executed against the code base and it looks like that. Beautiful, isn't it? Yeah, that's what I'm talking about. And the other little bit of good news, housekeeping stuff is the RSpec book is actually going to the printer tomorrow. I mean, after about four years ago I stood up, not at this podium, but at a podium at RubyConf and said, hey, it's gonna be Q1 of the coming year. Yeah, this time it's actually going to the printer. There's a discount code for any of you who wanna buy the combination of the print book and the e-book and this is the discount code. It's 20 underscore ACHBD underscore RubyConf in snake case. All right, 20% discount expires Monday, get it while on time, it's not even on the presses yet so. All right, but this talk is not about RSpec. This talk is about duplication. Now, we all know that duplication is a bad thing and the reason we know that is because we've been hearing about this for a long, long time. In Martin Fowler's book, Refactoring, he talks about code smells, which are things that you notice in code that kinda smell fun and one of the code smells he described is duplicated code and then Uncle Bob Martin in his book, Clean Code, said, duplicated code is the root of all evil in software design. This is actually, I think this is traceable back to Kent Beck like a few years before but I know I've heard that, that's a statement a long time, for a long time. And then of course there's the drive principle which everybody here has shown. So on the RSpec mailing list, a lot of people write in questions about the drive principle and it comes up, there's something like every week someone's asking about, how do I make this more dry? Isn't this, can this be more dry, whatnot? So I was curious and I did a little bit of research. I went to the Google and I typed in Ruby RSpec. I had to preface it, prefix it with Ruby because it turns out that there's a couple of other RSpecs in the world. There's a car, there's a Hyundai car called the RSpec. There's a spectrographic monitoring thingy that I don't know what it is but it shows cool pictures and it has to do with stars. So anyway that's RSpec and you can Google that. And then the other thing is something about swimming pools, like the S stands for swimming, S and P stands for swimming pools. Anyway so, and then I Googled Ruby RSpec dry and it turned out that 6% of the hits for RSpec also had the word dry in it. And then I thought okay well I wonder what that looks like for Ruby on Rails, right? So it did the same thing with Rails and it came back 3% though. So that was a little less but the real surprise for me came when I checked out just Ruby. Ruby language, now I had a Ruby language dry and 11%, more than 10% of all of the pages on the web that Google could find also say dry if they say Ruby and language. So people in this community really care about this. So one of these emails that I got had this subject, custom matchers, shouldn't they follow the dry principle? And basically there was a guy on the mailing list and he was trying to write a matcher library for like RESTful services, HTTP requests. And he wanted to write these two matchers. Is there anybody here who doesn't know what RSpec is and what matchers are? Good. Sure about that? Okay, one, okay. Seriously? The one who raised your hand? Okay, it doesn't really matter, it's just some code that we're not talking about. So here in this example, these are like texts, right? So they're executable code examples. And in the top one, we make a post and it says the response should be created and he wanted to create this be created matcher. And what that really meant was that we got back a 201. And then he also wanted to have an alternative which is this should have creative resource which would do both. It would check that it was a 201 and it would also verify that the object actually got created and stored in the database. And he wanted to make the underlying code for these drives, he felt that he couldn't do that. And so this is not the code that he presented to me or to the list, but I imagine that it looked something like this. So we've got the two matchers and so in both of these we say RSpec matcher is defined and then the be created and have created resource are method names, this thing defines methods. And it's important for what I'm talking about if you were to realize this actually creates two different objects, this code. All right. So, and you can see there's some duplication, right? We've got three appearances of comparing response code with the strain 201. And so he wanted to get rid of that duplication. And there's also these strings, the failure messages are very similar. In fact, they're identical because the second one could fail for two reasons, so it fails for the same reason as the first one, it would be the same message, otherwise it would be the same message. Now this is what he actually said he wanted to do. So you could see the top matcher is the same, but the code in the bottom one changed a bit. And so let's look at what happened here. So he said, I wanna be able to depend on the other matcher because the other matcher already does this comparison between response code and the string 201. But what he's doing here is he's creating this instance of another matcher and then calling the matches question mark method, that's a Ruby predicate, which is part of the underlying matcher framework. It's not part of the matcher DSL. So there's two problems that are introduced just by that one line of code. One is we're creating this dependency between the two matchers. And the other is we're letting the abstraction leak the internals up, right? So both of those are bad things to do. Similarly here in the be created and calling the failure message for should, it's calling it on the be created matcher. And again, we're depending on what's happening in the other matcher in order to do this. And now this one's a little bit more subtle, but what's going on here is there's this instance variable at message. And in this case, the part of the code that's manipulating that bit of data is not the same part of the code that we're gonna use to access it, right? So there's a weird dependency here. First of all, just looking at the code at the failure message for should block, you don't really know what's going on right away with that data. And second of all, they have to be called in order for this to work. Now it happens that in this framework, that's gonna happen. Framework calls them in order, but that's a weird sort of dependency to have in the code. And so by reducing the duplication in this way, the end result is that we've increased the coupling between the two matchers. And this is really true. Every time you reduce duplication, you're gonna add new dependencies and you're increasing coupling. Both of those things are bad things. Well, they're not both bad. Dependencies we have to have, right? The important thing is to be able to manage them. And so it's important to depend on the right things. So how do you know what to depend on? Well, there are a number of principles other than the drive principle that help us figure that out. So one such principle is called the dependency inversion principle. Now, it's a little bit more complicated than this, but the gist of it is depend on abstractions. Now, that comes out of that it was originally described in the context of statically typed languages. And in Ruby, kind of everything's an abstraction at some level, right? So in terms of trying to apply this to Ruby, we can rephrase it like this, which is depend on the things which are less likely to change. Because that's the reason we want to depend on abstractions in statically typed languages because the high level, the method names are not the things that change, it's the underlying implementation. All right, so with those things in mind, let's take a different look at how we can refactor this. So we still have this duplication where we're calling response code and comparing it to 201. The real problem here, the duplication is this magic number 201 represented in a string that keeps coming up. We all know that 201 has this meaning for us, which is that it's the status code to get back that says something got created. But, and this is sort of an unlikely example, but imagine that that code changed. We have to change it in all three places, right? So obviously it's unlikely to happen in this case, but a typical thing to do would be to give it a constant so that it's only defined in one spot. And then that way, if it ever does change, you change it to the one place and all the other places that reference it get the benefit of that change without having to change themselves. Another thing we could do is actually just add a method right onto the code object. It's a string, most likely. And we could just ask it, are you the created status code? So let's leave that there now. And then we've got these two strings that are identical. So rather than trying to have one matcher depend on the other matcher, we can have them both depend on something else. We can have this failure messages. I'm sort of making this up as I go, but this would be a perfectly reasonable solution. Have this object that creates failure messages for us. Give it a little bit of an API that makes sense in the context of the matcher. So failure messages, expected response code for created and gotresponse.code. And that would create the same message in both time, in both matchers. And if we ever wanted to change that, we would change it in one place. But now that we've done that, even though this bit here, this other failure message isn't duplicated anywhere, at least in what we're looking at here, it still looks different from all the other failure messages. We've got this sort of imbalance in the level of abstraction where we've got a concrete little here with that string. And so compared to calling out to the failure message generator. So there's sort of, I don't know that there's a principle for this. If someone knows of it and can tell me now. A slap. Huh? The what? Single level of abstraction principle. And is that, did you just make that up, or does that actually? I made it last year, so. Okay. So the slap principle. There it is. And so what we can do to apply the slap principle in this case is just do the same thing. We just put a method on the failure messages object that will create this message for us too. And when you move code around like this, nice things happen. Like all of the messages start to get created in the same place. And when we make decisions that oh, we don't like the way they're phrased, that they're all in one place. It's just like the stuff we do for I-18N where we put everything in a Yaddle file and all the doxters are in one place and you can scan them and see them all next to each other. So this is a little bit more balanced. It's, we've got, there's a little bit of duplication in terms of the characters that are written, but we've removed the parts of the duplication that are gonna buy us, which are the things that are gonna change. So the motivation for that, of course, is the drive principle. So I'm gonna tell you a little story. I was visiting my girlfriend's family in Brazil and this is her niece, Bruna. Bruna is four years old and Bruna came up to me while I was preparing these slides to do a presentation down there. And she said this to me. I'll translate it for you, but she said, I have a computer with a computer. I have a computer with a computer. And I asked her to slow down and she actually did a great job and she said it very slowly. And what it meant was, I have a computer and then this part of the end, Jim and Chiara, I didn't really understand what she said or what that meant. And so I'm learning to speak Portuguese and so I did the thing that I do when something sounds similar to an English word. It kind of sounded like, demented to me. So I imagined that she had said to me, she has a demented computer and I was perfectly happy to live with this perception of what she had said. So a little while later, I was talking to her cousin who's an adult and the cousin said, no, no, no, it's actually two separate words. It's de menchia. And I didn't know what menchia meant. So it still didn't help me that much. So I imagined, okay, what's another word that I know? There's this other word menchi, which means mine. So I thought, okay, it's a computer of the mind. So it's an imaginary computer. She has an imaginary computer. And I was perfectly happy with that too. And I went on for another half hour, hour of my life, believing this misunderstanding of what she had said. In the end, it literally means of lie, like untruth. And so she had the toy computer and I had the computer David Dodger, which is the computer of truth. So this made me happy as well. So here's the thing. The reason I told that story is because there was this period of time where I'd heard something and I was satisfied with my understanding of what that meant. And there is probably a fair number of these people in this room I'm gonna guess. Like how many of you think the dry principle is don't repeat yourself? Oh, that's good. Okay, actually, that's not what the principle is. That is a device for you to remember what the principle is. The principle is actually this. And this is what's printed in the book, The Pragmatic Program. Every piece of knowledge must have a single, unambiguous, authoritative representation of that system. So we're talking about pieces of knowledge. Bits of information, things like 201 has a meaning which is created. That should have one representation somewhere in the system. And there should be one representation. It should be unambiguous and authoritative. And what that's about is, and I think, I don't know, Dave and Andy were at this part together, I imagine, but they were talking about, so if you have a situation, consider active record, where we have representations of the attributes of a model that live in a couple of different places. They're in migrations. They're ultimately in the database and then they're in the schema file. But really, there's only one authoritative source for that. We write migrations and we generate the schema file from that and that generates the right time information about what those things are. So even though it appears in a couple of different places, it's still dry in that case. So with that in mind, let's look at another example. I'm working on an app at the company where I work and this is an application for allocating things to other things and there's a part of it that's a little Java web service and we're using this framework that asks us to represent the different paths in this manner. So some people might look at these three strings. I know they're kind of small, but I'll show them a little bit bigger in a minute and think, oh my God, they're all exactly the same. There's a lot of duplication here. Let's see what we can do to dry this up. So the first thing you notice is that each one starts with the word allocations. So we'll put that in its own constant and then we could use that constant in the generation of the other three, which are the actual paths that we're interested in. Then the next thing you notice is that source type shows up at the beginning of each so we can pull that one out also. And then you've got the same thing with target type and target ID and the year and month keeps showing up as a pair so we can put those all in their own constants. And so, okay, that's kind of nice. Maybe it's a little bit bleeder. There's no duplication, but still like source type and source ID, they both start with source, right? And then source type and target type end with type. And there's all these slashes and curly braces everywhere. So why don't we take those and we'll stick those in a red. And so now they only show up once. And then, so the problem now is you've got these lines in the middle that all start with delimiters, you're in a one and end with delimiters two. So we put those into a method and so you can clean it up a little bit. Here's the thing that's awesome about this. Imagine that we decide we're gonna go from snake case to camel case. I mean, the other way around from camel case to snake case. So all you need to do is go to the ID, make the I lower case and put a underscored front of it, do the same thing with type and you're done. Amazing. All right. So, what's that? I'm making a joke. Here's actually the point. Imagine there's a test failure or something goes wrong in production and I see that, hey, someone was trying to get to this path and I need to look at this mess and figure out which of these paths this thing lines up with. Compared to this, with all that duplication, you can just look right at that, scan those three paths and go, oh, it maps up to the middle one. So we started off with some strings with some duplicate letters and words. We said, oh, that's not dry enough and so we tried to make it drier and drier and drier and eventually ended up with something that's absolutely useless and silly, right? So the point of that is that dry doesn't mean don't type the same characters twice. That's not what it's about. And the reason I'm carving on this is because I see this all the time. People go way out of their way to reduce every single possible thing and it can make code really unreadable. And the underlying issue that Dry is trying to resolve is about duplicated concepts. It's about isolating change so that when changes come in, you only have to make the change in one place. All right, so you see some duplication and so how do you know whether it's really a problem or not? So think about its purpose. So in the case of the matchers, there's some kind of calculation there. There's some, it's doing some comparison. Whereas the strings are just there to represent patterns that you should be able to scan. So they're functionally very different things. Think about the risk of changing more and not changing that particular code. What happens if we leave the duplication from the strings in place? Well, maybe we'll get four, five, six, seven more of those and it'll be a longer set of strings but we still want to be able to scan them. So in that case, it probably makes sense not to change them whereas with the matchers, as it gets more complicated, we really do want to pull out the things that are duplicated and the risk is that you're going to have to change it in more than one place. And here's the thing about that. It's not about typing. It's not about the tedium of having to change it here and then having to change it here. The problem is that you go and you change it here and you don't realize that you've got to change it here also and you've got two different parts of the system that are behaving differently that should be behaving identically. That's the real risk that Dry is trying to help sell off. You might forget to change it in the other place. So, a little more about duplication. It's not always obvious. So for example, you can have a name that's used to represent two different things. This is one kind of duplication that's a little more subtle. And so, as an example, in that this allocation app I was telling you about before, let's say that we're allocating me as an employee to three different projects at these percentages. So, there are people who work with this application through a browser and they have to type in the percentages. And for whatever reasons, they want to type the percentages in as 50.0 meaning 50%. But the accountants who read the reports want to see 0.5 to mean 50%. And they both, both groups of users have really good reasons that that's how it should be. So, that's what we have. The problem here is that we've got this one word percentage and if we're looking at a browser, it gets represented as this whole number. Well, it's not a whole number, but greater than one, 50.0 for 50%. And in the reports, it's this other thing. And we have to store it in a database somewhere. So, we store it as the 0.5. And the way we do that is whenever we create one of these objects, we divide it by a hundred as we're creating it. And so, this was actually duplication that came out of this, right? You see this everywhere that we're creating one of these things, we have to divide it by a hundred. And we actually move, we tried to move that into the method itself so that inside the object, it would just do the conversion for us. And that ended up having some weird bug with active record where if you have a collection and you create, you add something to the collection and then, so you find the object, you haven't loaded the association yet. You create a new member of that association collection and then you iterate through all of the members of that collection. It goes and gets the full list from the database and starts instantiating objects. And I think what happens, I haven't been able to prove this yet, is that it says, hey, I've already got this object with this ID so I'm just gonna throw these attributes at it and it ended up dividing by a hundred twice. So we got, we ended up with the wrong number, which was crazy. Luckily that happened while we were in the middle of doing this refactoring and it revealed itself. Anyway. And then anytime we wanted to display the percentage in a browser, we would multiply the number. So the solution that we're in the middle of working towards right now is this. Instead of calling both of these percentage, we're gonna call them a percentage and a ratio. Now you could argue that that's a dry violation itself because these are kind of the same thing. And now we have two names for them. But really in the context of the group that we're working with, this clarifies it. Everybody knows we mean 50.0 for percentage and 0.5 for the ratio. And then in terms of how the data gets stored, it gets stored as the ratio and whenever we're talking about it with the object as a percentage, we do the math in there but we store it as the ratio. Now all works out just fine. And then now all the code that uses it can just use it, no problem. And then in the report it says ratio to end of report. So that was same name to your meeting. Here we've got the same meeting with two different APIs, which is sort of the opposite of that. So in the pragmatic programmer, when they're talking about duplication, they give this example. It's a class called line. And you initialize it with three arguments. A start point and end point and the length. So the problem with this, and we're focused on it right now but if you were just scanning this code, you might not notice. Can anybody tell me what the duplication is? Wait, I don't know. Huh? I was pointing to you but I'm really sorry, I can't hear you. You don't need the length, right? So the problem, the length is actually duplicating something we already have. The problem is there's two ways now to represent what the length is. One is whatever the client of this that creates it passes in and the other is figuring out the distance between the start point and the end point. And so you end up with a bunch of client code that has to calculate this and you potentially have a bunch of different versions of that calculation where what we should really have is this. You create it with the start point and end point and you let it do the calculation. And that sort of duplication is really hard to see because the names aren't the same, the structures aren't the same. So just be aware of that. It appears naturally and you'll see it one day and you should get rid of it. All right, another kind of duplication is structural. So here we have this first object that's got a collection of addresses and there's one that's a primary address. So we have this primary zip code method and so we go into the addresses and we say, hey, which one of you is primary? And if we get one back to use that, if not, we say, well, it's gonna be the first one and if we still don't get anything back then we don't return anything at all. But if we've got something back at that point, we return the zip code from that address. So we have a new requirement that comes in to have a primary phone number. And what do we do? We copy from one to the other and we change the name and now we have this perfect duplication that we can get rid of easily. We'll talk about that in a minute. But the thing is that this is all very easy to see when you're looking at no other context. There's no other code floating around. But this sort of duplication can appear in ways that you don't know. For example, imagine that originally this primary address is called a main address and when the name got changed, whoever the developer was didn't change the name of the local variable inside the method and so they don't look exactly the same even though they're really close in structure and that's pretty obvious right now. But maybe it was formatted a little bit differently. This is functionally the same but it doesn't look exactly the same. So be aware that duplication isn't always that obvious. That's sort of the point of that. So when you have duplication like this, the thing we do is we extract a method. And so here's what that might look like. So we've got the primary zip code and primary phone number methods are both calling to this primary address method. The thing is, there's another thing going on here. There's another code smell that should be making your nose twitch at this point. So the primary address method is going into the collection. It's iterating through everything in the collection and it's saying, hey, are you the primary one? And then if it doesn't get back one, it goes into the collection again and says, hey, give me the first one. And if it doesn't get anything back then, then it creates a new one. So this is a code smell called feature envy. And for those of you unfamiliar, the idea behind feature envy is you've got two objects. This one wants to do some operation and this one has all the data. And so this one says, hey, give me all your data and I'll do the operation. And it might even send it back updated data. And really we want to have the operation live where the data is. So solution to that might be something like this. We can have an address collection and it has the primary method on it. This is functionally the same as what we looked at before. But if you look at our primary address method now inside the person, it doesn't have to go into the collection and do all this manipulation. And the reason that that's valuable is because this isn't the only code in the system. There's probably a lot of other code in the system that wants to care about the primary address. So now we've got that piece of knowledge, how to get the primary address expressed in one place in the system that everybody else can use. So let's talk about specs. So let's imagine that on this person object we're gonna have this is like some system where you could create events that are happening in different locations. And the person has a distance to event method. And this is what we say about it before we write any code. We say, okay, so if a person has one address and it doesn't have a zip code, we should get back nil instead of throwing an error. It should handle that gracefully. So, and this is how you might implement this code example. Now the thing is, there's probably a bunch of other examples in here. This is just the one. So maybe within the with one address, with no zip code context we would pull out a before line. And assign a value to this person instance variable. And that's all fun right now. But what I've seen happen quite a bit is now you recognize, you know, the with one address context, the one right up above, we're gonna need to create a person with one address up there too. And we don't wanna have to duplicate that. So let's have two different before blocks, right? So the one in the outer context creates the person with one address, the one in the inner context, makes sure that that zip code is nil. And then we can take it a step further and say that everything in this file is gonna need a person. So we'll move that up to a before block at the top. And this is all very dry. Everything's represented once, but the problem is it's very difficult to figure out where you are if there's a problem. You have to go scan through all of these different before blocks rolling up the context, right? So we're reducing duplication, but we're introducing more interaction. And that's not an inherently bad thing, but it can make it harder to reason about the code. And when we're dealing with test failures, the last thing we wanna do is go chasing around our entire app to figure out what the hell's going on. You want to be able to look right at the example that's failing and understand the failure right away. All right, so, and then along those lines, this is a little bit different example, but. So when you first make a person, the rule is that person should have no friends. Someone has a good joke about that. So now there's another way we can express that, which is we can do this one line. So for those of you who aren't familiar with the way this works, the fact that it says describe person, we know we're dealing with a person class. And so, in the middle where it says it, and then the first method is should inside that block. When that block gets evaluated, our spec knows that we don't have a receiver for that method. So it goes and creates an instance of person and then passes that over. So these two are functionally equivalent. And you can see that the one on the bottom is a little bit less code. And we don't have the duplication between the name, right? It has no friends and then person, you should have no friends. There's like duplication in the top one that we don't have in the bottom one. This is okay for me. One of the things I really care about with our spec is what does it look like when you run these and you look at the results of it, right? So the top one's gonna create this. So person when first created has no friends. The bottom one is gonna automatically generate its own doc string and it'll say person when first created should have zero friends. So that's good enough. It gets the same point across. The problem is that this tool becomes like the golden hammer for a lot of fun. And so let's say you've got something like this. We've got a calculator and the add method should return the sum of the operands provided, right? So here's how you can drive this up using a couple of things in tools in our spec. And sure, there's less code, but it's also a little bit convoluted in this context. Like you can't really figure out, I can't look at that without studying it and make sense out of what it is we're trying to test. What are we specifying here, right? And the other thing is that the output of the top one reads like the spec, right? Calculator add should return to the sum of the operands provided. The bottom one says this. Calculator should equal five, whoo, right? So it's really important to understand context when you're making decisions about these things. What are the implications gonna be if I remove this through the patient already? So here's another issue is metaprogramming. We all love Ruby. We all love the fact that we can do metaprogramming, but sometimes we do it in places that aren't necessarily that helpful and create additional problems. And so here's a good example of that. So the person again, it's got these three methods. And if you look at the three methods, they look really similar, right? First name, last name, full name, and they're just returning the instance variable. So a really common thing to do is to make that into an array and then use the define method method to define these methods. And that's cool. We saved a few lines of code, but the problem with this is that if something fails and you start running your debugger, well, your debugger might put you in here, but you're not gonna be able to just scan and find this method. And that's the problem with this sort of approach. And now it has a really important place in the code we write, which is that when you don't know what the runtime conditions are gonna be, that's the time that you would create methods using this. So like again, bringing up active record, we have these dynamic finders that say find by username for a user, right? Active record can't know that there's gonna be a username property attribute, but it's able to create this method at runtime. So you can call it, what actually happens is method missing captures it and then it defines the method at that point. So that's a really good use of metaprogramming because you can't know, right? So it's great for that kind of situation. There's a lot of other situations that metaprogramming is great for, but again, it can make code hard to reason with. Okay, I think there's the last thing I wanna talk about, which is Rails controllers. So here's some code. This is like if you run generate scaffold, you get code like this in your controller. This is without all of the comments and it's also without all the respond to blocks. So we'll assume we're just dealing with HTML here. And this isn't the whole file where I'll show you the rest of it. So we've got this duplication here in the show and edit method. In both of those, we use params id to find a widget, assign it to the widget instance variable that gets exposed up to the view. And then it's the same thing happens in the update and the destroy methods. So based on what I was talking about before, pretty much in every other language that I've worked in and teams that I've worked with, the sort of instant reaction to this is to extract a method. So we would extract the assign widget method and then we call it from these more different locations. But this is not what we do in Rails because we have before filters. So typically what people do in Rails is something like this. We still create this assign widget method at the bottom, but you can see at the top we're declaring a before filter named assign widget and we're gonna do it on these four actions. And now there's no code in the show or the edit and there's a little less code in update and destroy. And then if we look at the other actions, yeah, those four are the ones that are all taking advantage of the, not index, sorry. Forget that I circled index, but show and edit and update and destroy at the bottom and we're all doing it. But there's also view and create. Both of those are assigning something to the widget. So the next step you might take is to take those bits of code, even though they're slightly different, and move those down into this assign widget filter. And by the way, I'm not making this up. I saw a blog post that actually recommended doing exactly this. And I believe it's the wrong direction, so feel free to disagree. But so anyway, so now we have this before filter up here, assign widget only for the six actions, so maybe we can make that a little bit smaller by saying accept for index. And then here's what the whole code looks like now. Now this is just stop out of the box, generated scaffold functionality, refactored to remove some of the duplication. Now here's the problem with this approach. Let's say something goes wrong with the create method. I go in and I look at the create method, and I look at it and I say, okay, the first line says, okay, widget saved. So there's this instance variable widget. Where is that coming from? I'm in a Rails controller, so it must be before filter. So I go up here and I look and I see, okay, there's this assign widget method, and it's used on everything except the index, so that must be being invoked before this method comes in front. So let me go see what the assign widget method does. So the assign widget method says if there's an ID in the parameters. So that happens in the, there's an ID, so in the edit and the show and the destroy the update, I think. Right, so if it's any of those, then we're gonna get it, find the widget from the ID. Otherwise we're gonna use the parameters actually we've got the widget from the parameters actually create one. And by now I have no idea where I started, right? I don't remember what method I even came in to look at, right? It was the create method. But the point is the amount of code that we're saving here to use this as a before filter is very small. And if we were to just call directly out of each method, we'd be able to look at each of these methods and know exactly what's going on. Now before filters are great for certain kinds of things. They're great for filtering. That's why they're called filters, right? So what do we mean by filtering? We mean things that should happen before we ever get to this method. Things like logging, things like authorization, right? That's what filters are intended for. And so at some level this making use of it as a tool to get rid of duplication is kind of using it in a way that it's not really intended. And it ends up creating problems. And I speak from experience here because I've been working on Rails apps for a while now and I've been in this situation where I'm trying to figure out what's going on and it's buried in some filter somewhere. And it's part of the method. It's part of the function of that method. It's not part of something that should happen before we ever get to the method. So filters can make it harder to reason about code. All right, I've got a minute and 22 seconds left. So wrapping up, many problems in software can be traced back to duplication but not all duplication is inherently evil. Duplication comes in many forms. Duplication appears for many different kinds of reasons. The dry principle is actually this. Every piece of knowledge must have a single unabiguous authoritative representation within a system. This is not about duplicating strings of characters, it's about duplicating concepts. And remember that every time you reduce duplication, you also increase coupling with new dependencies. So you want to manage this so it depends on things that aren't going to change that often. Learn about code smells. We talked about duplicating code. We talked about feature envy. Here's a few others. Get the refactoring book and learn about all the different code smells. Learn more principles. Dry is a great, great, powerful principle but it's not the only principle. We talked about the dependency inversion principle. That's one of the solid principles that Uncle Bob Martin described in the book, Agile Software Development. And there's three P's, principles, practices and patterns and I can never remember which order they go in but Agile Software Development. And then also the Prags, they have this article called OO in one sentence and the sentence is keep it shy, dry and tell the other guy. So we've talked about dry. So shy is about keeping, not revealing too much of yourself. Like if you're an object, you should keep all your data to yourself. It's kind of about data hiding but it's also about reaching across and getting stuff. And tell the other guy is a device to remember the tell-don't-ask principle which basically says it's better to tell another object to do something than to ask it for stuff that you can do things with. And that's it. So are there any questions? I'm a little bit over time so you're on your break time right now. But if there's, I can do a couple. Yeah, go ahead. Can you give controllers a little bit or I'll turn it into controllers just leaving it as is? I think it would depend on what the whole controller, the question was what would I do in the case of the controller that I showed. So I would either leave it as is or I would extract out separate methods for the different kinds of ways we want to instantiate the widget in that case. Part of the problem with that is that this filter actually had some logic so it was gonna behave differently depending on which action it was called before. And it's really hard to like map all that up. Even in the simple example when you just have the seven base actions but as soon as you get into a real controller and a real app and you have more actions, you have more stuff going on, it becomes really, really hard to figure it out. So hope that helps. Anybody else? Oh wait, there's one more. You raised your hand halfway so you get half a question. What do you have to say about dry and then performance? In that line example, if you wanted to sort by distance and distance was a pretty big calculation, you want to store those in the database, then maybe it would be a good idea to store the distance. Yeah, but you could do that. So the question is what about dry against performance? And the example he's bringing up is the one about the line class. So in that case though, you could do the calculation when you instantiate the object or you could do the calculation the first time someone asks for it and then store that in the object and keep returning the same one. The point is the calculation gets done in one place and not in multiple places. So these things don't have to work at odds. Yeah, so. All right, thanks very much.