RUBY

How to Delegate Like a Boss


Great bosses understand the art of delegation. They know what needs to be done and who the best person for the job is. They create an environment where everyone thrives and are happy with their job.

Delegation can also be applied when building software. In fact, we can use delegation to adhere to 2 of the fundamental SOLID principles of object oriented design;Single Responsibility Principle(SRP) and Open/Closed Principle. To know more about solid principles, check out this link.

god objects are the direct opposite of the Boss who is good at delegation. These so-called god objects, can do everything (omnipotent), know everything (omniscient), and are everywhere in the application (omnipresent).

More often than not, we hear fat models, skinny controllers as one design patterns that you can follow to build robust applications. These kind of patterns encourage the creation of god objects and are bad advice. Instead of creating fat models, your models should delegate like a Boss. Basically don't create gods,  create bosses that understand the art of delegation.

Use Cases

We have a company that trains people to become world class developers. The director ensures that new intakes attain a minimum skill level after 6 months. Fortunately the director understands the art of delegation.

How can the director delegate the task of training new intake. Let’s find out.

1. By Inheritance

In this case the director will inherit the training team and delegate all training task to them.

2. Method Missing

Another approach that can be used to delegate task is method_missing. In ruby, when a method is called on an object and that method do not exist, method_missing method is called as a last resort. We can hook into this method and delegate task to other object this way.

In our example let’s assume the director want’s to delegate all task(method) that begins with train to the training team. How will the director delegate using method_missing.

In this example, train_new_intake method do not exist in Director class so method_missing method is called and TrainingTeam object subsequently handled the request.

3. Delegate Using Forwardable

The Boss(Director) can delegate tasks to other object using  Forwardable. This  module provides delegation of specified methods to a designated object, using the methods def_delegator and def_delegators.

def_delegator(obj, method, alias = method)  accepts 3 argument; first is the object we are delegating tasks to, second is the actual task(method) you want done, third is an alias we can use to invoke the task(method) from the Boss(in this case Director Class).

def_delegators(obj, *methods) is used to delegate multiple tasks(methods) to a single object.

4. Explicitly

Let’s assume intakes can take different paths. Eg intakes can be trained in Ruby, Python, Javascript, PHP, Java, etc. It becomes difficult to delegate via inheritance since the training team class will be doing too much. Good bosses do not overwork their employees. Let’s see how a good Boss will delegate in this case.

The Boss(Director) have different training team that handle specific training track. Once the director is told to train a new intake, he ask for the track the new intake will be trained on. He then delegates the job of training the new intake to the respective training team. The director has no idea how the actual training is done in each specific track. All the director knows how to do is to delegate the actual task to different team.

By delegating responsibility in this instance, the director is more focused on performing a single function (see: Single Responsibility Principle), thereby reducing the amount of work it needs to do.

5. Roll out your own strategy

Let’s roll out our own strategy for delegation. The strategy we will be rolling out is similar to the one used in  ActiveSupport(and every Rails project includes it).

We can use this strategy in our Director class like this.

Delegating this way makes our code very readable. We are basically saying; delegate all this tasks to this object.

How does Decorators come in

A decorator is a design pattern. It’s intent, as described in Design Patterns by the Gang of Four is:

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Using Gang of Four terms, a decorator is an object that encloses a component object. It also:

  • conforms to interface of component so its presence is transparent to clients.
  • forwards (delegates) requests to the component.
  • performs additional actions before or after forwarding.

From this we could say that we have been decorating Director class with more functionalities by delegating those functionalities to other objects.

Summary

As we already know, Ruby is a powerful language, sometimes even too powerful, which means that it provides many, very similar ways for doing the same thing. We have outlined 5 ways you can delegate. There are other approaches you could take when delegating tasks to other objects apart from the ones outlined in this blog post.

Who is feeling like this guy?. In his mind, he wants to delegate all tasks to others. :smile:

Ikem Okonkwo

About Ikem Okonkwo

Ruby Evangelist, .NET Advocate. Trainer at @andela. Passionate about education and lifelong learning. Loves good food and soccer.