How to Delegate Like a Boss
Great bosses understand the art of delegation. They know what needs to be done and the best person for the job. 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.
There is a company(Andela) that trains fellows to become world class developers. The Director(Nadayar Enegesi) ensures that new fellows attain a junior developer skill level within 6 months. Fortunately the Director understands the art of delegation.
How can the Director delegate the task of training new fellows. 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 the task of training to other object in this way.
In our example let’s assume the Director want’s to delegate all tasks that begins with train to the training team. Let’s find out how the Director will delegate using method_missing.
In this example, train_new_fellow method do not exist in Director class so method_missing method is called and TrainingTeam object subsequently handles the request.
3. Delegate Using Forwardable
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.
The Director have different training team that handle specific training track. Once the Director is told to train a new fellow, he ask for the track the new fellow will be trained in. He then delegates the job of training the new fellow to the respective training team. The Director does not need to know how the actual training is done in each specific track. The Director just delegate the task of training to the different training team and trust them to do a good job.
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. Also notice that the Director is adhering to open/closed principle. Here if a new stack is introduced eg Golang, the Director class won’t change(closed to modification). Instead, a new training team called GolangTrainingTeam will be created(open to extension).
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.
What about Decorators?
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.
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. So, choose the strategy that works for you.
I want to believe that at this point, you are feeling like this guy. In his mind, he wants to delegate all tasks to others.