 patterns you might actually is, and for the purposes of this talk, N is equal to exactly five. So a little bit about me. I tweet at ThagamizerRB, and if you want to follow along on your very own laptop on this fine conference Wi-Fi, the slides have been tweeted at my account. They're also at my website, Thagamizer.com. I have Thagamizer on GitHub, and I work at Substantial, which is a digital product studio in Seattle, Washington, and hosts the monthly SeattleRB meetups. So, motivations. I'm going to start with a magic trick. So everyone, think of a design pattern, and I'm going to read your minds. Everyone got one? Okay. Raise your hand if you thought of Singleton. Some of you are lying. I know that. So Singleton was the only design pattern I learned in college, and some of them from the audience today was actually in that class with me. Hi. And frankly, the example we were given was pretty lame, and I didn't understand the purpose of design patterns. I'm like, why would I ever want this? So let me see if I can read more people's minds. Raise your hand if you thought of something with the word factory in it somewhere. Okay. Let me guess. Y'all started in Java. And if you thought of something else, this talk isn't for you. I recommend Stumptown. Go get a nice coffee. Come back for tender love's talk in half an hour. So I did this experiment on social media. I did it on my Facebook, on Twitter, on Google Plus, and I'm like, hey, quick, think of a design pattern. Every single response I got was either Singleton or something with factory in it. So if you thought of those, you're not alone. And I used to think that design patterns were just kind of menturbation. I didn't get it. I'm like, well, why don't you just write code instead of thinking about these special names for different kinds of code? And my aha moment came at my current job at Substantial. And it came in the form of a pull request comment. This pull request comment, again, looks like strategies. And the again is important because we had had this debate multiple times. But this comment told me a lot. I had submitted some code for pull request that I wasn't happy with. I knew that there was something wrong with it and I knew that it could be better, but I didn't know how. And in four words, my co-worker Adam managed to tell me what to do to fix it. I could take the design patterns book. I could look up strategy. I could read about it and they knew how to make my code better. And quite frankly, that kind of blew my mind. Just one simple word, strategies, communicated everything I needed to do to make a change. And that's when I finally got design patterns. The matter is that design patterns are common vocabulary and software design. They're the names for the stuff you're already doing or if you're a junior, the stuff you'll get to with enough mentoring and refactoring. All professions have common vocabulary. I really like cooking TV shows, MasterChef and Hell's Kitchen. Big fan of both of those. And the people who win those tend to be the people who communicate well. They know how to use culinary vocabulary to communicate concisely and quickly, even under times of stress. I used to teach skiing to preschoolers and most of our 12 weeks of training was focused on giving us a common vocabulary for talking about the common things that kids did wrong when they were learning to ski. We learned terms like railed ski. We talked about things like the bunny hop drill. We talked about words like balance, edging, rotary, pressure control. And that common vocabulary made it really easy for me to write up notes on what we did in class each week. So if I was absent, someone else could pick up my class exactly where we left off. And I didn't have to put more than a couple sentences down on paper. Hobbies and professions have common vocabulary for the common things they do. And design patterns are the common vocabulary of software design. And after two years at substantial and about 10 years in industry, I finally drunk the Kool-Aid. And I'm hoping that at the end of this talk, you will have drunk the Kool-Aid on design patterns like I have. So set some expectations. Ben already told you have about 140 slides and 30 minutes. So I'm going to go fast. This talk is code medium. I don't give talks without code. But this is pretty light for me. And this is an advanced beginner to intermediate talk. So feel free to go hang out in the Hack lounge if you already know all this stuff. I won't be offended. If the code is too much for you, focus on the concepts. Really, with design patterns, the concepts are what important, not so much the code. In a quick overview, I'm going to cover five design patterns, template, strategy, composite, decorator, and command. For each, I'll let you know what the design pattern is, give you some examples, show you some code, and then give you some pros and cons of that design pattern. So let's dive right in. A template is an outline for a similar task. So some examples. ETL, who knows what ETL stands for? Someone shout it out. Extract, transform, load. Extract, transform, load. This is common in data warehousing. Extract, pull data out of one or more data sources, frequently a production database. Transform, perform some sort of munging on that data. And then load, put it into another database or another data store so that you can run reports on or do analysis on it. And that's a three letter acronym, but it's a common three letter acronym because it has common steps. Extract, transform, and load. There's a common process there. Likewise, active record models. Active record models are basically a template. They all share some basic functionality. Most all models have a save. Most models have some validators. Frequently, there's some other hooks that are built in. And we all know kind of know how to respond to a model because they have that common functionality, that common algorithm. Reports, who has a system that has reports? Every system I've worked on has reports somewhere in the system. And frequently, they all start looking kind of the same. There's a lot of common code. There's a general process to follow. They all have to get emailed to the same address. That's time for a template. And for record that star symbol in the corner, that represents places that I've actually used these design patterns in production code in the wild. So in my project right now, we have reports. I report these a template pattern. So how do you recognize when you need a template pattern? When you have a basic process, but sometimes some of the steps are a little bit different. So maybe this particular report has to pull data from two data sources, but the rest only pull from one. Or this report has to be emailed to one person, but the rest have to be emailed to a different list. Let's look at that reporting sample a little more closely. So here's a report, the past two accounts report. It's got an extract method and aggregate method and an email method. And then it's got this generate method that runs through those in order. Generate the report by extracting data, aggregating it and then emailing it out. And here's another report from the system, the new users report, extract, aggregate, email, and then the exact same generate method. Clearly, we should pull the common code out somehow. So let's make a template. But first, let's point out all the common code in this class. This is the same report, but I've grayed out all the bits that are different. You'll note that almost all the code is exactly the same between these two reports. So here's a template. Let's look at it piece by piece. That generate method was identical, so we just pulled that straight out into this base class. And then we're going to define our extract aggregate and email, but we're going to raise. We're going to raise because we want anyone who inherits from this to have to implement it themselves. And we're raising NYI, which stands for not yet implemented, if you're not familiar with that three letter acronym. So let's see how this looks when we use it. So here's the new user report, using the inheriting from report template. So I got rid of that whole generate method, and we're following that common interface. Here's the pass to accounts report. Again, we got rid of that whole generate method. And again, it looks very, it looks much simpler. And this is just a starting point. There's a lot more refactorings you could do with this to make it even more efficient and pull out even more of the common code. But let's move on and talk about some of the pros and cons. So primary benefit of a template is you laws you to share common code and isolate the differences between your various reports or your various models. It's easy to add new versions. I want a new version, okay, well I just have to define three methods and poof, new report. And it forces a common algorithm. And this might seem like a disadvantage, but when you're working on a team where people are coming in and out or you're bringing on junior developers, having a basic outline of this is how we do this is really helpful. It means that your pieces work better together, and folks have less work to do to come up to speed on how your process works. So if everyone knows that your reports have an extract, aggregate, and email method, it's pretty easy for someone to say okay, I just have to implement those three and we're good to go. They don't end up reinventing the wheel or making something that doesn't play nicely with other parts of the code. But everything has some disadvantages. You have to read multiple files to find out what's going on. This is actually a fairly common criticism of a lot of the design patterns I'm going to go over. Some of those methods are in the base and you may have run into this with active record or active model. You're like, wait, where does that method come from? And it turns out it's like five levels deep in rails and sometimes it's only built when you have a method missing and it can be hard to figure out exactly what's going on. And the template pattern uses inheritance. And inheritance can be a real pain. And another disadvantage is that it uses inheritance because inheritance can be a real pain. And you might be thinking, well, object-oriented programming 101 says inheritance is awesome. Inheritance can be awesome, but it can also get you in some really awkward situations like this one. So let's say we've got three reports A, B and C and they share some common code. We've got reports B and C share this load two function at the bottom. It's the same between the two of them. And reports A and B share this extract one function. And if I need to make a template from this, what goes in that template? Do I put extract one in that template? If I do that, then report C has to override that. And maybe that's okay until report D comes along that also uses extract two. Or maybe I make a class and then a subclass and some crazy hierarchy and it can get really messy really quick. Turns out there's another pattern for that. And that pattern is strategy. So what is strategy? Well strategy is the polymorphic algorithm of course. Yeah, that's not particularly helpful, especially if you're new. So strategy is a way of changing the algorithm at run time. Also not particularly helpful if you're new. Confused dogs for the win. I like to think about strategy as a way of doing an extract algorithm. You know about extract method or extract cat class extract strategy extract algorithm is what you do with strategy. But let's look at a diagram. So we've got some basic code. It's got a four step process. Step one and two were common. Some crazy stuff happens in step three. And then step four is common. And if we do this with strategies what we end up with is something that looks like this. Step one is common. Step two is common. There's some common code for choosing a strategy. And then we go call out to classes that are step three A or step three B or step three C. And those don't have to even be the same shape or anything. They can all be very different. And then we come back and we do step four together. So let's look at some examples. Storage strategy. We're using this on my current project. You have some social network site where people can share media and maybe in development you don't want to you want to store all the files locally so that you have access to them. You can make sure they got transcoded properly by your code and stuff. But in production you really don't want to store your files on your production web servers because that way madness lies. You want to throw them into some sort of cloud storage offering like S3. Well you can use a strategy to pick store locally or store in the cloud. You could also use a strategy to figure out what are the transcoding steps or what are the thumb nailing steps I need to run on the different types of media files. Another example stock market. Maybe you are trying to build the next big Wall Street app that's going to make everyone tons of money. And so you want to have different investing strategies for different stock market conditions or different types of stock in your national versus small cap or different risk profiles of your clients. Another great example specifically particularly for this conference is sales tax. Oregon has no sales tax. Washington has sales tax. Canada has crazy sales tax. Plans of sales taxes and you might need depending on where your customers are from you need to charge different amounts of sales tax and account for that differently strategies. So how do you recognize it? You need a strategy when a process is the same except for step three or when you're using inheritance to combine common code and it's starting to get really hairy or when your code looks like this. Got step one got step two. There's some crazy stuff happening here in step three. We're looking at our argument and if it's X we do one thing if it's why we do a different thing. If it's Z and B is one two three we do a third thing. It's crazy. So what does that look like if you use strategies. Well here's one way to do it. We're going to make our strategies a hash and in our initializer we're just going to say our key is our key is X or Y or Z and then we're going to call into our we're going to make a new strategy object. And then when we get down to step three we just take our first argument A and look it up in the hash and run the appropriate strategy. And that's all well and good and here's what this looks like as a whole thing got rid of that nasty if so that's a bonus. What happens when we need to add a new strategy. Well there's one way to do it which is in your initializer you can throw another strategy in for the key AA. You only have to change one line and that's awesome but this is even cooler. You can make a method called add strategy in your class that takes a key in a strategy and this means that anyone anywhere in the system can inject a new handler can inject a new strategy into your project and all they have to do is call this like here I want you to handle AA by doing the AA strategy dot new which means you can do that in your starter code and rails or you could do it in a config file or you could have it injected by a third party system into your system via an API might be dangerous might be awesome you don't know until you try it benefits of the strategy pattern allows you to share common code and isolate differences sounds familiar doesn't it. It's really easy to add new strategies there's multiple ways to do it and you can do it independent of your class and you don't even have to know what the strategy should be when you write the class you can have someone else do it for you later and it makes you use a common interface this is great because it makes your code more consistent more reusable and frequently improves the object orientedness of your code and finally it allows you to avoid that avoid that inheritance mess we saw before but there are some downsides again you have to read multiple files to have any clue what's going on it's much harder to follow in source because you have no idea necessarily what strategies are going to be in place at runtime someone may have injected something crazy you don't know you don't know what strategy is going to be picked necessarily until you actually look at a stack trace and sometimes your strategies need to be initialized with lots of data a lot of people get around this by passing self into the strategies if you're tempted to do that reconsider your design it's probably violating some of the solid principles somewhere and finally you must have the same interface for all of your strategies we use strategy pattern very widely on the project I'm working on right now and occasionally it's been really hard to shoe horn something into the existing interface but that's almost always indicated we have a different problem that we need to solve and the problem is not that we can't use the strategy pattern it's that we're modeling something as similar that really really isn't so two strategies down three to go composite what is it it's common interface for one or many things and you're like common interface what so it's a way of letting consumers ignore the real quantity of objects they're dealing with they can be dealing with one or many and they can run the same method and they don't have to care so some vocabulary about composite this is the only UML I'm going to show today but I couldn't do a design patterns talk without including some UML so the component is the interface that all of your elements of your composite are going to implement in this example the component has one method operation anything that is part of your composite must implement operation you might have a leaf which is going to be something that doesn't have any subcomponents or you might have a composite which also implements operation that has a collection of subcomponents as well and when it it's operation method completes that operation on all of the subcomponents so let's look at some examples task management who uses a task manager like omni focus or things or have an RPG or any of the other great ones that are out there right so most of them support a task that is atomic empty litter box they also can support a task that has sub tasks prepare your talk for good for cascadia ruby conf and that might have a sub task of pair slides and that might have five sub tasks of slides for strategy slides for template slides for composite or practice practice once practice in front of your coworkers practice in front of your meetup group and but all of those tasks supported done method and when they're done the UI changes from an empty checkbox to a check checkbox and if I check a single task that task gets a checkbox if I task a check a parent of a task all of its sub tasks also get checked off another example is html you might have a div that div might be standalone that div might also have 1000 divs inside it if you want to show or hide a div you want that effect to transfer to all of the children composite and a kind of interesting example that you don't think about often is something like test scores high stakes testing is really common in the education world right now and schools have to report test scores on a per student basis a per classroom basis which affects teacher performance they have to report test scores on a per school basis which frequently shows up in real estate listings among other places and they have to report their test scores on a per district basis which will affect their funding from the federal government and frequently from the state government and you have to be able to compute an aggregate test score at all of those levels so composite so how do you know when you need to composite you should use a composite when you have to perform a similar action or calculation on one or a lot of something or when you have to handle trees of arbitrary depth so let's talk about that reporting scores method here's a really naive implementation so if it's a student just get their score passing one argument in if that argument is a classroom we're going to take all the students we're going to map across them to get their scores and then we're going to average them and I'm using the magical non-existent version of array that has average built in and if you have a school you can take all the classes in that school map across them to get a collection of students which is actually a doubly nested array so then you're going to flatten it and then you're going to take you're going to map across that to get their scores and then you're going to average them and that's disgusting so how can we make this cleaner make a composite so here's a component interface and you don't actually have to implement this in Ruby and I recommend you don't I'm including it for very for clarity here but all of our components are going to implement a score method of some kind so let's look at what the student class looks like student has an adder access to it for score Ruby writes the score method for you okay well that was simple scores just an attribute well classroom has a collection of students and it has a score method that maps across those students and averages their scores okay that looks pretty good school has a collection of classes and the score method maps across the classes gets their scores and averages them okay and look what this does to our report score method it goes from seven lines or eight lines of crazy case statement with classes in it to a single line that's awesome so advantages you only have to use one common interface your customers don't have to know how many objects they're dealing with you can have an arbitrary depth that's really cool you can frequently insert stuff in the middle of your hierarchy relatively easily and everything still works so maybe you want to start reporting on sections or grade levels in addition to classrooms and schools not that hard to do and no messy ifs here is a ruby pro tip if you are checking the class of something in ruby you're probably doing it wrong generally that's not how ruby's written so the downsides it's harder to follow in source you have no idea in that report score method what class that thing is you don't know if it represents an individual student or the 40,000 students in some school district somewhere and that has some fairly significant performance implications you have to prepare that you might be running that calculation on something that's going to take a long time so final design pattern actually second to last design pattern decorator what is it it's a way to extend an instance of an object yeah not actually helpful so a lot of people think about this as it's a wrapper that adds some functionality to existing instances and here's what that looks like you have my object you wrap some stuff around it but you keep my object interface the same then you can wrap more stuff around it my object interface stays the same but now it's got the blue functionality and the green functionality which means it's twice as awesome so some examples classic example is GUI elements you've got a window you want to add a scroll bar to it so you wrap it in the scroll bar decorator it's now a window that can scroll but it's still a window and it still supports all of the window-y stuff about a window okay well maybe you want a scroll bar and a status bar so you wrap your scroll bar wrapped window with a status bar decorator and so now you have a scroll status window and it still supports all the window-y stuff but it can scroll and it has status bar functionality and that's awesome if you work on an e-commerce site you probably had to deal with calculating discounts buy one get one free 10% off for the month of March only no sales tax if you have this magic coupon code that we sent you in a spam email that you deleted and those have to work together so decorators wrap your shopping cart with the buy one get one free decorator wrap your shopping cart with the coupon code no status no sales tax decorator as long as you support the same interface as your shopping cart so a tax and a total it's good to go you don't have to worry about all the different combinations that your customers might come up with and my favorite I put on my robe and wizard hat and we have some RPG characters so you've got a base character you get a buff to perception great perception decorator and then you cast some spells that have effects so you have your golden wolf which gives you extra strength extra strength decorator golden wolf decorator it's awesome so how do you know when you need a decorator you need a decorator when you want to add additional functionality to an instance of a class but only sometimes if you want to add that functionality all the time it goes in the class but if you only want to do it sometimes decorator is the way to go so our characters got a character has health damage and XP if they're alive if their health is greater than 0 and you can attack enemies and pow I cast might of the dragon and my damage is increased by 50% so time for a decorator here's my dragon might decorator and we're going to initialize our decorator with our character store that off in an instance far and we said that our damage was increased by 50% so we're going to take our we're going to rewrite the damage method and we're going to take our character's original damage and multiply it by 1.5 and I mentioned that decorators have to preserve the interface of the underlying class so here's how we do this in Ruby we can use forwardable which is in the standard library you require it you extend the forwardable module in your class and forwardable gives you this great method def-delegators and it takes two arguments the first is who should receive your messages in this case character and the second is a list of the messages to send to that class which in this case is health and XP so we're basically saying that I don't want to deal with health and XP just pass them to the original character and use the original implementations that's fine so let's check it out see if it works we instantiate a character give it 100 health and 10 damage and we have our dragon might decorator and we initialize that with our character and now our damage is 15 so that part worked but we need to make sure that we preserved our original interface so our health is going to check our health and our health is still 100 so we did preserve our original interface and this totally works so pros and cons gives you the ability to change behavior dynamically it allows you to customize an instance it allows you to support nesting of multiple attributes so you can have all sorts of different crazy spells on your RPG character and they can interact in awesome ways and you don't have to worry about how that happens at development time and some downsides you're offloading your pain to your consumers and all the stuff I've read about decorators it's frequently used when people don't know what people want to do with all these enhancements I don't know how these are going to combine I'll just make a bunch of decorators and then whoever has to use them can figure it out and that sucks if you're the consumer you're like okay which of these decorators can I use in which circumstances and how do they interact and you may not have to instantiate five objects in order to get the functionality I want that's pretty lame and you have to use multiple files again you have no idea where your given damage method is coming from and how many times it's been rewritten in your decorator tree and that can get really confusing and finally many decorators frequently leads to unpredictable behavior if you cast dragon might spell three times what happens how is that supposed to work or maybe you have a plus strength and a minus to strength of different percentages do those combine in the right way you don't know so final design pattern command what is it it's an objectified closure which pretty much means nothing so objectified closure the command pattern is an object containing an algorithm in the context to run that in so an example delayed job who uses delayed job hands yeah using delayed job you're most likely wrapping up some data and something to do with that data and then saying hey delayed job do you think drawing applications canonical example of command pattern is do and undo and so if you've got something you need to write some code that does a stroke well that's a command and the data is how to draw that stroke and then the undo is how to undraw that stroke active record migrations when up and down for those of you who actually worked in old versions of rails instead of this fancy stuff with change up and down and do and undo another example recognizing it first time if you're going to do an undo you probably want a command pattern work on an app that supports undo we use the command pattern it's really handy here's an active record migration you can see the up and the down this is from a rails 2 app that I had locally for those of you who haven't seen this syntax because you only use change and in this case the context is the database and you get that from inheriting from active record migration that takes care of the context for you another time you might want to use the command pattern when you want to do something but you want to do it later so you wrap up all your data maybe generate this really complex report and your algorithm and then throw it off on disk or throw it in your database so delayed job can pick it up or have a cron run it you're wrapping up a whole bunch of you're putting an object around some data and something to do with it command pattern delegation maybe you want to do something but you don't want to do it yourself you want someone else to do it wrap your data in your context command pattern pros you can support undo and redo you can offload, queue, distribute or delegate things with the command pattern it's simple to understand and it encourages good design because you're making tiny little pieces of functionality that you can use and reuse in different projects or in different ways downsides it's overused because everyone can pretty much understand it it's used in also over the place and quite frankly in Ruby you're probably not going to need it we have prox we have lambdas we have blocks all of those are closures all of those can act as the command pattern use them don't actually make classes if you don't have to so by this point you're probably either asleep or thinking so what and the big point is you're already using patterns everyone in this room has most likely seen something similar to one of the examples I covered today they have done something like this so you're already using it you might as well use the common vocabulary to save yourself some words and to make it so that it's much easier for you to talk to other developers about what you're doing quick cheat sheet you have several objects that are mostly the same template got a process of the same except for step three strategy got a bunch of hierarchical objects composite if you sometimes need an enhancement decorator if you need to undo delay or delegate command so if you want to learn more because I really didn't cover even the beginning of design patterns here you need to get a copy of this book one of the reasons I love working at substantial is that we have multiple copies of this book floating around the office and it makes me really happy but it's called design patterns but you're almost never going to hear it called that it's almost always called gang of four or surprisingly fairly frequently golf frequently in text and that's after the names that's after the fact that there are four primary authors on this text so if you hear gang of four in a computer science or nerdy context they probably mean this but if you're not real comfortable with C-like or Java-like code and you prefer something that's pure Ruby this is a really good book as well Pete recommended this to me I really liked it I read most of it while preparing for this talk and the thing I especially like about it is that it calls out the places where Ruby does this for you and the command pattern it points out that you can just use a proc and the iterators it's like yeah we kind of have those built in learn a numeral, go and it gives you that functionality so that you don't have to worry about that stuff but really the place you need to go is the original wiki like really this is the first wiki Google Portland pattern repository or C2 wiki it was built here written by folks from Portland all of those pioneers of object-oriented design and design patterns and if you spend just two hours with this I guarantee you will be a better developer go, go do your wikipedia thing but do it with a lot of smart people coming at you as opposed to random people on the internet so a quick thank yous thank you to Ben Karan and Jonan for making this conference happen I love it, I've spoken on it every year because it's awesome thank you to the folks at Seattle RB for helping me decide what patterns to include especially Ryan, Aaron and Pete composite pattern is included specifically because Pete mentioned it and thank you to Substantial for sponsoring me to be at this talk giving me the money and the time off to come here and for being awesome and specifically I wanna thank my lead and my manager Adam Pearson and Adam Smith because they were the ones who had somewhere between a dozen and two dozen arguments with me about the value of design patterns before I had that aha moment and the fact that they had the patience to do that really says a lot about them so I don't have any time for questions but come find me, I wear pink that makes me easy to find I'll be wearing pink tomorrow so I will still be easy to find thank you very much