Wednesday, March 18, 2009

On inverting control

The term inversion of control is one that gets bandied around quite easily these days. Unfortunately most people react to the term with blank stares. In the hopes of preparing my explanation for the next time, here is my reflection on IoC. Consider the simple example:
class CustomerInfo {
}

interface NotificationService {
 void sendNotification(CustomerInfo info);
}
this separation is logical because the sending of customer info is not necessarily bound to the sending of some notice. It does however have a few problems: for one it forces each implementation of the notification service to know the details of the customer info. We can however consider some inversion on this:
class CustomerInfo {
 void sendTo(NotificationService notificationService);
}

interface NotificationService {
 void sendNotification(String message);
}
this would result in a send command that looks like this:
customerInfo.sendTo(notificationService);
which reads fairly well. This inversion has helped us to simplify the notification service, and allowed us to re-encapsulate the customer info. Now what happens if the notice has a complicated, transport-specific format? We can make the abstraction more transparent flexible:
interface NotificationService {
 NotificationMessage createMessage();
 void sendNotification(NotificationMessage message);
}

interface NotificationMessage {
 void setSubmiter(String submiter);
 void setSubject(String subject);
 void setMessage(String message);
}

class CustomerInfo {
 void sendTo(NotificationService notificationService) {
  NotificationMessage message = notificationService.createMessage();
  ...
  notificationService.sendNotification(message);
 }
}
Now this approach could allow us to implement an email-based notification or an instant-messaging-based notification service. The code is cleaner and safer, all without coupling the service to the source of the message. Not bad.

No comments: