Wednesday, March 11, 2015

Dependency Inversion Principle in Practice

Ever notice how the requirements of an API affect the design of your classes? Well, they shouldn't!

Consider the requirements for using resque.  Please don't misunderstand; resque is a great library which abstracts away the details of asynchronous execution.  In case you weren't aware, its #enqueue method accepts a class name followed by an arbitrary number of (zero to many) arguments.

The fact that it does this should have no effect on the design of your classes.  Yes, you need to make a #perform method that then takes zero to many args, but again the design of your class should not be affected by this requirement.

For example, I've seen code where everything became a class method because of resque's requirements.

To get around this, you'll write an adapter layer which translates between resque and your code.  You don't have to be stuck with class methods.  Design your own code without Resque in mind, then hook it up at the last possible moment.

Another example is in Rails codebases:  how many times have you seen -- or even written yourself --

     some_model.update_attributes(foo: 'bar',  panda: 'bamboo')

when something like:


would make more sense?

You can hide the details of ActiveRecord's API behind domain-specific, intention-revealing method names that you choose.

What are your thoughts on the Dependency Inversion Principle, especially when writing Ruby?

The inspiration from this post came from several ideas: