Instantiating behaviour

In last weeks post we had a quick look at a little hack called digg.

some_complex_json_rsponse.digg('preview', 'thumbnail', 0, 'id')

In order for this to work we need to extend each class we want to digg with the digg method. This leads to modifying core classes; and we should frown upon that. 😠

So what else can we do?

module Digg
  def self.digg(soil, path)
    # …

Digg.digg(some_complex_json_rsponse, ['preview', 'thumbnail', 0, 'id'])

That would work. I bet this will very quickly lead to a “Util” class that become a bag of tricks. 👜✨ We don’t want that.

So how about adding some instantiation?

class Digg
  def initialize(soil)
    @soil = soil

  def digg(path)
    # …

digger =
digger.digg(['preview', 'thumbnail', 0, 'id'])

Alright! Now we can digg for multiple paths on the same set of data. 😎

But… This doesn’t feel right either. 😧 The act of digging is defined by what steps are taken. (e.g.: Pick up spade, stab in ground, lift, dump, repeat). It is not defined by the soil that we digg in. { |json|['preview', 'thumbnail', 0, 'id'])['preview', 'name'])

See! That just doesn’t look good.

What if we turn that around?

class Digg
  def initialize(path)
    @path = path

  def digg(soil)
    # …

digger =['preview', 'thumbnail', 0, 'id'])

Now we define “how to digg” when initializing. See how much better this looks for loops:

thumbnail_digger =['preview', 'thumbnail', 0, 'id'])
name_digger =['preview', 'name']) { |json|

Finally! 😌

This way of thinking about your objects, by defining behaviour on initializing, has a lot of benefits.

Not only is it faster (in this case) (gist), but also more intention revealing. 📖

By instantiating behaviour you can start to compose your objects with more ease, or start thinking about caching or optimising the behaviour.

Let me know what you think. And if you apply this in your code I’d be happy to have a look at it.