Slide 1

Slide 1 text

Wednesday, 13 June, 12

Slide 2

Slide 2 text

Design patterns Wednesday, 13 June, 12

Slide 3

Slide 3 text

WTF? Wednesday, 13 June, 12 So... Why Design Patterns? They’re those things used by people in static languages like Java and C# right?

Slide 4

Slide 4 text

WRONG Wednesday, 13 June, 12 Mother Fucker.

Slide 5

Slide 5 text

Wednesday, 13 June, 12 Design patterns aren’t some shit that’s set in stone. They’re guidelines, patterns, perhaps a good idea because some poor bastards run into the same problem already.

Slide 6

Slide 6 text

Wednesday, 13 June, 12 These patterns are more like the the cookbook of software development. Sure if I wanted to cook a chicken I could put it on a fire and eat a piece of it every once in a while to see if it’s good. Or I could open a book or the internet and get some guidelines on the right way. We want to make systems that are awesome and don’t break each time we want to introduce changes.

Slide 7

Slide 7 text

Useful Bits Wednesday, 13 June, 12

Slide 8

Slide 8 text

Single Responsibility Wednesday, 13 June, 12 One of the SOLID principles. We want to reduce the cascading effect changes to modules can have on other modules within a system

Slide 9

Slide 9 text

T X Y Z Wednesday, 13 June, 12 If I make a change to Module T, I shouldn’t have to make changes to any other modules except for perhaps Z. Any further than that, and well you’ve done goofed and didn’t adhere to the SRP.

Slide 10

Slide 10 text

Interface Wednesday, 13 June, 12 Program to an Interface

Slide 11

Slide 11 text

Interface Wednesday, 13 June, 12 Well wait... let’s scratch that. Interfaces sound to java/C# esque and bring in some programming ideas along with it.

Slide 12

Slide 12 text

Protocol Wednesday, 13 June, 12 Instead program to a protocol. Here we have a set of functions we expect and we’ll *only* use those ones. That is our protocol. Therefore, any object given to us that follows that protocol can be used by us.

Slide 13

Slide 13 text

Wednesday, 13 June, 12 For example, here we reverse a stack. The stack object could be whatever the hell it wants. As long as it responds to the push and pop function, our method doesn’t give a damn.

Slide 14

Slide 14 text

Composition Wednesday, 13 June, 12 Prefer composition objects versus just having things that inherit from ancestors. Inheritance can easily lead to a violation of SRP and a change in a parent class can mess shit up for your classes. Composition allows us to keep our inheritance tree relatively shallow, which can drastically simplify our system.

Slide 15

Slide 15 text

Delegate Wednesday, 13 June, 12 Finally, whenever possible delegate a job to something. Often our objects don’t need to know the fine details of how something works.

Slide 16

Slide 16 text

Wednesday, 13 June, 12 For example, there’s too much going on in this function. The adventurer needs to know too many minute details about the target.

Slide 17

Slide 17 text

Wednesday, 13 June, 12 Instead, what we can do is delegate as many of the functions off to others since the adventurer really doesn’t care about the details of how damage is dealt or how dice are rolled.

Slide 18

Slide 18 text

Wednesday, 13 June, 12 Alright, so let’s into some tasty patterns.

Slide 19

Slide 19 text

Template Wednesday, 13 June, 12 A relatively simple pattern. Usually when we have objects we want them to do something. For example we could want objects that generate charts or have different adventurers who all attack differently.

Slide 20

Slide 20 text

Wednesday, 13 June, 12 Here we could have a hero that does an attack, but what if we want to add a new hero to the mix? We could simply add some conditional statements, but that kinda sucks.

Slide 21

Slide 21 text

Wednesday, 13 June, 12

Slide 22

Slide 22 text

Wednesday, 13 June, 12 Instead what we could do is simply have a function that we expect the subclasses to implement or override. Those optionally overridden functions are often known as stubs.

Slide 23

Slide 23 text

Strategy Wednesday, 13 June, 12 While the template can work, it’s often not the right kind of solution. We don’t always want a different class just because our objects do slightly different things. This is where the strategy can come into play.

Slide 24

Slide 24 text

Wednesday, 13 June, 12 A ruby-ish way of implenting the Strategy would be to allow a block to be passed in as the Strategy function vs, passing in an object that conforms to a certain protocol.

Slide 25

Slide 25 text

Wednesday, 13 June, 12 Now we can easily create some objects that all have different kinds of attacks.

Slide 26

Slide 26 text

Wednesday, 13 June, 12

Slide 27

Slide 27 text

Observer Wednesday, 13 June, 12 We’ll run into situations where other objects need to know about the changes that are going on to things.

Slide 28

Slide 28 text

Wednesday, 13 June, 12 Since these changes are relevant to the objects interest, we can simply make them observers and any time changes happen (that we deem relevant) we inform our observers about it.

Slide 29

Slide 29 text

Wednesday, 13 June, 12

Slide 30

Slide 30 text

Wednesday, 13 June, 12 Now, that we have an observable object we can add our observers. All the need to do is respond to the saw_flash function, and boom, they’ll know when changes happen to the observed object. To get an idea of where the Observer is used, we need look no further than Active Record. We are able to create Model Observers so we can be notified when a model’s changed so we can perform various actions based on however the content changed.

Slide 31

Slide 31 text

Composite Wednesday, 13 June, 12 Usually we want to be able to represent a very complex workflow as simply as possible. Through the Composite we can figure out some basic components and build our system from that. GUI libraries are an example of how the composite pattern can be used. We have a window, which has sub components like buttons and text areas which can be arbitrarily deep.

Slide 32

Slide 32 text

Command Wednesday, 13 June, 12 Another straightforward pattern is the Command. Basically, we want to tell an object to perform a specific task such as when a button is clicked or when some other kind of event has happened. As rails developers we've actually seen the command pattern in action any time we've wanted to make a change to the database.

Slide 33

Slide 33 text

Wednesday, 13 June, 12 For Active Record, our Execute commands are the #up and #down methods. By providing these we've told the migration what to do when it's time comes.

Slide 34

Slide 34 text

Adapter Wednesday, 13 June, 12 Often we'll run into an interface that we naturally cannot use. For example we could have an HDMI projector but are stuck with a Mini-Display port. Luckily, we have adapters that make it possible for our computers and display devices to exist in harmony. As with hardware, we often need something to make it possible for our existing system to easily plug into a new library or service. This is where our Adapter comes into play.

Slide 35

Slide 35 text

Wednesday, 13 June, 12 I was going to show off some active merchant code, but there’s way too show off for a 1hr presentation. In essence though, I wanted to elaborate how we can use Adapters to take an unexpected API and turn it into something that fits more comfortably into our system. This is often the case when integrating with 3rd parties, and Active Merchant is a perfect example of how we can create order from a chaos.

Slide 36

Slide 36 text

Proxy Wednesday, 13 June, 12 Sometimes we want to provide access to an object, but there are some conditions. This could be the actual data is remote or we could have some sort of permissions required before we actually give access to the object. This is the time where instead of providing the actual object we'd put a proxy in front of it. For all intents and purposes, the client doesn't really know the difference between a proxy and the real thing since the proxy behaves in a similar manner

Slide 37

Slide 37 text

Wednesday, 13 June, 12 So let’s say we have a brewpub. They like to let people in, and they do. Unfortunately we have these laws that only permit 21 year olds into establishments of fine drinkery, but we don’t want these details to bleed into that of the BrewPub. They have more important things to worry about like making beer and serving people.

Slide 38

Slide 38 text

Wednesday, 13 June, 12 Instead what we could do is have an proxy to the brewpub that enforces the age limit. We could achieve this as follows. But this sucks! If there’s anything we don’t care about we need to just pass it off to the actual brewpub instance. Luckily in ruby, there’s an easy way to do this.

Slide 39

Slide 39 text

Wednesday, 13 June, 12 We can simply implement the method_missing function in ruby then just pass of anything we don’t care about off to the patron instead. This allows us to add new features to the patron object while keeping the code in our proxy stable, and only requiring changes when we need to change how the proxy works.

Slide 40

Slide 40 text

Singleton Wednesday, 13 June, 12 The global variable, a single instance, the app delegate, whatever. This is the one object to rule them all. While they can be useful (such as storing settings for a desktop app or something) the temptation to add things that shouldn’t be there is ever so strong. And before you know it...

Slide 41

Slide 41 text

Wednesday, 13 June, 12 Your singleton has turned into this horrendous glob that corrupts everything it touches with it’s plagued appendages.

Slide 42

Slide 42 text

Decorator Wednesday, 13 June, 12 Similar to the Composite, the Decorator allows us to add new functionality to our objects at run time. The GoF example is a GUI window. Let’s say we wanted to add a horizontal slider to it. We could subclass window with a HorizontalSliderWindow, but what if we wanted to add a vertical slider too? Well now we’d need to have a VerticalHorizontalSliderWindow. As you can tell, things can get a little bit out of hand, and the system could become a bit of a nightmare to maintain.

Slide 43

Slide 43 text

Wednesday, 13 June, 12 Let’s say we this LineWriter which does some pretty simple things. It takes in an array of strings and writes them out to the terminal. Simple enough.

Slide 44

Slide 44 text

Wednesday, 13 June, 12 Now, let’s say we wanted to add the ability to add timestamps and line numbers to the output. We could’ve went the more traditional approach and had our writers take in a writer, but instead we can use the power of the Mixin to easily add the functionality we desire.

Slide 45

Slide 45 text

Wednesday, 13 June, 12 We could’ve included these writers in the TextWriter class, but then that would’ve made it a hard inclusion. What if depending on certain conditions we want to use different writers? This is where we can simply call extend on our instance with the module we want to add to our object.

Slide 46

Slide 46 text

Factory Wednesday, 13 June, 12 Often times we’ll run into the situation where we don’t completely know what objects we’ll be using at runtime. But we do know what protocol the objects we’re getting will conform to, but other than that we really don’t have any more information.

Slide 47

Slide 47 text

Wednesday, 13 June, 12 Typically when we see an example of a Factory it’s in a style like this. While it does work, it’s not very rubyesque and there’s most definitely a better way we can implement the Factory pattern in Ruby

Slide 48

Slide 48 text

Wednesday, 13 June, 12 Here’s a simple example of where we used it in Active Fulfillment and within Shopify. In this example, Base.service is the factory that constructs the classes for our consumers to use. While, it’s not pulling out fully instantiated objects, it’s doing almost all the work for actually getting the object we care about.

Slide 49

Slide 49 text

Builder Wednesday, 13 June, 12 The final GoF pattern we’ll be talking about. Often when we want some easy way of setting up data we’ll use a builder. They provide a nice interface and a way of helping ensure that the resulting objects are in a sane state.

Slide 50

Slide 50 text

Wednesday, 13 June, 12

Slide 51

Slide 51 text

Wednesday, 13 June, 12 An even better example of a builder is Nokogiri. It provides an interface that makes constructing XML extremely simple

Slide 52

Slide 52 text

Wednesday, 13 June, 12 Alright, so now that GoF is out of the way, let’s get into the good parts. That is, some new patterns that are somewhat specific to ruby, but are also very prevalent in Ruby projects.

Slide 53

Slide 53 text

Domain Specific Languages Wednesday, 13 June, 12 Sometimes we reach a point where we’d like an easier way to interact with our system. This could be for the sake of our end users, or it could be to simply our own lives. The Ruby world is rich with examples of DSLs that range from rendering HTML to testing and automation.

Slide 54

Slide 54 text

Wednesday, 13 June, 12 Let’s return back to our Hero example. Now, let’s say we wanted to provide an easy way for a user to pass in their characters statistics and gear. Currently that would require they write a bunch of code, which isn’t necessarily friendly.

Slide 55

Slide 55 text

Wednesday, 13 June, 12 What we could do instead is have this HeroSheet, which loads up a file or string and extracts that information into a hero object. We can also delegate anything that is hero specific off to the hero by simply implementing method_missing

Slide 56

Slide 56 text

Wednesday, 13 June, 12 Now this is what our DSL would look like for the HeroSheet shown previously. Now, we've all seen plenty of DSLs in our every day work at Shopify. The rails routes file, our test suite, rake files and if you're working outside of Shopify core, RSPec. And this is just naming a few!

Slide 57

Slide 57 text

Meta- Programming Wednesday, 13 June, 12 This is something I don't have a lot of experience with, but it's a pretty awesome concept. The basic idea behind metaprogramming is we can, at runtime, modify our objects and even classes. This could be things like adding new methods to an object or including modules. Rails relies heavily on meta-programming to provide a lot of it’s magic.

Slide 58

Slide 58 text

Convention Over Configuration Wednesday, 13 June, 12 Configuration via XML, it's a nightmare. Often to get even the most basic system running, you'd need to configure. Things, shouldn't need to be this complicated and rails showed a way to have a very solid system that didn't need all this configuration. The premise is quite straight-forward, we have a system that makes some assumptions about where things will be or how they will be named. With this in place we can provide an easier to use interface which also allows for extensions to be easily added.

Slide 59

Slide 59 text

Wednesday, 13 June, 12 Let's go back to that ActiveMerchant code we were looking at. Primarily that of ActiveMerchant::Fulfillment::Base. Adding new services is exceptionally simple and requires the least amount of change to the code base (simply add tests and the new service).

Slide 60

Slide 60 text

Wednesday, 13 June, 12 Design patterns have a pretty bad reputation, but as we’ve seen, they are still quite relevant to other languages like Ruby. The difference is that several of these patterns we can pretty much get for free or for very little effort because of how Ruby has been designed. Also, because of how easy it is to dynamically change things in ruby, implementing the other patterns is typically quite simple.

Slide 61

Slide 61 text

Wednesday, 13 June, 12 Questions?