Home > dotnet 4, SOLID > Loosely Coupled Architecture

Loosely Coupled Architecture

In this post I will give you another interesting perspective into designing loosely coupled architecture. Lets first see what does Wikipedia says about Loose Coupling ..

  In computing and systems design a loosely coupled system is one where each of its   components has, or makes use of, little or no knowledge of the definitions of other   separate components.  

In some of previous post I showed how dependencies between components/services can be decoupled by interface (contract) and it is the contract each component cares about.It does not care how it is implemented and who has implemented it. Then we introduce IoC/Dependency Injection which determines which component will be used when any part of the system calls that interface. To decouple we simply have the interface passed to the constructor of the class and this is called constructor injection and same way you can have method injection as well.

As usual I will start with a basic example and see how we go from there.So for example you are writing a batch job or some piece of code which execute some Update to the database using an Id. (I know this sounds quite vague but very soon you’ll see what I am getting into).

So let’s see how it appears to our mind :-

public interface IDbTask
{
    void Execute(int id);
}

As a good architect you should always anticipate change.The code works fine but in future I am anticipating that the criteria will become more complex and I have to factor that in because the business is evolving.

Let’s say the criteria is id plus something more like if the date is Tuesday and the first name is like this or that ..blah blah ..you got the picture. Keeping this in mind I would create the interface contract as this ..

public interface IDbTask
{
    void Execute(IActionParameter param);
}

and for the first iteration this is how my interface IActionParameter looks like.

public interface IActionParameter
{
    int id { get; set; }
}

see at this point I am just defining the contract no actual implementation. So now the BA comes and says we need to add the date parameter and since we are doing real Agile we have to adhere to the open close principle i.e. we should not change the IDbTask nor the IActionParameter

But with the open close principle this class or interface can be extended ( remember extensibility). So we will go ahead and extend it.

public interface IDateActionParameter : IActionParameter
{
    DateTime Date { get; set; }
}

and just for the sake of it and to see the bigger picture a class implementing the interface would look like

public class DateActionParameter : IDateActionParameter
{
    public int id { get; set; }

    public DateTime Date { get; set; }
}

Now since DateActionParameter still implements the base interface i.e. IActionParameter we can still pass it as is and we didn’t change the signature of the execute method.

I know you might be thinking that we still have to change inside the code to factor the 2 parameters in your decision-making. Well may be or may be not ;-). I mean if you really want it like that,then there are much complex and sophisticated patterns to implement and this is the first baby step.

The fundamental thing is there has not been any brut force signature change and you are not breaking anything. You are extending it, hopefully you will also see how IoC/DI plays a big part on designing such components.

Lets see this in another more real life scenario like the repository layer, business layer, web service layer etc.Suppose you are implementing a simple Customer business layer and for easy illustration I am just going to show CUD i.e. Create, Update, Delete( and Read will come later)

public interface ICustomerBL
{
    void Update(ICustomer entity);
    void Add(ICustomer entity);
    void Delete(ICustomerActionParameter param);
}
 

As you can see it’s pretty simple all the interface and it’s actual implementation like Customer and CustomerActionParameter will be injected by IoC/DI and we are keeping everything clean.

There is no tight coupling and it has full extensibility , anything can be chop and change on the fly and still everything works.

If I have to test the Add method with a  fake object all I have to is implement the ICustomer interface and create it’s fake implementation.

So you might be thinking if everything is so cool and easy then why am i holding onto the Read and if you haven’t figured it out then here is the big deal with it ..(drum roll)… the problem lies in its method signature ..

public interface ICustomerBL
{
    void Update(ICustomer entity);
    void Add(ICustomer entity);
    void Delete(ICustomerActionParameter parameter);
    ICustomerDO Get(IActionParameter parameter);
    List<ICustomerDO> GetAll(ICustomerActionParameter parameter);
}

At surface it all looks okay and the ICustomerDO is supposed to be a domain object which might have a different properties or behaviour as compare to your database entity “customer” (it’s always a good design pattern to not expose your database entity directly to business layer,service layer or UI layer).

Now the real problem lies how do I new up this object with out hard coding it ?

You might say Oh ! that’s easy like in the previous post we will just use the constructor injection …hmmm good thinking but isn’t our constructor already preoccupied by this :-

public class CustomerBLICustomerBL
{
    private readonly ICustomerRepository _repository;

    public CustomerBL(ICustomerRepository repository)
    {
        _repository = repository;
    }

    public void Update(ICustomer entity)
    {
        _repository.Update(entity);
        // just for illustration
        // same for add and delete
    }

    public void Add(ICustomer entity)
    {
        _repository.Add(entity);
    }

    public void Delete(ICustomerActionParameter parameters)
    {
        _repository.Delete(parameters);
    }

    public ICustomerDO Get(IActionParameter parameter)
    {
       
    }

    public List<ICustomerDO> GetAll(ICustomerActionParameter parameter)
    {
        //Call to the Repository and it return a list of
        //Customers from database but we need to map the
        // database customer to the Customer Domain
        //Object and hence we need to new up an object
    }
}

and you might also say well change the signature of Get and GetAll so that it takes the required interface and through our IoC/DI container we will inject the actual class. And you might implement it something like this

public ICustomerDO Get(IActionParameter parameter,ICustomerDO customerDO)
{
    //perform some logic of extraction
    // and mapping and then return the object
    return customerDO;
}

 


public List<ICustomerDO> GetAll(ICustomerActionParameter parameter,List<ICustomerDO> listCustomer)
{
    //Call to the Repository and it return a list of
    //Customers from database but we need to map the
    // database customer to the Customer Domain
    //Object and hence we need to new up an object
    return listCustomer;
}

Yes this approach will work but if we need to extend this we will have to change the method signature and what if it needs more than just 2 interfaces or the depending objects have their own dependencies on other objects.(Like Logging using ILogger interface etc).

It will be ugly to pass all the interface through methods and I rather not do that. So how do i solve this problem ?

This is where the factory pattern which I mentioned in my this post comes handy.

To implment this factory and the DI I am going to use the AppServiceFactory provided by David Hayden and the code of AppServiceFactory looks like this.

public sealed class AppServiceFactory
{
    private static readonly AppServiceFactory _instance = new AppServiceFactory();
    private IWindsorContainer _container;

    public static AppServiceFactory Instance
    {
        get { return _instance; }
    }

    public T Create<T>()
    {
        return (T)_container.Resolve<T>();
    }

    private AppServiceFactory()
    {
        ConfigureServiceContainer();
    }

    private void ConfigureServiceContainer()
    {
        _container = new WindsorContainer();
        _container.Register(
            AllTypes.FromThisAssembly().BasedOn<IWindsorInstaller>()
            );
        ServiceLocator.SetLocatorProvider(() =>
           new WindsorServiceLocator(_container));
        var installers =
            ServiceLocator.Current.GetAllInstances<IWindsorInstaller>();

        foreach (var installer in installers)
        {
            installer.Install(_container, null);
        }

    }
}

I have taken his pattern as is and improvise a little bit.I first tell IoC container(Castle Windsor) to look for all classes which implement the interface IWindsorInstaller and register all the installers with the windsor container then set Service Locator to current container and get all the instances of these classes.By the virtue of the fact that these classes implement the IWindsorInstaller interface (contract) I know they have the install method and I iterate through this installers and execute the install method.

And now I can use it just like the way I would use the normal windsor container i.e.


     ICustomerDO  customerDO = AppServiceFactory.Instance.Create<ICustomerDO>();

 

If you are finding some of this stuff quite different it;s perfectly alright.May be you haven’t come across these scenarios or may be you have,and you might have a different way of solving the problem.The important thing is that we are working for the same goal i.e. Loosely coupled architecture and not newing objects directly and there is always different ways to skin a cat important thing is the effort.

In my opinion in todays day and age you should not be hard-coding classes and should not new up objects directly,it’s the IoC/DI job and let it handle it (SRP).

Advertisements
  1. December 6, 2010 at 1:28 am

    Hi Prasantbhai,

    Good article. Haven’t worked with Windsor Castle before but will play with it soon and extend my post (http://www.nimeshdotnet.info/post/Dependency-Injection-using-Unity-Container.aspx) which uses Unity as DI container to use Windsor Castle.
    One thing I liked in this article is “(it’s always a good design pattern to not expose your database entity directly to business layer,service layer or UI layer)”

    We always know what is the best practice (do TDD, domain objects should be seperated. bla bla bla), but sometimes we have to compromise on things due to time constraints and crazy GM’s in small companies (not always the case though)

    Overall, loved your article.

    Thanks,

    Nimesh

    • December 8, 2010 at 3:00 am

      Hi Nimesh,
      Thanks for your encouragement. Yes I understand what you mean by time constraints and crazy GM’s, we all have been there and done that. But I think in retrospect there are two things more important and they are.

      • 1) The Ninja in you. ( The Ninja developer/architect in your )
      • 2) Lesson learned.

      I mean I have learned a lot just admitting to it and accepting it and not to repeat it again.I think it will be interesting to read each others post and learned from there. May be we should exchange crazy ideas/patterns over email or something :).

      I always like mind bogling ideas and new challanges although whether I can implement it or not but it’s always good to learn.

      Regards

      Prashant Brall

      • December 10, 2010 at 6:46 am

        Hello, yup. I regularly visit your blog to learn new things. Still after 3.5 years of experience in commercial field, I feel I have just started. Want to learn more and more everyday and your blog def helps in that. My email address is nim_patel2001@yahoo.com and just drop an email and will keep in touch for sure.

        Now on to reading Adapter Pattern 🙂

        Cheers,

        Nimesh

  1. July 19, 2011 at 9:10 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: