 Next up is Rainne Heinrichs, is it Heinrichs? Yeah. Rainn, Reine, yeah, whatever. Talking about Ruby best practice patterns. Obviously. So before I go any further I want to say that I had somewhat of a change of heart before I came in here for this conference and I won't exactly be talking about Ruby best practice patterns. I will be talking about something somewhat similar but before I get into that let me talk about what Ruby best practice patterns are before I don't talk about them. So there are basically three concepts in Ruby best practice patterns. When you break it down there's Ruby and even though we all know what Ruby is this is important because these best practices are all within the context of Ruby. They're not within the context of software development or a number of other possible areas are all about Ruby the language itself and a best practice is simply a set of techniques that experts currently recognize and use. Now in that little phrase there's one important word which is the word currently and that's important because best practices are only a snapshot of our current understanding and they're always evolving. So the best practices that I may be able to tell you about now could very well be different in six months or even a couple weeks because we're always learning more about the best way to write software. And a pattern is simply a decision that an expert makes over and over something that's repeatable and more importantly it's also something that's learnable. So when you put that all together Ruby best practice patterns are a set of techniques that Ruby experts currently use to make the best decisions over and over again. And the point here is that if experts can do it and it's something that can be learned then you can make the same decisions experts make which essentially means that you'll become experts you would think. So the idea is that if you can think like an expert and make decisions like an expert when you're designing Ruby code when you're writing methods when you're designing classes then the code you write will be better for it. So how do patterns actually help us write better code? The answer to that is that patterns are designed to optimize the communication value of the code that you write a lot of different ways that you can optimize code. You can optimize code for performance. You can optimize code for a number of things but patterns are about making your code communicate more effectively. And once I realized this I this is where I began to question a few things. So patterns help you write code that other people can understand. For instance, I think we can probably all look at this code and have a good concept of what it does. We don't necessarily need to know what a page is exactly but we know that for each of these pages we're going to rebuild that page if it's dirty. This code communicates its intent clearly. Another example and this is from Capistrano would be what happens when you deploy? Well, it's quite simple. You update the repository cache and then you copy the repository cache. But this got me thinking. If patterns help you write code that other people can understand that means that anyone else can work on the same code that you worked on. That means that you can write code and then someone else can come and work on it and not have a lot of lead in time trying to understand the design decisions you make because you made them according to best practices. So this means that anyone can conceivably work on your code. This is actually a problem, isn't it? Think about it. If you're writing code that anyone else can understand, you're doing it wrong. I'll tell you why. First of all, think of the children specifically the children that you may have who may be affected by your newfound expendability. If you write code that anyone else can understand, there's a good chance that someone else is going to be working on it instead of you, which raises an important question. How secure is your job? Keep in mind. Studies show a strong correlation between the maintainability of code and the extendability of its author. What does this mean? I know some of you are visual learners, so I'll put it like this. If we're all writing code that's easy to understand, that communicates its intent effectively, anyone else can do our jobs. Probably someone will be because there are a lot of people that are cheaper than us. When you think about it, we're probably all pretty good at what we do. We probably charge good rates. Might be able to get someone off the street for 10 bucks an hour. Then we're screwed. So what's the solution to this? If maintainable code makes you expendable, how do we fix this problem? So I'm here to present a different talk. Instead of really best practice patterns, my talk today is going to be about unfactoring from patterns. So what is unfactoring, really? Well, it's quite simple. I hope when we all leave here today, we'll have a better understanding of how this can work and how you can apply it. Unfactoring is the process of taking well-designed software and through a series of iterative and small changes, making it completely unmaintainable by anyone but you. So we all know maybe we've heard about some of these best practices. Don't repeat yourself. Localize the consequences of the code that you write. Optimize your code for understanding and code to an accurate domain model that actually reflects what's happening in the real world. Then there's some patterns that you may have heard of. Intention revealing names, compose method. These things help you make your code more understandable. They make it more readable. They simplify it. But they might get you fired. So before I go into a few examples of how you can also unfact your code as I have learned to do to improve your job security, let's talk about why patterns are so damaging and so dangerous. Because really, patterns are about figuring out what the context of the code is. And whenever you're faced with a decision, a design decision in your code, it's important to think about what are the different forces at play here? Maybe it's important that this code be performant. Maybe it's important that this code be maintainable, that it be easy to test. There are a lot of different things that you want to think about. And so a pattern that you write or that you apply is really only valid based inside that context of if I want to solve a certain problem, how do I harmoniously resolve all of these forces? So as an example, if I want to name a method correctly, that interrogates an object about its state, for instance, I want to know if a check has expired. So one thing I can do is everywhere I want to check that I can ask if the checks expiration date is, you know, before today. That's one way I could do it, right? Every piece of code could say if check expiration date is less than today, I could do that everywhere. Or I can simply write a method that queries the check for its expiration status, and then use that method. And so some of the tensions play here are I want a readable method, I want something that I can look at and immediately understand its intent. I also want to dry my code so that I'm not saying expiration less than now in 50 different places, because what if that logic changes? What if I really want to know, maybe it's maybe I want to catch it a day in advance. So now it's expiration less than one day from now. Well, if I'm using this expiration concept everywhere in my code, that's a lot of places I have to go and change it. So another factor that's important here is not repeating yourself. And so when you roll all these things together, you realize that a pattern that applies in this case, and there are a lot of similar cases, which is the power of patterns, is to name, to write a method that performs this check, call it something that's revealing of its intention, like expired with a question mark at the end, because that's a ruby idiom to use a question mark at the end of methods that ask questions, which is actually one of my favorite ruby idioms. And so doing this, you resolve these tensions, these forces, you dry up your code, you make it more readable. But you make it more readable potentially for someone else. And that's the problem. So let's talk about some common unfactorings. Let's get back on course here and consider some easy ways that you can make your code less maintainable. So let's look at that example that I gave before. This is from Capistrano. This is the remote class that goes out and performs things on your server and on the repository that it gets the code from. So this is the deploy action. When you run CapDeploy, internally it's going to do something like this, depending on your configuration. So what this deploy does is pretty easy to see what we're doing. We're deploying. That's what the method says it does. And then that method does two things inside of it. It updates the repository cache and it copies that repository cache. Is anyone confused about what this method does? Does anyone think that they could write a method like this or maintain a method like this if they needed to change the functionality? For instance, let's say between updating the repository cache and copying the repository cache, we want to add another step. For instance, would that be easy or difficult to do with code like this? Pretty easy, I think. There's a line just out of line, write a new method, stick it in there. It's done. So the first thing we want to do is we want to make it difficult to understand what these pieces of code do. We've got two things happening here, updating and copying. So we want to take that updating and that copying, which are two composed methods, and decompose them. Just put that code, wham that right back into the method. And now it's much harder to tell where one of those behaviors begins and ends. And so if I want to add some more behavior here, I have to kind of look in there. All right, if there's a line break there, maybe I can put it in there, maybe not. So that reduces maintainability. So that's the first thing we can do. Now given that, and like I said, this is iterative. So as you're unfactoring away from these patterns and making your code less maintainable, you want to make small changes. And ideally you'll have a comprehensive test suite so that when you're unfactoring, you can catch any bugs that you may add. And that way you can unfactor successfully and no one will ever know the difference, except you. And then when your boss eventually decides to consider replacing you, and they do a code audit perhaps, and try to determine the complexity of the code and what they would need to do, how much it would cost to replace you, they're going to say, holy shit. I didn't know that it was this bad. I don't think anyone else could possibly maintain this code other than the person I have right now. I can't replace him. He is irreplaceable. And so that's our goal, to make you irreplaceable. So one thing we can do, you can see that we're off to a good start here. We've taken those nice simple method calls that clearly communicate their intent and the order of the functions that happen here in this method. We can break that apart. So that's a good step. But there is some repeated code here. This scm run, and then this run, when you actually look at those methods, scm runs just set some options and then calls run, which is a nice refactoring towards, you know, the drive principle. It's not repeating yourself. That way you're not calling run twice and passing an option. And also run itself is dry. That method is drying up some behavior that's used in both of these places. So let's break all of that apart. Let's take that run method, put it in here. When it's scm run, let's add those options in inline. And I think I think you can see where we're getting here. We're moving away from this place of simplicity and flexibility and ease of understanding into a much, much different, I think, much better place where the code is not revealing of its intent, where the sheer magnitude in terms of the size and complexity of the methods makes it very hard for anyone to really understand what's going on. Now it clearly passes the test so we know it's working. But it's very hard to say why it's working, at least at a glance. If you go back to the way it looked originally, it's pretty easy to just scan the code for comprehension and understand what's happening. We do not want that. We want we want people to take literally hours to try to understand a simple method like deploy here. We're getting there. We're getting there. So let's go back to the way it started and look at these names. Look at the names that we're using here. Remote. Makes sense. Deploy. Got it. Okay. So we're deploying something to a remote. I don't even need to know what Capistrano does. I got that. We're good. And I'm pretty clear about how that deployment is going to work, right? Yeah, that's not good. We're going to fix that. I suggest pig Latin. I find that if you name things with pig Latin, it becomes almost an order of magnitude harder to comprehend. And so what I've decided to do here is if we go ahead and break all of this down, if we apply all of these steps together, we can decompose those simple methods and just wham all of that code into that one method, make it nice and long. We can take that dry code where duplication has been moved into one central location. We can move it back out. That way, if you need to change it in one place, you'll really have to change it in like 15 places, which also, you know, it's going to make you guys more money, I think, right? Think about it, you're not paid by the job, you're paid by the hour. If you have to go fix it in 15 places, that's 15 times as much money you guys are going to make. Think about it. So here's what we started with. And here's where I want you to be. I think we can all do this. I think this is something that we can all shoot for. Now, it may take a while to get to this level of unfactoring. This is not something that you can do overnight. It took me, I would say, three or four nights to come up with code this bad. But it's not really bad, though, is it? It's actually good when you think about it. Because I defy anyone in here, no matter your experience, to look at this code and tell me what the hell it does. I don't think you can do it. And that's the point. Because if you wrote it, you understand it, and you can keep your job. So there are a lot of patterns out there. There are a lot of best practices. I can talk about, you know, probably 30 or 40 different ways that people are writing good code just in Ruby, just in very small pieces. You can talk about, let's say that we are writing five or six methods and all of these methods are getting past the same parameters. It's a little bit weird to write the same method, or the same parameters five or six times to five or six method calls. You could put those method calls in an object and let that object's instance variable store those parameters, and then all of those methods would have access to the parameters. That would be easier to maintain. You could do that. But then someone else can go maintain it. Let's see, what else? There's some good ones here. And you may, you may find yourself, you know, naively using these in your own code thinking that you're doing yourself a favor. You're not. I think, I think one of the most important ways that you can avoid obsoleting yourself is simply don't name things well. Think about what it's supposed to do. Think about why you would want to use this method. What it's supposed to accomplish. Think about a name that would indicate what this method or what this variable is used for or what it's supposed to accomplish. Then name it something else. Name it something completely different. Pick names, I don't know, pick names out of Dr. Seuss if you have to, but don't use intention revealing names. That's a bad idea. So what I'd like to do is I'd like to start a little workshop possibly, where you all bring me your well-factored code, your well-designed code, and we can work towards making it unmaintainable together. Of course, that raises the problem that then I could maintain your code, but I promise you that I don't want your jobs, especially if you're writing code like that. So I think the conclusion here is actually quite simple, which is that maintainable code is simple, is communicative, it's flexible, but ultimately it's bad. It's going to hurt your job security. So I think we can all agree to unfactor your code so that you can keep your job. Thank you. Okay, that's actually not the real talk that I want to give. The real talk that I want to give is about Ruby best practice patterns. I will, because I actually think that best practice patterns are really important. Why are best practice patterns so important? There are a lot of factors that come into play when you're writing software and anyone who's led a project or managed a team will be aware of this reality. On time, under budget or bug free, you can pick two, right? You get to pick two. Why is this? The first factor is risk. There's some risk involved in writing code. We may not fully understand the problem we're trying to solve and that's risky. We may not fully, we may know the problem but not fully understand or comprehend the solution to it. And so there's risk involved in figuring that solution out if we haven't already done it before or just have other experiences we can draw on. And then there's an issue with productivity. We all want to be productive, but we know that if you have four people on a project and it's running under budget, you can't add another person and then suddenly find yourself more productive. In fact, it ends up that your projects typically become even later when you try to add man hours to them. But we all want productive teams, we all want code that's easy to work with, easy to extend. Which brings me to my next point, which is maintainability I think is the most important consideration. When you're writing code, you have to understand that far more time will be spent reading that line of code than you ever did writing it. I would say 10 times as much, if not more. Every line of code you write, you write it once, but then you will read it for the rest of the life cycle of that product. And so writing software is risky. Risk is the enemy of productivity and all legacy code that we've already written, all code that is legacy needs maintenance when we're working on developing new features. The problem with that is that your code is legacy code right after you write it. As soon as you put a method in there, it's legacy code. The only other thing you're going to be doing it with that from now on is maintaining that code. So code is easy to write and it's cheap to write often, but it's difficult and costly to maintain because most of our time is spent maintaining that legacy code. And so the fundamental truism here is that software costs far more to maintain than it does to write. What this means is that the real productivity increases and the real gains and the real cost reduction comes in making software more maintainable, not in writing it faster. I think using best practices and patterns will help you write software faster, but the far more important takeaway here is that it's easier to maintain software that's written according to best practices. And the reason for this is that we actually write code for humans. We don't write it for computers. You could almost say that the code running is a side effect. We really write code so that we can understand it later. It's pretty easy to write code now that machines can execute to do what you want. It's a far more difficult and a far more useful challenge to write code so that you can read it and understand it. And best practices and patterns are all about helping you make decisions that make your code easier to understand. Code should inform its reader of its purpose. Whenever you want, whenever you make a decision about how you should write something, one of the first things to consider is when I read this, does it look like it does what it actually does? Does it read to me in a way that tells me what it does clearly? So how do patterns help us do this? Patterns do help you write code that other people can understand because they make you think more and they help you make better decisions on a line by line and method by method basis because it's not about the quality of the code as a whole, it's about the quality of the code in detail. So fundamentally patterns and best practices help you write code faster with less risk that's easier to maintain. So there are a few patterns here that I want to share with you which are some of the ones that are the most useful for me. But as I do so, I wanted to be clear that these aren't the only patterns that are out there and also that you cannot find an encyclopedia or a dictionary of patterns and best practices because they will change within the context of your organization, within the context of the product that you're working on, within the context of the code of the libraries that you're using. But fundamentally they all come from the same place which is a desire to improve the communication value of the code that you write. So the first pattern that I want to talk about is called Composed Method. It's probably one of the ones that I used most often when I'm writing my code. And so Composed Method answers a simple question and all patterns are designed to answer simple questions. The question is how do I divide a class into methods? And when you're thinking about a question like that it's important to consider the context of the question. The different forces at play in helping you make the right decision here. So one of the forces at play is not having a 20 or 30 line method that's hard to scan. You want your methods to be short and concise and clear and simple. So what this means is that in order to answer this question and write a pattern effectively you have to think about a few things and make some decisions. One of these decisions is that each method should perform one simple task. Each method should have an intention revealing name and complex methods should be composed by building them from smaller methods. And so this is the example I used before which is that I want to perform a series of steps in Rails deployment. Now it could be written like this. And this will pass the test. This will do what you wanted to do but it's hard to read this and figure out why it works. Especially if you wanted to change it later. So we have two pieces here and I don't know about you but it would take me a minute or two to read this and try to understand exactly what's going on here. There's a logger message that's going to help me with that but if I just had to read that command I would probably be stumped for a little while and the same thing goes for this second step here. And when I'm trying to understand how deployment works I don't want to concern myself with the implementation details of cp-ing something to a directory and these things these things don't concern me at this level. What concerns me at this level is how does this deployment happen? And it happens by updating the repository cache and then copying into the deployment location. So if you rewrite your method or if you design it in the beginning with this in mind so that you can't have each method perform one simple function one simple behavior and then you can compose more complex behavior out of these simple methods you can write a method like this which is the one that actually exists in Capistrano itself which is intention revealing deploy tells me exactly what I expect this to do when I run it and when I look at the implementation of the method it is itself intention revealing because I know what it does to deploy now without having to decipher the implementation details that are contained inside these methods. So that's one of my favorite patterns I think I use it in almost every method that I write I don't like my methods to be longer than four or five lines or to contain more than one concept or behavior at a time I like to spread them out I like to chunk them down into smaller chunks so I understand each chunk in detail and then the method itself and its complexity by not having to understand every single line but being able to simply read and scan it for its intent. Another one that I like that is actually an idiom in Ruby itself and this is another one that was taken and by the way a lot of the patterns that I'm going to be talking about are taken from Kent Beck's book Small Talk Best Practice Patterns. Now how many of you have read this book? Good, good. How many of you have heard of this book? Good, good. So those of you who have read it know that Kent probably put into words one of the most elegant I guess treatises on how to write good software on a very small scale. There are books like The Gang of Four that you may be familiar with that talk about some of the larger context patterns like the the visitor pattern or the command pattern the iterator pattern. All of the patterns that I'm talking about here and the patterns that Kent talked about are very small scale. They're very detail oriented. They include things like how do I compose a method of smaller methods? How do I break up that functionality? Or in this case the question is how can I ensure the two actions happen together? And so the answer in Small Talk and also in Ruby is that you write a method that takes a block and then you do two things. Inside that block you execute the first method you yield and after you execute it after you yield then you execute the second method. And a lot of these patterns make a lot more sense in context. And the context here is I want to open a file and ensure that it closes. Now some of you may know that when you open a file in Ruby without a block that file connection is maintained until it is manually closed. So in this bad case here I've opened a temp file and I'm writing data to it and then I have to make sure that I remember as a developer to manually close that file when that connection is no longer necessary. And the much better pattern is to let the semantics of Ruby inform me of that. I open a file in a block I do things with that file in the block and then when that block goes out of scope I can expect if this is written properly I can expect Ruby to handle the de-acquisition or the destruction of that resource. And so the way this works in Ruby itself when I'm taking these examples from Rubinius is actually very simple. I'll go through it in each of those steps. In Rubinius the file is opened, the file is processed and then the file is closed. And you'll find a lot of examples of these patterns in the wild in a lot of Ruby gyms and libraries they're all familiar with. So here's an example from Rails. I want to execute some things before I want to render an action and then I want to execute some things after. So you're all probably familiar with this. This is the around filter in your Rails controller. So for instance I can define an around filter that calls log action and in that filter I do something I yield and I do something else. And so this has less to do with resource acquisition and more to do with the concept of wanting to ensure that I can wrap behavior in another set of behaviors that will always be executed before and after. So that's why it's called execute around method. And then one of my one of the patterns that I like that is more of a Ruby idiom rather than necessarily a small talk idiom is what I call yield and return and you'll see this in Ruby 1.9 and also in Rails. And the question here is how can I send multiple messages to the same object? One way that you could do it would be to simply call each method in turn on that object on a new line but there may be a more elegant way to do that and I think that it's to yield to that object so that all of this happens inside a block and then return the object. Now an example here would be from will paginate. Now if any of you use pagination in your Rails applications there's a good chance that you use will paginate to do it. The will paginate is actually useful for more than just paginating database calls in Rails. You can actually use it to paginate any collection. So I want to paginate a custom collection with will paginate. Now one way you can do this is you can create a new collection. You can specify some options about it and then at the end that posts collection is ready for use. Now the the thing about this that strikes me as in elegant is that there's no clearly defined notion of when that post that posts collection is ready to be used. Is it ready to be used after I instantiated at the top? Is it ready to be used after I replace it with the results? Or is it only ready to be used at the end where I have posts at the bottom? And using this pattern if you put this in a block you can see that the posts object is only completely instantiated after it's been created and the block returns. So for me this is sort of a a data life cycle question which is how can I know that the operations or the behaviors that I'm performing on this object are complete and that I'm not in an intermediate state of the object? So going back this posts object here in the middle when you're replacing with the result is in an intermediate state where it's not really ready to be consumed. It's not really ready to be consumed until all of this has been performed and the block is quite clear about that. You can't access this posts object at that point after the pager has been replaced. You can only access it at the end of that block scope. And the implementation for this is actually quite simple. It simply wraps new to accept a block to yield to that new object and then to return that new object. And this is a pattern that I actually I'd like to see more of. I think it's a very useful pattern when you have complex instantiation or creation of objects. And so as you can see it yields to the object that's been created and then it returns it. Rails has something similar. Rails has this returning method. With returning you pass it the object that you want. It yields to it in the block and then it returns it. And Ruby 1.9 has the tap method which is like returning with self. So you can tap an object, pass it a block. Whatever is in that block will be done to that object when it's yielded and then it'll be returned. And this is often useful if you have a collection for instance and you're iterating over it with a select and then each and something's going wrong. Your each isn't working the way you expect it to and you're not sure if the select you're using to filter out those elements is incorrect. Without tap you would have to store the result of the select in a temporary variable, debug that temporary variable perhaps by logging it somehow and then iterate with each over that temporary variable. With tap you can just say object.select with your select block dot tap and then that tap will let you do anything to that object you want and then it'll return it so your each will function like normal. So tap can be useful for debugging but it's also I think a pattern that applies for other things as well. And another pattern that's very useful for me is one that I mentioned before is how can I write a method where many lines of code share the same parameters and temporary variables. So often when you're writing systems you may have methods that need to be called actions that need to be performed but they don't really represent what you would normally think of as an object that holds the kind of state that an active record model might for instance. So they don't really hold the text of a blog post or the amount of a transaction or anything like that. They're really just you're really just performing a lot of the same things with the same parameters or you're performing a lot of operations and they each need those same parameters. So the way that you handle this is that you create an object to represent an invocation of the method and inside that object all the instance variables will be available to all of the instance methods so that you can simply compose a method and then use the internal state of that object. So for instance here is a Ruby library that takes Ruby objects and turns them into dot graph files that you can load into graph viz. So you can see the composition of Ruby objects in a pretty cool visual way. And what it does is it takes a given graph and then there's an accumulator output equals empty array there and it passes the graph and the output to a number of different methods that do a few things. Now these methods are pretty intention revealing. This is a good example of composed method but you can see that we're sharing the same parameter in a number of places and we're sharing the same temporary variable as a parameter in a number of places. Now the only thing that's really important here for the dot file contest method is the graph itself. So the rest of that is really not is really shared state for those two methods the output classes and i-methods and the output i-methods and ids method. Those two methods share the graph and the output objects but nothing else really does because they're local variables. So you can move that out to an object that handles the command itself that handles the methods that are performed and then just run it on that. So for instance the implementation here is to initialize that object pass it in those locals that would have been temporary variables or accumulator variables or parameters and then those instance variables will be available to all of those methods and that generate that generate method at the bottom there. So those are some examples of patterns that I use and patterns that some of them were taken from the small talk book some were taken from my experience with Ruby but for me telling you all about the patterns that I know of is not as interesting to me as helping you understand how patterns are created because I'm not going to be able to think of every cool pattern or every useful pattern that exists in the Ruby world and Kent didn't think of every small talk pattern that was useful but what was important is a way of thinking about writing code so that you can create these patterns when you're writing your own code or you can identify them when you're reading someone else's libraries. So the first important thing to remember with patterns is that the context is very important. Each pattern solves a small part of the problem of writing good code and if you understand the context you'll figure out you can help to figure out which problems each pattern solves. So when you're thinking about patterns when you're thinking about when you would use a pattern which pattern you would use why that pattern is appropriate one of the first things you want to think about are what forces are at play and how you want to answer the problem in terms of anytime you want to make a decision you're going to be pulled in different ways. One way you may be pulled towards writing something that has to be performant enough but you may also be pulled towards writing something that is maintainable that is simple a lot of different tensions that are going to pull you in different directions. So using a pattern applying a pattern is all about understanding these tensions and the pattern should resolve them all the most harmonious way possible. So when we talked about query method how do I ask an object for information about itself? You can't answer that question without understanding some of the unasked questions about what the different forces at play are. I want to make sure I can ask it in a way that I can ask it one way, everywhere and get the same answer so I want it to be dry I don't want to repeat myself. I also want to be clear about what I'm asking it so I want the method name to be intention revealing. So when you decide on applying a pattern you should look at these different forces that are in play and then try to make a decision that balances all of these forces and comes to a good solution and then figure out try to remember not only what the decision you made was there but how you came to that decision what the forces were that you were thinking about and how you prioritized them and then how you eventually decided on a solution for all of them. So the first way that you can help learn to use patterns and also to identify your own patterns is to understand the context that you're using the patterns in. And there's a lot of good Ruby code out there. There are a lot of really well written gems that display some excellent Ruby idioms and Ruby conventions. And one of the ways that I've learned a lot of patterns is by getting involved in open source seeing what's out there seeing what other people that were doing that were better at Ruby than I was trying to ask myself well why are they doing it that way? Why didn't they do this a different way? And then that made me think about the different decision-making processes that go on in these people's heads why the code's written that way and that helps me make those same decisions and then apply those same patterns later. And after you come up with a collection of patterns that sort of make sense to you like composed method or query method the next step is just start writing your code based on these patterns see if it's more familiar to you see if the code that you write makes more sense is easier to understand because the code that you read is going to speak to you it's going to talk to you about whether it's written well whether it's fit whether it's suitable if you find yourself asking questions or find yourself confused or find yourself wondering why code's written a certain way that's your code trying to tell you something and so ideally when you're writing code it should be a pretty free experience you shouldn't be feeling a lot of dissonance in the code that you're writing because the well written code is both a joy to write and a joy to read I find I enjoy reading well written code because it doesn't give me the sense of dissonance in my mind that something is not quite right and often that something isn't quite right feeling that you have it's hard to put into words it may be hard to quantify exactly but it's important that you recognize that that's valuable to you when you feel that the code you're writing isn't quite right then you should take a step back and think about the decision that you made and the code is suggesting that there may be a better way so that is about all I have for patterns and best practices thank you all any questions? maybe more of a comment I want to bless it about that feeling you get when you know that something's not right and over time that feeling gets worse and worse and you get to the point you don't even want to scratch it and start over so the comment was that the feelings that you have when you're reading code that something may not be quite right sometimes they build up over time and eventually it just sort of becomes unmanageable you just can't bear to look at the code anymore and I think that is absolutely valid and one of the things that you can do to prevent that is get to the core of the problem and fix it there often times you make a faulty assumption you may have missed some important detail in the domain model and all of the decisions you make based on that faulty assumption will be more and more wrong and sometimes you'll find that if you fix that problem at sort of the base then everything you do onwards after that just simplifies sometimes problems just go away because you correct a faulty assumption David? I have a comment slash question about the whole idea of readability I mean I'm sort of in a crisis of faith about whether there is such a thing I mean, well let's put it this way I think there is you know I can say what I find readable and I don't but over the years I've just heard so many people use the word readable or you know say this is more readable than have examples that I find you know less readable I mean so it's one of these things that I'm sort of wondering if we're going to have to conclude that it's just like you know taste in music or something which I hate to think because I would like to think that there are sort of ways that we could roughly agree on I mean that's the thing there's no consensus so at least at a pretty granular level but I like what you're talking about I'm actually kind of like in a sense taking refuge in some rules or you know patterns though again I'm pessimistic about this sort of penetration of any of them because I mean as we know somebody will say well actually it's better to do this but I don't know if you have I mean this is just kind of maybe kind of existential crisis as any practical you know some of my period is what you were talking about some patterns are at odds in terms of the way they solve a problem and so you may select one pattern when another person would have selected another pattern for the same problem and then you may critique their the readability of their solution because you would have gone a different way but I think the important thing to remember there is is that the decisions you make don't happen in a vacuum they happen based on other code that's around the problem you're working on they happen based on the culture you know both of the code itself and of the organization and they also happen based on your needs at the time and the way you're thinking about the problem at the time and so I think that there are sort of fundamental I don't know that standard is the right word but there are fundamental principles that I think improve the communication value of code and that's what I want to strive for is code that communicates well I don't know that readability is the best term I mean it's kind of folds into the same concept of you know that just people's eyes I mean I have to take people's word for it when they say that such and such is more readable or communicative whatever even though it's kind of hard and you know you mentioned that not all people like the same music so maybe one person's yeah by the way it's really God I believe you I get it you know one person's musical taste may be different from another person's but at least in America we all pretty much agree on what basic harmony is you know we all pretty much agree on how many notes there are in the musical scale so there are these fundamental concepts that I think transcend should I use injector should I use you know something else and so I think that for a given piece of code there may be multiple ways to write it people would disagree on which one of them is the most readable to them but I think that they're probably all a lot better than some other ways that miss out on the on the fundamental principles and which is I I I I would like to think that the patterns that I try to use and that can I talk about in some way capture those more fundamental principles along the lines of what David is saying writing software is a creative process so you might give you know we've all agreed on a medium you know here we agree that we'll be and design patterns in my perspective are it's like it's like perspective it's something that you can use not everybody is going to use the same way but you know just generally it's it's a creative process and we're not always going to see art in the same way yeah I agree it's actually it's somewhat difficult for me to come up here and talk about patterns because for different people and for different organizations the patterns that you use will be different and the way that you think about your code will be different and so it's it is hard to come up with a blanket sort of I don't want to write the Ruby code style document that everyone is required to use what I want is to help people think about the decision-making process when they decide on their own coding style so that they are considering the important questions like does it communicate its intent effectively is it simple is it flexible you know these more basic values one key for me is you know six months down the line when I have to look at this code and I haven't tested it for a month will I remember or will I be able to figure out what it does so six months down the line when I look back at this code am I going to have any idea what the heck it does and that I think is a great test I usually when I write my code I think if I was going to explain what this did to someone else who's never seen it how long would it take and if it takes less if it takes more than a minute I think I need to rewrite it because if you look at that compose method for the deploy for instance I can look at that in a minute and even if I don't understand what update remote cache does in its implementation I don't if I don't understand how it's implement implemented I at least understand what I'm going to do if I call this deploy method in in the you know the general sense and so comparing that compose method to having all of it in line in the method and trying to understand that you know when I'm scanning there's the it's night and day difference so these patterns are all designed to optimize does your does the code you write will it be readable for other people understandable it's not just readable really it's understandable one of the things I found it's been a challenge especially when I'm in a relatively new environment language framework whatever is that there's code that I see that seems very obscure because I don't recognize it as a pattern I've never seen that before when I did see it before it looked like that so to me it just looks unnecessarily clever someone trying to you know I'm not sure that those are necessarily patterns well no but thing what I'm saying is that as I get a little familiarity with it I realize what that is and then I see it again and again in other places and I begin to recognize oh that's doing the very clever thing in a very compact way then at that point it becomes shorthand for sure what it's trying to convey and so it's very helpful to me to try to develop my sense of thinking that I'm looking for these repeating patterns trying to find what the code words are because I don't have to understand necessarily how this little thing works when I've seen it several times I know what it does I don't have to know how it does now but like you said at a harder level I know it's a copy and catch for fun you know one thing that I probably harp on far too much is that intent is far more important than implementation you know that little clever bit of code I don't need to understand the detail of the implementation if I understand its intent I mean I may need to understand the detail of the implementation if I want to rewrite it you know if I want to change it but if I understand its intent what it's supposed to do then that's the understandability that I need to be able to work with it so part of that is what we need to separate patterns and idioms as well as rubies and bearing idioms things like order idioms it's not necessarily patterns it's making that separation something critical so there's a comment is on making the separation between patterns and idioms for ruby and I think that the patterns that I talk about are on that separation line I think that the gamma et al gang of forestile patterns are very much more complex almost you know systems in and of themselves that you would use to solve a design problem whereas the patterns in the small talk best practice patterns book in the ruby best practice patterns book are almost on the level of idioms things like how do I name something you know correctly you know what is what is the ruby way to name a variable what is the ruby way to name a method what is the ruby way to iterate or filter out a collection and so you may actually you know they may be better called idioms to a certain extent it's not language specific it's best practice what a name and method is ruby or in java or in whatever it's the minus you have to make yourself clear so the comment is that best practice doesn't necessarily mean in terms of ruby there are general principles you should name things well there are general principles that apply beyond simply ruby but when you're working with a certain technology you have to understand them and how they apply within that context so it's very important to say name things properly but that will mean something different to a small talker than a will to a rubyist so what you tend to use are what you and your colleagues probably only something that collectively you understand as a group and I think that's a lot more important than trying to do things the ruby way on the rails when making applications for your job is make sure that your colleagues can understand it and have a corporate style instead of worrying about what everybody else is doing so the comment is that it may be more important since in ruby and rails you often work in smaller teams that you have a consistent style or a consistent language within the organization itself in terms of how things are coded how things are designed within that organization that may not necessarily have to coincide with the best practices for ruby or rails as a whole yeah a lot of things will be the same because rails very opinionated framework so one of the things that I like about ruby is that it'll let you do a certain thing in a number of different ways and some of them not all of them are good but some of them are pretty good you can iterate over a collection in a number of different ways there are a lot of ruby lets you skin a cat sometimes in a few different ways that are all feasible and so which one you use or which one your organization uses can to a certain extent just be a matter of preference within that group but even if I don't think this is what you're suggesting but let's take the extreme example of an organization that codes in ruby and writes their programs in a way that they understand but is not very divergent from the ruby and rails way what happens when they want to bring in another developer when they want to hand off that code to someone else it makes sense it's important to think about in terms of your organization that everyone in that organization understands what's going on but it's also important to think in terms of maintainability and in terms of downline a lot of eyes are going to potentially see your code I think David was first you mentioned literally just three or four people ever seeing it but I do think it's important I'm a bit sort of conservative on this I do think it's important to unless there's a really compelling reason to try to conform to the traditional ruby style I mean I know people like to have tabs of age instead of two spaces but unless there's really unless you're just not able to see it or if there's some real issue about it I really think that there's a reason that the traditional style has attracted so much I mean a lot of us got into ruby because it looked so good and it doesn't look good when you start you know changing sort of second guessing a lot of that stuff but also yeah I mean especially if the code I mean your example was really within a group but if the code is going to be distributed I mean I think one of the smartest things that David Hansen did with Rails and the others was to stick to a very just in terms of the style of very vanilla ruby style they did not sort of all the opinionated things one thing they didn't do was insert a lot of kind of you know different ways of you know different from the original ruby style they have the two spaces and the parentheses around this and that whatever in the source code I mean you know some of the patterns do talk about things on the level of how do you format code most of them don't but some of them do because within any organization you'll develop a shared vocabulary you know as to how you go about solving certain problems go ahead one of the key parts about the community though one of the reasons that I I work with want them in the community is A. it makes open source stronger because if we're all working as a community following so many standards you may only pick up your code within your organization once but not everything you develop in your organization has to stay there the question is what is your organization if you're working in a four person agile team and you know ruby and rails do lend themselves very well to small agile iterative you know teams I see a lot of two four six person teams is that really the actual scope of the you know of the influence of that code often times it's not and if you work in ways that your team understands to the detriment of you know people outside of your team and harm the project more than you may think I think many of us maybe consultants and I think we're all going to be doing some work on other people's code in our professional lifetimes that if we can all work on a new project with the confidence that we'll be able to understand that code when we see it then we'll feel you know we'll be happy about our jobs we'll be more productive with these you know with our contracts all these things so if there is a certain sense of shared responsibility for writing code to the best you know to the best practices as we understand them then I feel far more confident about being able to take on someone else's project and contribute value to it you know quickly and efficiently so that's important for me especially you know as someone who's involved with open source is being able to work on anyone's project and feel like I'm going to be at home to a certain extent that I don't have to spend days or weeks trying to understand the conventions you use within your community so the comment is I believe that oftentimes readability has been overloaded to mean pretty and for me readability is all about packing the most communication into the most efficient package possible so returning may be pretty and I like it for the pattern that it expresses I can understand that it's slower than some alternatives so there's always you know like I talked about tensions there's a tension between readability between the understandability of the code and performance often these are often at odds with each other and so you do sometimes have to make sacrifices in the prettiness or the readability of code for its performance I think that you can write I don't want to suggest that writing to best practices or patterns forsakes performance entirely I think that writing simple and flexible code is often leads to more performance code simply by virtue of being easier to change if it's easier for us to comprehend chances are it's easier for the computer to perform as well easier to instruct the computer so I don't know that returning is the best example of readability but I think it's a good example of a pattern that expresses a common need when you're designing you know a small part of a system so sometimes you can do what I would call a treasure hunt where this method has a lot of other methods that have a lot of other methods and then finally figure out what it actually the implementation is and that is certainly true that you can sometimes, if you really want to look at what that code does or rather how it does it you can sometimes dig through code you know and get somewhat frustrated in trying to figure out well how does it do this and that is one of those tensions, one of those forces that you consider when you're designing things that way how likely is it that I will later on be interested in looking at the implementation of this method and if I am likely then maybe I should optimize towards it being flatter in terms of the way it's composed but I would say that if you design towards intent rather than implementation that I don't necessarily need to look into that full system if I understand its intent, intent being what I expect to do when I call this method, what I expect to happen if I understand what I expect to happen I don't need to know how the system does it necessarily I think that's just a real basic principle of abstraction without which you would not be able to build the amazing system that are being built today and so I think there's just a point in which it breaks down between various things but we wouldn't want to give up abstraction just to understand better what's happening I've seen a lot of examples of methods that are essentially a three line method def something, do something very simple and the value in it is really just in being more intention revealing that the method informs the reader of its intent whereas not having that method only informs the reader of the implementation so I see a lot of examples of very small methods that seem to do something very trivial but actually when you use them all over the place they really enhance the the understandability of the code that is a decision that's made based on the importance of a certain factor in this case performance so performance is a factor and your optimization for understandability and for comprehension is affecting your need for performance then you have to optimize away from that but you're making the decision to make the code more suitable fundamentally really valid point because I see sometimes that we are constantly at least I get in the habit of knowing that a certain trick for technique performs better than another so I just always use it and forget that perhaps that technique is not very necessary or important it actually isn't better or else it's just I'm worried about a millisecond difference in the process that's going to take a day anyway that's why I think the comment for anyone who didn't hear it is I think essentially sometimes when we write code a certain way we develop habits in the way we write code and we don't stop to think about the decision making process each time that we don't stop to think well I'm writing this way to solve what I expect to be a problem because it was a problem before but in this case it's actually not a problem so what I think is an optimization or solving a problem is actually just wasted effort kind of thing and so that is why I really when I stress applying patterns I stress how important it is to understand the context each time you make the decision so that you can make the correct decision you have to understand the forces that are at play each time you make a decision or there's a good chance you're going to make the wrong decision and just doing the same doing something again just because it worked last time without being certain that the situation is actually the same that you're solving really the same problem that's carbiculting that's not applying patterns any other questions? alright, thanks a lot guys