Introduction
The world is changing fast. Immense market pressure and cut-throat competition has changed the idiom from “build to last” to “build to change”. This and development methodologies like Agile stress software system to be more flexible more resilient. Apart from other design and development principles “Loose Coupling” plays a lead role in flexibility. In simple term loose coupling can be defined as –
In the system of dependent unit, if we change any unit the other units are (ideally) unaffected, in other words change in one unit do not have any impact on another unit.
Software systems are built as collaborating components, which intern are set of collaborating cohesive classes, collaborating and communicating layers, communication with data sources and external sources. This requires loose coupling to be applied at different levels:
· architectural style
· design and classes
· Interaction with databases
Loosely coupled systems are easier to maintain and extensible.
This paper explains the technology and techniques that can be applied at these different levels for loosely coupled software system. The paper should be looked as source of pointers to achieve loose coupling. Details description of any technique is out of scope of the paper.
Architectural Style
Selecting appropriate architectural style, among client/server architecture, layered/N-Tier architecture, component-based architecture, message/service bus architecture and service oriented architecture (SOA), or combining different architectural styles plays significant role in loosely coupled software system. These styles can be grouped as follows:
|
Degree of coupling |
Architectural style |
|
Low degree of coupling |
Layered/N-Tier architecture Message Bus architecture Service Oriented architecture Domain Driven Design |
|
High degree of coupling |
Client/Server architecture Component-based architecture |
The above grouping should be looked as just pointers and even lower degree of coupling can be achieved when different architectural styles are mixed. In SOA style services implemented with N-Tier style adds up low coupling benefits of both the styles. Client/server architectural style’s coupling – where traditionally server logic is written in database stored procedures - can further be loosen by dividing the logic in self contained well interfaced components.
Many factors will influence the architectural style or combination of architectural style one choose. You will have to strike a balance between loose coupling and other design principles. For example loosely coupled N-Tier architecture with each tier deployed on separate box will have more demand for security measures than less loosely coupled client/server architecture which generally offers a great control on security.
Design and Class
Separating interface from implementation provides better control on coupling. Consider the example below which shows loose coupling between depending class and set of concrete classes. The DependentClass does not have any knowledge of concrete implementation of interface IInterface. One can add new implementation of IInterface, say InterfaceImpl4, without informing anything about this new interface to DependentClass, which provides a great degree of flexibility. Even if you have one to one mapping between dependent class and dependency, I recommend programming dependent class against interface of dependency, as shown in figure B.
One has to ensure that interfaces are well articulated, well defined and fairly stable.
In above arrangement, still there exists a small amount of coupling if DependentClass creates an instance of InterfaceImpl1 like IInterface inf = new InterfaceImpl1().This can further be eliminated by linking classes at runtime – through configuration – rather than compile time. Following design patterns helps to achieve loose coupling:
· Factory/Named-factory/Abstract Factory pattern
· Plug-in pattern
· Dependency injection pattern
· Bridge pattern
· Service locator pattern etc.
Reflection APIs can take the coupling to lowest level. Many languages like C#, Java provides built-in reflection APIs. Third party libraries like XCppRefl can be used for reflection in C++. Microsoft Enterprise Library Unity block, NInject and Sprint.Net are few dependency injection frameworks available. The new initiative from Microsoft, Managed Extensibility Framework (MEF) – still in development – also provides Dependency Injection.
In Figure B even if DepedentClass is programmed against IInterface, but chatty communication, it increases the coupling between dependent class and dependency. Sometime chatty communication results in exposing greater details about dependency. It mud-slides dependent class code with dependency behavior. Try to reduce number of calls between classes.
Improper identification of classes also has adverse impact on coupling. They lead to increased number of dependencies and cress-cross communication between units. Consider reorganizing class responsibilities and communication between them.
Wherever possible, prefer composition over inheritance. Inheritance imposes very tight coupling between parent and child classes, thereby limiting the reuse of child classes.
Avoid deep dotting. Deep dotting exposes dependencies to other classes. Consider figure below. ClassA is dependent on ClassB which in turn is dependent on ClassC. It is better to delegate method call from ClassA to ClassC through ClassB to avoid calls like objClassB.GetClassC().DoSomething().This minimizes the impact of any change in ClassC which requires dependent classes to be changed.
In case of layered/N-Tier architecture, use abstraction between layers for loose coupling. This can be achieved with the help of façade pattern with well known input and output.
A simple magic wand to test loose coupling
Take a class from your business layer, and just copy its code into a new console project. Try to compile it. You’ll likely be told about missing some dependencies. Copy those classes to the console project and try again. You’ll likely discover other missing classes. When you are finally able to compile, you may find that you have quite a significant fraction of your codebase in the new project. If this is so, your design needs to be re-investigated.
Persistence Ignorance
Persistence Ignorance is development technique to design and build business logic independent of the database. It is mostly used in domain-centric design like DDD or TDD. Frameworks/utilities like Entity Framework with LINQ, from Microsoft and NHibernate with HQL provides fair amount of independency from database.
Wrapping it up
There are various design techniques, principles, design patterns, frameworks, utilities etc. to develop loosely coupled software systems. All of these provide loose coupling by adding a layer of indirection or abstraction.
Achieving loose coupling definitely needs extra development time in initial phases of application – which is scarcity in current “wanted it yesterday” scenario. One has to negotiate with stakeholders and present the case on how it pays off in long term.
One has to judge the degree of coupling wisely. When loose coupling is abused or misapplied or not though thru, you have unneeded indirection and abstractions, requiring extra setup, inefficiency, extra complexity, translations between concepts and performance hit. Many factors will influence the options you choose like capabilities and experience of developers, infrastructural and organizational constraints, capacity to handle indirections and abstraction etc.
Popularity: 55% [?]



June 26th, 2011 at 3:29 pm
Thank for article. The post is very useful for me. I understand design patter.