Monday, September 8, 2008

Dependency Containers and Design by Contract

Design by contract used to bring an idea of complexity to me before I could really understand the idea and get my hands dirty on it.

The main idea I try to follow is that major system components should be represented by what they do and not by what they are. Let’s pick up a simple idea, a collection. A collection is something that is able to return an enumerator to transverse its elements, it can add an element to it and it can return how many elements it is holding. These are some of the things a collection is able to do.

A collection can be a list, it can be a tree, it can be a stack, as long as it can behave as a collection it is a collection. If you search for Duck Typing you will get a lot of funny stories about this idea.

When possible we should encourage replacing concrete objects by their abstractions because the code written against abstractions obviously promotes more reusability.

In most cases designing by contract is writing the interface first and implementing the classes that realize then after. This was what I did on this really dummy invoicing system:

#region contracts

   /// <summary>
   /// Manages aspects related with user authorization.
   /// </summary>
   public interface IAuthorizationManager
   {
       bool Authenticate(string user, string password);
   }

   /// <summary>
   /// Traces who did what, when.
   /// </summary>
   public interface IAuditingManager
   {
       bool WriteAuditInformation(string operation, string who, DateTime when, object what);
   }

   /// <summary>
   /// Manages invoicing operations.
   /// </summary>
   public interface IInvoicingManager
   {
       void CreateInvoice(string salesPerson, string customerCode, string[] products, decimal[] unitPrices, decimal[] quantities);
   }

#endregion
Then I created a concrete class that uses this components ( I could have been a purist and write a contract for it :) ):
public class SalesSystem
{
   public IAuditingManager AuditingSystem
   {
       get;
       private set;
   }

   public IAuthorizationManager AuthorizationSystem
   {
       get;
       private set;
   }

   public IInvoicingManager InvoicingSystem
   {
       get;
       private set;
   }

   public SalesSystem(IAuditingManager auditingSystem, IAuthorizationManager authorizationSystem, IInvoicingManager invocingSystem)
   {
       this.AuditingSystem = auditingSystem;
       this.AuthorizationSystem = authorizationSystem;
       this.InvoicingSystem = invocingSystem;
   }
}
Note how I pass in all the objects in the constructor. It is good to read my post on the "Law of Demeter”.
These are my really dummy realizations of these classes (do note the really bullet proof the security code :)!)
#region really dummy realizations

internal class MyAuthorizationManager : IAuthorizationManager
{
    #region IAuthorizationManager Members

    public bool Authenticate(string user, string password)
    {
        if (string.Compare(user, "user1", StringComparison.OrdinalIgnoreCase)==0)
        {
            if (string.Compare(password, "123", StringComparison.Ordinal) == 0)
            {
                return true;
            }
        }

        return false;
    }

    #endregion
}

internal class MyAuditingManager : IAuditingManager
{
    #region IAuditingManager Members

    public bool WriteAuditInformation(string operation, string who,DateTime when, object what)
    {
        Console.WriteLine("{0} by {1} at {2} over {3}", operation, who, when, what.ToString());
        return true;
    }

    #endregion
}

internal class MyInvoicingManager : IInvoicingManager
{
    public MyInvoicingManager(IAuditingManager auditing)
    {
        this.Auditing = auditing;
    }

    public IAuditingManager Auditing
    {
        get;
        private set;
    }

    #region IInvoicingManager Members

    public void CreateInvoice(string salesPerson, string customerCode, string[] products, decimal[] unitPrices, decimal[] quantities)
    {
        Console.WriteLine("Invoice created for {0}", customerCode);
        this.Auditing.WriteAuditInformation("CreateInvoice", salesPerson, DateTime.Now, "Invoice");
    }

    #endregion
}

#endregion
Now comes the time to introduce the idea of a dependency container. It is really a component to help lazy guys like me. I don’t want to write code to create an authorization manager, a audit manager and an invoicing manager just to create my sales system. I still have to work for the next 30 years and I need to save my fingers.

Without the jokes what I don’t want to do is call the constructors on those components because as the system evolves they will change, when they change things will get broken and I will be in trouble. What I want is a system that is really smart and does all those boring news by me. This system is Unity.

Unity is a dependency container and it can resolve dependencies by me. It I tell him what classes realize my contracts we can the create instances of other classes that required these contracts to be built:

class Program
{
    static void Main(string[] args)
    {
        UnityContainer unityContainer = new UnityContainer();

        unityContainer.RegisterType(typeof(IAuditingManager), typeof(MyAuditingManager));
        unityContainer.RegisterType(typeof(IAuthorizationManager), typeof(MyAuthorizationManager));
        unityContainer.RegisterType(typeof(IInvoicingManager), typeof(MyInvoicingManager));

        SalesSystem system = unityContainer.Resolve<SalesSystem>();

        if (system.AuthorizationSystem.Authenticate("User1", "123"))
        {
            system.InvoicingSystem.CreateInvoice("User1", "Customer1", new string[] { "Product1" }, new decimal[] { 10.0M }, new decimal[] { 1.2M });
        }

    }
}
Try to write the code to replace these by Mock objects :). If you are a fan of TDD you will love this.

No comments: