Dependency Injection on the small
I've been, very slowly, going thru Sandi Metz' wonderful Practical Object-Oriented Design In Ruby. In Chapter 3, which deals mainly in managing dependencies, one of the suggested ways to loosen coupling between entities is to inject the dependency.
This got me thinking about my usual playground for programming ideas, my eternally-in-development Halibut library. In it there are two classes that are very much entangled, in a very similar way to the book's examples: Halibut::Core::Resource and Halibut::Core::Link.
You can see this coupling here,
Halibut::Core::Resource
def add_link(relation, href, opts={}) @links.add relation, Link.new(href, opts) end
which method is further called from other places.
def initialize(href=nil, properties={}, links={}, embedded={}) β¦ add_link('self', href) if href end def add_namespace(name, href) add_link 'curie', href, templated: true, name: name end
On top of the several connascence of name sprinkled through the Halibut::Core::Resource class each time I send a message to Halibut::Core::Link, and this includes #new, we also have connascence of position and probably some other types of dependency.
What this essentially means is that any time Halibut::Core::Link changes, especially the initializer method, we are probably breaking Halibut::Core::Resource. This might not be a big deal, since it's such a small library and you can even argue that such breakage is actually desired, since all these pieces are meant to work together.
On the other hand Resource already depends on Link, and I'm not doing the user that much of a favor by shoving "implementation details" further down the road. The user already has to know that a link has a href, and possibly options, and which type of options it supports, so I might as well make it explicit and make the user inject the dependency directly.
Having added Halibut::Builder to the library, I'm actually more confident in making this change. The builder pattern allows a straight-forward (I hope) way to build a resource, making use of the much popular DSL pattern.
You can see the diff after applying this change right on GitHub











