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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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...
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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
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!
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.
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.
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).
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.