Friday, June 27, 2008

Writing Testable Code - Part I

In the current project that I am working on we decided that we will strive to write as many unit tests as possible. Here I will try to share some lessons learned from this experience.

The application was broken down to following layers, A DAL that communicates with the underlying database, a service layer that implements business rules and the UI layer.

We started with writing the DAL and some services. Since our services didn't have any state we decided to go with static classes. A typical service class might look like this.

public static class OrderService
{
public static void ProcessOrder(int orderId)
{
OrderHeaderDAL headerDAL = new OrderHeaderDAL();
OrderDetailDAL detailDAL = new OrderDetailDAL();
CustomerDAL customerDAL = new CustomerDAL();

//Do the processing.

}
}


We managed to write unit tests for the DAL without any issues. But as soon as we wanted to write unit it was apparent that we cannot do this because the service classes are directly coupled to the DAL. Clearly we needed to decouple the Services from the DAL and the first solution that came to my mind was dependency injection. To do this we needed to make the following changes




  • Make the service class methods instance based rather than static


  • Define a set of interfaces that will decouple the DAL from services


  • Add a factory class that will assemble the service classes


service classes instance based rather than static and add a layer of DAL interfaces that the services will depend on instead of the concrete classes . Now the above example will look like this.



public class OrderService
{
public IOrderHeaderDAL OrderHeaderDal
{
get;
set;
}

public IOrderDetailDAL OrderDetailDal
{
get;
set;
}

public ICustomerDAL CustomerDal
{
get;
set;
}

public void ProcessOrder(int orderId)
{

//use the injected DAL's
CustomerDal.DoWhatEver();
}

//Whenver you want to use the order service you call the ServiceFactory
OrderService service = ServiceFactory.CreateOrderService();


This solution worked. now we can mock the DAL and write unit tests for the service classes easily. But this had the following issues. Some methods in a service don't use all the DAL classes that the service depends on. But when the service factory creates the service it injects all dependant objects regardless of weather they are used or not. In the next post I will describe how I fixed those issues.

Thursday, June 05, 2008

SysInternals tools available on a Internet file share

All SysInternals tools can be now run from \\live.sysinternals.com\tools. This is very handy when you are troubleshooting productions servers and don't want to download everything on to the server.