Blog Archives

Focusing on the controller’s responsibility

This morning I came across an interesting article about Controller responsibility: http://mhinze.com/focusing-on-the-controllers-responsibility/

This is the excerpt:

A heavyweight controller

public RedirectToRouteResult Ship(int orderId)
{
   User user = _userSession.GetCurrentUser();
   Order order = _repository.GetById(orderId);

   if (order.IsAuthorized)
   {
      ShippingStatus status = _shippingService.Ship(order);

      if (!string.IsNullOrEmpty(user.EmailAddress))
      {
         Message message = _messageBuilder
            .BuildShippedMessage(order, user);

         _emailSender.Send(message);
      }

      if (status.Successful)
      {
         return RedirectToAction("Shipped", "Order", new {orderId});
      }
   }
   return RedirectToAction("NotShipped", "Order", new {orderId});
}

According to the author, that controller does a lot of things, so he suggests a refactoring techniques called “Refactor Architecture by Tiers. It directs the software designer to move processing logic out of the presentation tier into the business tier.”

Here is how the controller is refactored by moving the logic for shipping an order to an OrderShippingService, our action is much simpler.

A simpler action after refactoring architecture by tiers
public RedirectToRouteResult Ship(int orderId)
{
   var status = _orderShippingService.Ship(orderId);
   if (status.Successful)
   {
      return RedirectToAction("Shipped", "Order", new {orderId});
   }
   return RedirectToAction("NotShipped", "Order", new {orderId});
}

I must admit that I have implemented that so-called _heavyweight_ controller when developing website using ASP.NET MVC and I rather call it a ‘fat’ controller which violates Single Responsibility Principal since it does a lot of things. My solution is somewhat familiar with the author: moved the logic to Service or Business layer. This will keep the controller ‘thin’ and concentrates on its responsibility: a coordinator between View and Model which intercepts user request, asking  business layer to perform business logic, pull data from Model and choose a right View to return to client.

And it takes time, even blood, to absorb.