Ask for help, not for data

Sometime ago I received an email asking for confirmation about an event about to take place. Included in the email was a little snippet meant to make it fun and attractive to developers. As many of us read through it, it brought several opinions on the quality of the code. Here’s the thing:

if (employee.WantsToAttend()) {
	if (employee.IsWorkingFromOffice1())
	{         employee.reply(manager1, "I wanna be there");     }
	else if (employee.IsWorkingFromOffice2())
	{         employee.reply(manager2, "Dude! I wanna be there!");      }
}

I realize that this code is meant to express the idea of the invitation. But the sad thing is that you can find this kind of code on production software. Oh? what’s wrong with this code you said? well, let’s talk it out.

Tenets of OOP

We’ve all heard about the oop principles: encapsulation, polymorphism, inheritance and abstraction. Let’s evaluate the code in the context of these.

Encapsulation

Encapsulation states that you must hide the object internals in such a way that if you change them no dependent object should be afected.

Now consider this method calls:

employee.WantsToAttend()
employee.IsWorkingFromOffice1()
employee.reply(manager1, "I wanna be there");

These calls are all implementation details of the “confirm assistance” scenario. Truth is we only care the employee object to confirm it’s assistance. We could easily move the first evaluation into the object:

class Employee
{
   ...
   public void ConfirmAssistance(string manager, string msg)
   {
      if(wantsToAttend())
		reply(manager,msg);
   }
}

Now the client code would look a little more cleaner:

if (employee.IsWorkingFromOffice1())
	    employee.ConfirmAssistance(manager1, "I wanna be there");     
	else if (employee.IsWorkingFromOffice2())
	    employee.ConfirmAssistance(manager2, "Dude! I wanna be there!"); 

So far so good. We’re now hiding the data by making the decision inside the object. However there is a subtle but important implication: we shift the responsibility of validating wheter the customer wants to assist to an event from the client code to the object. From now on you don’t need to figure out if the employee wants to attend everytime you want to confirm his assistance. The object will do it itself.

Allen Holub calls this asking an object for help instead of data. This is a direct consequence of encapsulation and probably the most influential piece of advice in my transition from a data driven mindset to an OOP one.

Can we stop exposing the employee’s office? we can try:

class Employee
{
   ...
   public void ConfirmAssistance(Func<string,string> msgFactory)
   {
      if(wantsToAttend())
		reply(Office.Manager,msgFactory(Office.Id));
   }
}

And so we have a one liner now:

employee.ConfirmAssistance(officeId => officeId == 1?"I wanna be there": "Dude! I wanna be there!");

If you’re confused by the weird syntax it’s just an inline/anonymous function created using a syntax called lambda expressions (the examples are all C#).

Compared to the previous version which one looks more reusable to you?

A few comments here:

1) now we have a msg for office1 and another for the rest (not only office2)

2) we really don’t care how the manager and office id are stored, we can easily change that to private fields and it would not make a difference to the calling code.

Cleaning up the responsibilities

The reply method implies a third party service. Storing a reference to the service it’s overkill. You have to instantiate that service with the rest of the object graph every time you initialize an employee object. Let’s break this down in 2 parts: the reply message creation and the actual sending of that message.

class MessageGateway
{
    Send(Message msg){...}
}

class Message 
{
   public Message(string recipient, string body)
   {
      Recipient = recipient;
      Body = body;      
   }

   public string Recipient {get;set;}
   public string Body {get;set;}
}

class Employee
{
   ...
   public Message ConfirmAssistance(Func<string,string> msgFactory)
   {
      if(wantsToAttend())
		return new Message(Office.Manager,msgFactory(Office.Id));
	  else
	    return null;
   }
}

The client code:

Message reply = employee.ConfirmAssistance(officeId => officeId == 1?"I wanna be there": "Dude! I wanna be there!");    

if(reply != null) new MessageGateway().Send(reply);

We now delegate the reply message creation to the employee object and the sending of it to the message gateway object. Splitting responsibilities like this allows us for better reusing and comply with the Single Responsibility Principle.

But… we’re breaking encapsulation on the Message class.

Let’s fix that.

class MessageGateway
{
    Send(string recipient, string body){...}
}

class Message 
{
   public Message(string recipient, string body)
   {
      Recipient = recipient;
      Body = body;      
   }

    string Recipient;
    string Body;
    
    public SendThrough(MessageGateway gateway)
    {
       gateway.Send(Recipient,Body);
    }
}

class Employee
{
   ...
   public Message ConfirmAssistance(Func<string,string> msgFactory)
   {
      if(wantsToAttend())
		return new Message(Office.Manager,msgFactory(Office.Id));
	  else
	    return null;
   }
}

and the client code looks like:

Message reply = employee.ConfirmAssistance(officeId => officeId == 1?"I wanna be there": "Dude! I wanna be there!");    

if(reply != null) reply.SendThrough(new MessageGateway());

“What?? all the fuzzle for this? just inverting the way we send the data?” Well yeah, but that’s not all. Do you see that null check there? we can now get rid of it.

Polymorphism

There’s this concept that states that the more execution paths are on a program the harder is to maintain. This is called cyclomatic complexity and is a common indicator of code quality. Bottom line is the less “if” and “switch” statements the better.

Our initial approach removed all of the branching statements from the program. But later we introduced a new one with the null check. Let’s remove it. A common OOP technique it’s the null object pattern. It relies on the polymorphism attribute of OOP. Let’s see how it goes.

1) extract a common interface

interface IMessage
{
   SendThrough(MessageGateway gateway);
}

2) create an object that does nothing (as you would if you received a null)

class Message: IMessage
{
   public Message(string recipient, string body)
   {
      Recipient = recipient;
      Body = body;      
   }

    string Recipient;
    string Body;
    
    public SendThrough(MessageGateway gateway)
    {
       gateway.Send(Recipient,Body);
    }

   //usually the null object it's used in a singleton fashion
   class NullMessage: IMessage
   {
	   public SendThrough(MessageGateway gateway) 
	    {
	       //Do nothing 🙂
	    }
    }

   public static IMessage Null{get;private set;}

   public static Message()
   {
      Null = new NullMessage();
   }
  
}

3) return the null object instead of null

class Employee
{
   ...
   public Message ConfirmAssistance(Func<string,string> msgFactory)
   {
      if(wantsToAttend())
		return new Message(Office.Manager,msgFactory(Office.Id));
	  else
	    return Message.Null;
   }
}

Presto! now let’s update the client code

Message reply = employee.ConfirmAssistance(officeId => officeId == 1?"I wanna be there": "Dude! I wanna be there!");    

reply.SendThrough(new MessageGateway());

look ma! in one line (again)!

employee
	.ConfirmAssistance(officeId => 
	   officeId == 1? "I wanna be there": "Dude! I wanna be there!")   
	.SendThrough(new MessageGateway());

Polymorphism allows us to change a system behavior without changing the code. This is done by creating variations of the same method and swapping them as needed.

If not OOP, then what is it?

Let’s review:

object – data (state)= module (remember vb6?)

object – methods (behavior) = struct (yes, this was already available in C)

You can easily write a program using modules and structs and that’s fine for a lot of situations (forms over data ;))

In conclusion

1) Encapsulation enables Polymorphism

2) Polymorphism enables the use of design patterns and other OOP goodies

OOP shines on making flexible code but it has a price: indirection. If your project is relatively simple (like the example used here) you may want to ponder if there’s a simpler way, like structured programming (modules + structs). But if you still decide on this route, just remember that objects do things. Ask for help, not data!

Extra: a functional twist

Closures can simplify this code a lot. Since they were already present in smalltalk I consider them part of the OOP toolset. Here’s the whole enchilada:

class MessageGateway
{
    Send(string recipient, string body){...}
}

class Employee
{
   ...
   public Message ConfirmAssistance(Action<string,string> confirm)
   {
      if(wantsToAttend())
		confirm(Office.Manager,Office.Id);  
   }
} 

//client code

employee.ConfirmAssistance((manager,officeId)=> {
   var response = officeId == 1? "I wanna be there": "Dude! I wanna be there!";
   new MessageGateway().Send(manager, response);
});