Part-2 is Available At the Below Link
I am publishing this article in parts and have just submitted part -2 of it. Part-2 contains Liskov Substitution Principle. You may visit Part-2 of this series at:
I got several opportunities to work in highly available, scalable enterprise application. Some of them were using legacy technology stack & some as new, but most of them had a serious problem of High Coupling and Low Cohesion.
Developers understand the theoretical concept of these keywords, but when it comes to applying them in the real world, they struggle with these OO principles.
I would like to highlight the benefit of applying SOLID design principles to achieve Low Coupling and High Cohesion.
It is good to have an understanding of Object oriented principle along with basic knowledge of Coupling and Cohesion.
Why is Low Coupling & High Cohesion Required in the Enterprise World?
Larry Constantine invented the metrics of coupling and cohesion in 1960s as part of Structured Design, based on characteristics of good programming practices that reduced maintenance and modification costs.
Low Coupling & High Cohesion are the building blocks for a successful & maintainable enterprise applications. And working on these applications, you would like to maintain the Separation Of Concern (SOC). If you design different modules, processes, sub systems or inter-related / inter-dependent systems, then applying SOC with Low Coupling & High Cohesion helps us achieve this objective.
Coupling in its very simple form is the degree to which one class is connected to another class. If class is highly coupled, then you are bound to use /edit rest of the connected classes where only editing one class could have served the purpose.
Example of High coupling is shown in the below image where one or more classes are dependent on quite a few other classes.
Low coupling can be achieved by having less classes linking to one another. The best way to reduce coupling is by providing an API (interface). OOP languages like C#, Java, C++ offer quite a few mechanisms to offer low coupling like
public methods, interfaces and other interaction points between different classes and modules.
One last bit on low coupling / zero coupling is: Zero coupled classes are not very usable and very low coupled applications are very difficult to maintain. So striking a balance is definitely an art.
Cohesion is collaboration. Cohesion is how a colleague in a team behaves and works to achieve the business objective / solve a problem statement.
Cohesion in computer science would be how two or more systems work together to make a more valuable application or solution.
At a high level, you would like to consider 2 or more systems to handshake their information to create a more valuable system.
Example: In an Investment bank, pricing a Foreign Exchange derivative product requires an input & with 3 other systems like Market data Service, Trade service and Quants system. This is a very complex process as output from Quants could very well be accepted as an input to Market data service for further calculations, thus eventually valuating a Foreign Exchange derivative (as in the below image).
Another design level example of High cohesion would be of N-Tier architecture. You would want a user interface technology that makes it easy to wire up the business logic and data access layer. Cohesion is all around. You only need to recognize it for what it is.
Whilst designing software developers talk about high-level concerns and low-level implementation details, you can easily understand the cohesion by how well the lines of code in a method or function work together to create a sense of purpose? How well do the methods and properties of a class work together to define a class and its purpose? How well do the classes fit together to create modules? How well do the modules work together to create the larger architecture of the system? Understanding this perspective will help you understand the extent to which the pieces are cohesive or not.
One last point (just like Zero Coupling) -- do not put all the responsibility of a module in a single class, to avoid low cohesion.
How "SOLID" Helps Achieve Low Coupling and High Cohesion
SOLID are five design principles. Author of these principles is Robert C. Martin in 1990s.
SOLID stands for:
- Single Responsibility Principle [SRP]
- Open Closed Principle [OCP]
- Liskov Substitution Principle [LSP]
- Interface Segregation Principle [ISP]
- Dependency Inversion Principle [DIP]
Single Responsibility Principle [SRP]
Single Responsibility Principle [SRP] suggests that a class should have one, and only one reason to change. If an object has more than one reason to change, then it has more than one responsibility and is in violation of SRP. Reason to change is not the same as reason to exist. This sounds counter-intuitive at first but actually they are not.
If you build classes with only one reason to exist, then you 'may' end-up creating them with only one method and thus generating plethora of classes and in-turn complex design. This way, we could end-up in a maintenance nightmare.
Why Single Responsibility is Essential
Imagine you have a master key which is 'responsible' to open all the locks in your house, including your safe. Do you think it is wise to overload a key with so many responsibilities? What if your key is stolen? Now rather than replacing only one lock, you eventually end-up replacing all the locks.
So a overloaded responsibility could turn nightmarish.
Business Context is the driving force to coin Single Responsibility Principle. Business context will drive the segregation of responsibility in a class or module rather than logical segregation.
A very good example could be our Mobile phone. Do you care about the internal procedures of a mobile phone? Internally, a mobile phone could have a circuit board, ROM, a flash memory, RF amplifiers, a micro processor, a speaker, micro phone, LCD, etc.
Probably, you would not care about internal setup, if you are like a regular mobile user just like me and use mobile phone to communicate with my friends. But yes, if you are a mobile phone service engineer. So a single responsibility would depend upon the business context you are binding to. In the context of servicing, every individual part of mobile phone needs to be separate. You would need to code them as single classes and ensure they are all up to their individual specifications. In the context of a normal mobile user, the complete mobile phone is a single concept that does not need to be broken down any further.
How SRP Helps Achieve Low Coupling and High Cohesion
You would realize the whole point of SRP is to achieve Low Coupling and High Cohesion by exposing a very limited number of responsibilities. The class intersects with a segment of the system and as business requirements change, the chances of changing a class is even lower. Every class will encapsulate the smallest responsibility, but we would still require a placeholder for orchestration logic that the system would require.
Open-Closed Principle [OCP]
The Open-Closed Principle says that a class should be open for extension, but closed for modification. This principle in a nutshell means that a class should be open for extension with respect to behavior addition. Our goal should be to allow classes to extend (by incorporating new behavior) without the need for modifying existing code. By doing so, we make resilient designs that are flexible enough to take on new behaviors / functionality.
Decorator / Observer / Strategy and quite a few other patterns had always used OCP principle.
An example could easily be spotted when you visit a Nike shoe store.
Nike does not have a single shoe for Running, Trainers, BasketBall, Tennis & Football etc. (click here for shoe guide example). So Nike is not closed for modification and extending different shoe behaviors using 'Open for extension example'. These individual differences in shoes are what make each type of shoe unique. One shoe is very good in running and other could be gripping and balance while playing in wet field.
So how can we allow OCP? Simply by implementing an abstraction. So the above stated patterns facilitate the behavior change through the use of
abstract classes and interface.
This first image shows less coupling and less extensibility, whereas the second image demonstrates the extensibility by usage of
Abstract class or Interface (
IVehicle). As VS2013 does not gives me Show Base Interface option, I have created
abstract class for relationship linking.
I will continue with the rest of the 3 principles sometime next week... enjoy coding.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.