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 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 :-
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 ..
and for the first iteration this is how my interface IActionParameter looks like.
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.
and just for the sake of it and to see the bigger picture a class implementing the interface would look like
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)
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 ..
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 :-
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
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.
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.
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).