 So my name is Ben Orenstein. I work at Thoughtbot in Boston. And I have come here to talk about refactoring, to show you some live coding, to do some vimming. I'm really excited. And so Marty and the organizers of Rocky Mountain Ruby turns out these are smart people, because they put me right after Sandy. And in an amazing, lucky coincidence, our talks fit together amazingly well. No coordination, but I'm just watching her talk going, this is exactly what I would want to have happen right before I go up and do what I'm about to do. So perfect. You guys lucked out. So two things before we get started. First of all, this is not me lecturing at you, telling you the truth from the mountain. This is us pairing. I'm now pair programming with this room. So if you don't understand what I'm doing, please say something. If you disagree with what I'm doing, please say something. I love questions. You're not going to mess up my flow. The point of this talk is not for me to get to the end of it. It's for you to learn something. So don't be shy. Shoot the hand up. The second thing is, I want to tell you the most important part of my talk right now, just in case you tune out or fall asleep or something like that. So this idea, there's an idea. It's called tell, don't ask. And the idea behind tell, don't ask is, it's better to send an object a message and have that object perform some work for you rather than ask the object about its state and make decisions on its behalf. That theme is going to run through all these examples that I'm about to show you. So if you remember just one thing, remember to consider tell, don't ask. It tends to lead to very good object-oriented code. So let's dive in. Let's write some code. Once this projector boots back up, you're going to see a little bit of code that looks a lot like something I wrote recently. So take a second and just read this. You're probably getting the gist. So this is an orders report. And the goal of the report is to take a collection of orders and a start date and an end date and then calculate the total sales that happened within that date range. Very basic sort of analytics type thing. Now, if I had written this code about a year ago, I probably would have stopped here. It's not terrible. I'd say it's about a B. Maybe it's a B minus. But over the last couple of years, I've developed some new ideas and some things that I would use to change this to make it better. So here's the first one. Check out line 12. We're creating a temp variable called orders within range. And then we grab from the collection of orders. Those are replaced within the date. Now, we have this variable in a temp. And lately, I've been extracting this. So I'm going to extract this temp variable into a private method instead. And I actually have a macro I recorded for this to save us a little time. So here's what it looks like now. Now line 12 just calls that private method. And we've extracted that logic into a method. Now, there's a couple of benefits that we've already gotten here. This is a small change. We've just gone from a temp to a query method. But there's a couple of benefits. The first is, ignoring the odd wrapping we have in place here, we went from one method with two lines to two methods with one line. Now, I'm not going to be ridiculous and say that's always a good idea, but it usually is. I'll take one line methods all day long. I'm almost willing to say that methods longer than a line might be a smell. Now, it's important. Let me define what smell is before you get too ridiculous and start tweeting that quote and people flame me. A code smell is something that indicates there may be a problem. A smell is not a problem. It's an indicator. I think methods longer than one line might be a code smell. So now, we've had one win. We've gone from one method, two lines, two methods to one line. That's good. The other thing we have here is we're more likely now to reuse this logic. So we have right now one method in our orders report that calculates total sales within date range. It's very likely that we're going to come along and add average sales within date range. Something later in this report is likely to need to calculate all the orders that are within that range again. Now that we've pulled this out into its own method, it can be reused by future methods. We've made this calculation more accessible. It's more likely that code we write later is going to be more dry. And there's a third win here. And this is actually, I think, one of my favorites, which is let's look at that code how it looked right before our refactoring, like this. For whatever reason, when you have a temp variable in a method, you can't help but read how it's implemented. If I was reading this method, I'm saying orders within range. OK, how do we do that? OK, we look at the orders and then we go through here. And I'm actually trying to figure out how it actually works. When it's just a call to a private method, I think you're way more likely to ignore how it's implemented for now. You say, OK, that's a private method. I'm just going to trust the guy that wrote this and his tests that orders within range in fact returns the orders that are within the range. And I'm going to move on to reading the rest of this method. So I think it's a readability win as well. Now let's look for some of the stuff we can improve. Let's go back down to this private method we just extracted. Another thing I've been doing lately is developing a strong intolerance for blocks or conditionals with and and or or in them. I have almost always extract those these days. So we have the select here. And if you're reading the select, if you're reading the code, you can pretty quickly parse what it means. But if I were talking to you, I would say, from the orders, select all of them that were placed within the range. That's not exactly how this reads, right? So let's make it read better. So what if we said instead, let's ask an order if it was placed between two dates. The start date and the end date. I like this better. So now we are, let's move this down. I think we've got a small win here. We're sending a message to order as opposed to digging around it. We're going to move that calculation for, hey, are you placed between two dates into order? I don't want this report to know how to figure that stuff out. I'd rather just ask order. By the way, so I meant to mention, I have specs for all these examples. I'm going to show you a bunch of examples. They all have specs. First rule of refactoring, don't refactor code without specs. Just don't do it. Write the tests first if they're uncovered, and then refactor. So I'm going to be writing my tests as we go to make sure they're right. So let's make sure this extraction worked correctly. Go back to where we were a second ago. Extraction worked correctly. Okay, so now we're trying to write this new method called place between undefined method. That's what we want to see. So let's go in here. So what does this look like? Okay, this takes, whoops. This is going to take a start date and an end date. And it's going to, we're going to ask the order, is your placed at after the start date and after the start date, yet before the end date? Let's see if we're good. Back to green. Yes. So now I've pulled out a little logic into order. I'm liking this code more. I think we're creeping up towards like B plus range. Life is getting pretty good. But we've actually, in this extraction, created a new problem. So notice all the places we're passing start date and end date. We pass it into the orders report. And then from this method, we pass it into order. This pair of start date and end date is showing up in a lot of places. And when you have parameters or attributes that show up in a lot of places, there's a chance that they might be what's known as a data clump. And what you do with a data clump is you pull it into its own class. And a good way to check if you have a data clump is to say, if I have two pieces of data and I took one away, does the one that's left still make sense? And in this case, it doesn't. Because I'm asking, hey, order, were you placed between start date and nothing? That doesn't make any sense, right? So these two things are clumped together so we should extract them. And that's going to give us a couple of wins. And we'll talk about this as soon as we got it. So let's pull these out into a very simple class. And I'm going to start in the spec. So here I have my start date end date. Let's just turn this into a range. We'll call it date range. And we'll just throw them in there like this. And then in our, over here, oops. So now I have this new class called date range that takes us to start at an end and I'm passing that into the orders report. This blows up because date range doesn't exist, which is fair. Now date range exists. We get the wrong number of arguments because we're passing in some initial attributes. So let's just use a struct real fast. Now we have a date range that takes those. Good. Okay, so now we have an argument error here. We're now passing in just two and the spec's three. So let's change this to take our range. You guys know Drew Neal as in the audience? Vimcast guy, he's watching my vimming very intensely, I'm sure. How am I doing, Drew? Good. Approval from Drew Neal. Okay. So now we have one more place to change. So this now takes just the date range. I'm just threading this through these same calls that happened before. In here, we just take a date range now and now we ask the date range what the start date is and what the end date is. And we're back to green. So we follow what happened here, had that data clump, was two parameters, we pulled it out, now it's one stupid class that's basically just a data container. So you might well ask, is this a win here? It actually is. So notice what happens to the parameter list in orders report and also that method with an order. We went from three parameters to two and you're saying, so, that's actually a big deal. It's a big deal because of something called coupling. Now coupling is a degree to which components in a system rely on each other. If A and B are completely uncoupled, you can change A as much as you want and it will never affect B. If A and B are tightly coupled, changes to A will impact B. Now there's a kind of coupling called parameter coupling which means any time you pass a parameter into a method, the calling method is coupled through that parameter. Let me show you a quick example of what that looks like. So notify user of failure is coupled to print to console because notify user of failure has to pass in a parameter called failure that responds to two sentence. If I passed in nil into print to console, this would blow up because nil does not respond to two sentence. So as a result, notify user of failure actually has some knowledge about print to console. It is slightly coupled. There's coupling between these methods because it needs to assemble the right thing. Now imagine print to console passed in two parameters. You can see that the coupling goes up. If it's, say, I passed in a failure and an email address to send a failure to, now the email address needs to respond to some method and now the coupling between these two methods has increased and if we went to three it's even more and four it's even more and five it's even more. So this actually yields an interesting result which is methods that take no parameters are better than methods that take one. Methods that take one are better than methods that take two and so on up the chain. So by pulling out that date range and slimming down our parameter lists, we have reduced the coupling between these components. So this actually is a win and it's a pretty big win but there's more. It also gives us a pretty handy place to hang behavior on. So now that I look at this code, I'm loving it less and less. We've got this date range here but we're asking order to determine if it was placed within a range. It seems like determining if things are placed within a range would be a good job for this new date range class. I can envision other things other than orders wanting to know if it happened within a certain range. So let's pull, let's extract another method here. Let's write the code we wish we had, see how that works. So if you ask an order if it was placed within a date range, let's just ask the date range, do you include my place that? This will blow up. And then we'll go into date range and we'll take a date and then we'll say, you're included in my date range if, now I'm gonna make use of Ruby ranges real quick. So we can actually say start date end date dot include date. That'll work because Ruby's awesome. Cool, so we're back to green. So that we've picked up another win from this date range class which is a great place to hang date-related behavior. I've noticed a common thing among people that are sort of intermediate level of object-oriented programming which is they're a little bit hesitant to extract classes and part of that is reasonable because to extract a class invites a little bit of indirection. Suddenly your code isn't in the same place it's somewhere else but most people air too far on being unwilling to extract classes. As I write code, I extract tiny classes. Notice that in Sandy's examples she pulled out classes that had one method in them and the code was greatly improved. Don't be afraid to pull out a tiny class that just has two data attributes or even one. Maybe instead of passing around a string all the time that happens to represent a phone number implicitly you create a phone number class that just has that same field. It makes things more clear. So don't be shy about extracting classes, methods, those things are great to do. Most people don't do it quite enough. Lots of tiny classes that's a good sign of an object-oriented system. Okay, before we leave this example there's a couple small little things I wanna change to make this slightly better. First is this mess right here. So we find ours within range and then well we're summing them. We're summing the amount. This could be better. So first let's pull out, let's extract this into its own method. So total sales we'll call it. And I'll bring this all in here. It's gonna need a parameter. Extract it out the total sales and then there's one last little thing that I can do in here with this inject thanks to Ruby 1.9 land which is just this. Good, now look at this. Check out my public API. It's one method called total sales within date range and the body that method reads total sales of orders within range. I love that in a public method. I love how this reads. If you wanna know how either part of this works you can dive down to the private methods. If you don't you can read the method name and the body is completely unsurprising. I love that. This is the kind of code I would check in. This is probably about where I'd stop. Okay, I'm happy with this. I like life. Yeah, what's up? You can order through this right here. He wants, yeah. He has to see orders within range. Oh yeah, thank you. I forgot that. Good call. Now I wanna ask it if it include, right? Date range, thank you. So, hey date range, do you include? Oh right, do you include my placed app? Thank you. This is why it's good to have pairs. Boom. Good, good call. Exactly, so this is the problem that I write the method first as I sometimes forget to go back and do it. Yeah, what's up? That's an interesting point. Interesting. That's awesome. So he's saying that the include here on line 28 is because I have that range of start date end date it's going to instantiate all the dates within that range and then ask if it's included in there. Well I can use the cover question mark method and that'll just instantiate the ends and check for that. That'll be way more efficient. That's cool. What's that? One nine only. So if you're a one eight seven, what are you doing anyway, honestly? All right, a lot of hate on one eight seven in here. Yeah. Yeah, right. Okay. It's a Ruby version back from the Dark Ages. Okay. So let me run my specs. I got a new spec in line now. Okay, time for a new example. Here is a modeling, a very simple modeling of a job site. Like we're doing construction, let's say. This is an app to manage construction projects. Now a job site has a location and it maybe has a contact. We maybe don't know who the contact is. So within job site, we have some checking to see if we have these contacts here. So when we get the name we need to first make sure the contact exists and if not we have a default for when they don't. Same thing for phone and same thing for emailing a contact. We only ever do that if we actually have a real contact. Contact is a simple open struct down here. So what's happening here? Why is this code not so good? So the first problem is it violates tell-don't-ask, which is something we started talking about earlier. So we would rather just tell contact or something else. Hey, give me your name. Instead, we're asking, hey, contact, do you exist? And if you do, I'm gonna call a name on you. And if you don't, I have a default, so don't worry about it. So this is the opposite of tell-don't-ask. This is ask, don't tell. This is the wrong way. So, and the problem here, the core problem here, is we're co-opting nil. We're asking nil to stand in for when there is no contact. That's actually what's happening here. When I create a jobsite with no contact, at contact becomes nil. And now I need to check for that presence of nil all over the place. So this code can be improved. And it can be improved with something called the null object pattern, which is one of my favorite new things that I've been using all over the place. So let's create a class that stands in for not having a customer, as opposed to using nil for that purpose and all the ugliness that it entails. So let's add, when we don't have a contact, oops, let's have a null contact. Now this is gonna blow up all over the place because I have tests that test where there's no contact. Now let's write this null contact class. It looks like this. Now we have the right class, but it doesn't have the methods we want on it. So let's define name, and we'll say no name, phone. And now we get down to email, whoops, don't hold undo. Now we get up here to email contact. And you'll notice that we only send it if contact exists. So I'm gonna define this on contact, deliver personalized email, body. I'm just gonna have to do anything. I'm just gonna define an empty method here. Let's see if our test pass now. They do. So now we have a null contact to stand in when there isn't a contact. And now we get to do the favorite thing of all programmers every year, which is what? Italy code. Italy code, absolutely. No one has ever not gotten that. Every audience I've asked that has gotten it instantaneously, just so you know. All right, so let's read some code. Life is so good. If you don't like deleting code, I think you need a new career. This is the best part. Re-indent those bad boys and re-write again. And it still passes. So I just yanked out like 10 lines of code, maybe more. And everything still passes. So this is because, what's up? I'm not a native speaker. Yeah. That's awesome. So now we've created a, so Sandy talked about how you wanna send messages to objects. And what you can do is use the messages you wanna send to pull new classes into existence. The new class we wanted to pull into existence was a class that stands in for the case where there's no contact. That's what no contact is down there. It defines what to do when contacts aren't there and possibly even just does nothing sometimes. And now we're happily following tell-don't-ask. We just tell different types of classes of contact, what we want it to do. And also we've moved a bunch of crap. So our code before, the true intent of the code was obscured with effectively error handling or checking if contact exists. Now it's much more obvious what these methods are doing. They're shorter and they're clearer and we've gotten rid of conditionals. This is what Sandy was talking about with replace conditional with polymorphism. This basically says, rather than have an if where you check things about the object and then decide what to do, have two classes and just send the same message to both ones and blow away that if and life is good. There's a question somewhere over here? Yeah. So no contact just is a. Yeah, so this question was no contact is just a simple plain old Ruby object right now. Would it be better to inherit from contact or possibly make a, what's the second part? Singleton, great. Okay, so I'll answer in reverse order. So first, yes, it would be totally reasonable to turn this into a singleton. Why? Because how many null contacts are there? Just one, right? There's lots of contacts. There's only one null contact. So if you told me in a code review you wanted me to make that a singleton, I would do it for you. I might not write it that way at first pass, but that's a reasonable point. The other part of your question was would I inherit from contact? No, I would not inherit from contact. I want to define exactly the API that null contact supports manually, because there may be a lot of additional methods on contact that I don't need to have on null contact. There's a small chance I would do it, I would decorate contact with a null contact on top of it, but generally I'm not gonna inherit for that. Inheritance, for me, is a tool I reach for when nothing else is working. I actually am fairly anti-inheritance. And here's a great metaphor. This is my favorite metaphor I've heard recently. So, and don't take this as social commentary. So composition, so inheritance is like marriage. Composition is like dating. So with an inheritance, no, it's like family. Inheritance, hold on. Don't tweet that. Oh, that's getting a lot of trouble. Okay, here it is. Inheritance is like marriage. And composition, this is such a good, yeah. Did I get it right? Okay, inheritance is like your family, right? You inherit something from the beginning. You are born as a subclass of a parent class. You cannot change that. It's fixed throughout your life. Composition is like relationships. They can come and go. They change throughout your lifetime. They're flexible. So composition is basically always inherently gonna be more flexible than inheritance. It's much harder to get yourself in trouble painting yourself into a corner with composition. It definitely happens with inheritance. I saw the hands, maybe? Yeah? It was a basic question. So it was something like null object. Would you put that with your models or would you put that in like a separate place, like the folder? Yeah, so the question was, where would I put this null content? Would I put it in app models? Yeah, I'd put it in app models. I'd put it in app models. If I had 50 of them, I might pull it into like app null objects, possibly. But generally, I'm gonna stick most stuff in app models. My personal rule for app models versus lib stuff is stuff that is specific to my application lives in app models, like business logic, all that kind of stuff is gonna live there. The only thing I put in lib are things that I might extract or sort of general purpose things that I might use between projects. Personal rule, you guys can do what you like. Other questions? Awesome, okay. One more example for you guys and I'm gonna summarize and wrap up and we're gonna get you to the break. So, oh, one quick thing before we leave this. Who has code in their app right now that says something like, if current user, yada, yada, yada? Liars, raise your hands. Yeah. Exactly. You probably have it in the view. You probably have it in application controller. It's probably throughout your app. Can you see how this might help that? So rather than have current user return a user when they're logged in and have it return nil when they're not, have it return a user when they're logged in and a different class when they're not, then you can blow away the 50 conditionals that are complicating your code and just always send the same message. Say, hey, current user dot welcome message and if they're logged in, it's one thing that this class responds to and if they're not, it's something that this class responds to. This basic idea of polymorphism over conditionals cleans up a ton of code. This has been one of the biggest tool improvements that I've gotten from a single concept or idea in a long time. Yeah, what's up? Current user, usually the text will be in view. So I'm explaining in one partial for one. Yep. This starts to get a little, I mean here it's just in the model or same model, model, or you can take any welcome message, you can have a 25, 30, 30 message and it's great for once in a decade. Yep, so if you say that this sort of breaks down on the view and he's kind of right, it can be sometimes I don't follow, tell, don't ask in the view because effectively a view is getting an object and pulling out things from it and showing them. So I'm not as rigorous about following tell, don't ask in the view, but when things get nasty and they start getting really conditionalized and ugly, I'll often reach for some sort of presenter and I'll pull that out into its own class and then possibly potentially use polymorphism in there. Yep. It's going to be an asker, isn't it? Right, exactly. Isn't it a view's job to reflect state? So it's going to be an asker. It's hard to not ask in the view. It's kind of the view's job. So I exactly, I'm not as rigorous about it there. That's one of the things I learned about programming maxims which is I learned something and it seems so simple and beautiful and it works everywhere and then I realized, no, it doesn't actually work everywhere and you have to kind of get excited and then realize it breaks down in some places. So always question things like tell, don't ask is a great principle. It is not a law. It's something you should consider when you're writing your code. It's not something that is always correct that you always must follow and the view is one of the places where sometimes it tends to break down a little bit. Okay, so one more example. So one idea that makes it much easier to change code is to depend upon abstractions. Sandy said that exact phrase in her talk and the reason depending upon abstractions makes code easy to change is because you can alter the details without affecting the calling code. In effect, this lowers coupling, right? If your public API is simple and predictable, your coupling will end up lower. If you hide those details where other code can't see them, can't know about them, can't accidentally get intertwined with them. Now most people are pretty aware of this to a certain point. So for instance, I imagine none of you, if you need it, so Braintree is a payment processing system. I imagine none of you, if you needed to make payments through Braintree, which has an HTTP API, I would hope that none of you would wire up like net HTTP and start shoving like posts down the line or even go lower and just like fire binary down a socket. Like no one would go down to that level, right? They know that that would be a bad abstraction. So you'd come up a level and you'd probably do something like this, which is you'd reach for a gem that wrapped us up for you. And that's the right idea because you want to depend upon abstractions and a gem is an abstraction on top of Braintree's HTTP service. So I see code that looks like this in a lot of Rails apps. So we have a user and there's a subscription amount. And we might want to charge user for a subscription. So we grab their Braintree ID based on their email and then we charge them for the subscription amount. Maybe we create them as a customer for the first time. We use their email. And let's say also there's a refund for some reason that also uses the Braintree gem. Only this time we need to grab a transaction ID so we can know which one to refund. Now this code is decent, but it can be better. And the issue here is this code depends on the Braintree gem. So we're abstracted away from the HTTP, but we now have our business logic code is concerned with which gem we're using and what that API looks like. And also the particularities of it. Why on line six does user need to know how to find itself within Braintree? So those details have leaked into our business logic about how Braintree works. So how can this be better? Well almost all the time when I'm working with an external service I will write a very simple, very dumb wrapper around it. And this wrapper shields me from change. So in this case, let's say we wanted to switch to Stripe. Okay, well user and refund both need changes. There may be a hundred other classes that all have various methods that call Braintrees in certain ways along with knowledge embedded inside them that all need to change. That change is painful. And that's a change that's reasonable to happen. Changing payment gateways happens, I've done it. So how do we shield against this? Simple, simple, simple, simple. We depend upon abstractions. Here's the refactored code. I've pulled out this idea of a payment gateway with simple, well-named methods. It doesn't even have any state. These are just class methods. Here's my payment gateway. I'd put it in a limb as I said because it's sort of a general purpose. Wrap around Braintree and something that I'm very likely to reuse. And now all those details are hidden within this class. And again, I said before, most people are not willing to pull out enough classes. This is a great example of a simple class that takes five minutes to write that can potentially save you 40 hours later on. Not only that, but now that we have this class, imagine we're testing the old version, right? We're testing this old version. I wanna make sure this works. I need to stub methods on Braintree gen. That should give you the shivers. I do not want to stub methods on somebody else's library. Here, look at what user calls. Calls my methods. That I'm happy to stub. I'll stub those all day long. Now I'm shielded from change. My details are hidden and testing is easier. If that's not a win, I don't know what is. All right, so I wanna wrap up with a couple final ideas about when do you do these refactorings? Because Sandy brought up a great point, which is you should refactor when it's gonna save you money, when not doing so costs you money. And I think that's great. That's a good idea. If there's code that's never ever gonna change, why refactor it? But there's a couple other nuances that I'd like to bring up. It's a great idea to refactor God objects. Now what's a God object? Well, I'll show you. So this is a app that I have anonymized to protect the guilty. And we're in the app models directory. Now let's get a word count of all the lines for all these models and then let's sort it. And here you see my hidden shame. Check out user and order and merchant. So this app has three God models. Now what's a God object? The God object is one of those objects that everything seems to rely on. Everything's calling methods on these things. They're giant, they seem to know a ton. And in Rails apps, you will almost always have two. One is user and the other is whatever that application is about. If it's an e-commerce app, it's order. If it's a to-do list app, it's a to-do. You almost always have two. This app happens to have three. We got user leading by a mile and we got order and merchant. This is, of course, an e-commerce app. So order and merchant are both ugly. Period is now a pretty big class but it's trailing by so much. I'm gonna call those top three of my bad ones. Every time I touch code in a God object, I'm gonna refactor it. If I need to add functionality to order, it's not going in order. It's gonna go somewhere that order composes or it's gonna live somewhere else. And every time I gotta spare a minute, I'm gonna be ripping stuff out of there all day long. God objects are what makes systems hard to change. You got something that everything relies on which means that everything is coupled to each other through that object. It's always worth refactoring those objects. And this is such a simple way to determine what your God objects are. Just look at how many lines are in your models. So that's one great time and place to refactor. Here's another one. High churn files. I touched on this earlier and so did Sandy. It's worth refactoring something when you change a lot. So you might have the ugliest code in existence but if it is literally never gonna be changed and barely has to be read, it's probably not worth your time. So how do you find high churn files? Well, you look at your color display settings. No, you look at this gem. It's called churn. Churn shows you, for any given file, how often it changes. It goes through your git history or SVN if you are insane and tells you how often it changes. So high churn files are great candidates for refactoring because it means you're in there a lot. It means they're a source of constant change. So you would love to get in there and improve them, make that change easier and hopefully shield yourself from that change with some smart refactoring and some good code. And then there's one other place that is a great place to look for refactoring which is places you find bugs because a bug in code means that you didn't understand it the first time. It was too complicated for you to notice that there was a bug there. And the truth about bugs is that bugs love company. They tend to show up together. So if you have a file that you just keep finding problems in, it's probably a great candidate for refactoring. Thank you guys very much. You've been an awesome audience. Last minute, wrap up questions. What's that? I don't get the reference there. Oh, he's asking about my tabs up top. This is terminal Vim. So these are, my tabs are shown up at the top as just like text. Is that what you're asking? I think that's stock Vim. I don't think I've done anything that. Is that true Drew? Does it just look like that in terminal? He doesn't know. I think so, yeah. I don't think I've done anything crazy with that. If you just do tabby, it'll open up a new one looking like that. That's all I'm doing. Yeah. Yeah. Yeah. Can I go back to, he asked if I could go to the first example. We do have time. He asked why don't I break a one line method or one method with two lines down to two methods with one line? No. Uh-huh. Yeah. Oh, okay. So it was one line before. It's still one line. Why is it better? Is that the question? Oh, no, it's two methods one line. Okay, yeah. So method count isn't always a good measure of goodness of code. Like, see now before it was one line, but you had to basically read and understand all the details of that line. So I would argue that this is much easier to understand than it was before. I think the readability has improved. I'm totally willing to pull out, very willing to pull out tiny little methods with good names to clarify code. Yeah. Yeah. Yeah. Can I ask a spell? Yes. Oh. Yeah. That's a great question. I struggled with that myself. So he asked, he always heard that classes that exist solely of class methods are a smell and that's what that wrapper is, that payment gateway that I built. And I have also heard that. I think in this case it's okay. I think it's, like you said, it's a smell. It's an indication that something might be a miss. In this case, this is just kind of such a simple layer on top of something. I think it's all right. And I struggled to find a way to not do that and nothing really seemed to make sense because it's sort of just a bundle of brain tree methods as opposed to having state of its own that needs to be dealt with. Yeah, he was saying sometimes you might want to swap that out. So I might have different payment gateways. Maybe we use brain tree sometimes and Stripe other times in which case I would probably have a gateway that you would instantiate and then inject into classes that use it. Yeah, yeah. Yeah, let's take a reminder about that. Totally, yeah. You say that you can actually inject the class itself as an object into the place that's calling it. That's definitely true. Yeah, agreed. So class methods are effectively global functions. There's no state they can be called anywhere. They are definitely a smell. Yeah, worth considering. I'm comfortable with how that turned out though in this case. Their namespace to this, yeah. I have one more question. Do you have the turbulence term? No. Michael Feathers, Chad Fowler, and Martin Decker. Oh, right. Some religion research on that. Cool. That's like a churn but it's like these classes. Gotcha, cool. So another tool that got recommended was Michael Feathers and Chad Fowler, or Turbulence, the gem. Cool, good recommendation. Thank you guys, thanks very much. Enjoy the break. Thank you.