Most of the software developers know the theoretical definitions of coupling, cohesion, and encapsulation. But unfortunately, many of us don’t understand the benefit of low coupling, high cohesion, and strong encapsulation. But if we can maintain these three properties & develop a software, it will be easier to read, easier to understand and easier to change.
The Object-Oriented Principle
Ideally, we want to ensure that our systems have low coupling and high cohesion. These two principles help us to create the building blocks of a software system. We would like to have a self-contained building block too, which are encapsulated. It is obvious that we would not want blocks to be leaking into other blocks.
Coupling is used to describe the relationship between components. Coupling is the extent to which a component of the software depends on other components. For example, the degree of coupling between two classes can be seen as how dependent one class is on the other.
Suppose there are three classes of car, boat, a train which are dependent on the class engine. Now a modification in the engine class will necessitate changes in the car, boat and train class. And if any of those classes are tightly coupled to other classes then those classes will have to be changed also, and so on and so forth.
Now let’s imagine a class which has zero coupling. That is the class is not dependent on any class and vice versa. But what is the benefit of it? The class is a useless one. Coupling is not always deleterious. So we need to attain the correct level of coupling while creating a system that is functional, understandable and maintainable.
Cohesion is used to describe a single software component. When a component has only one responsibility, and therefore only one reason to change, it has high cohesion. When a component has many responsibilities it has low cohesion.
Components with high cohesion are more robust. For example, if the engine class is responsible for both the acceleration & deceleration, then a change in acceleration implementation could affect the deceleration implementation. However, this problem can be solved if the engine class is only responsible for the acceleration & another class named brake is responsible for the deceleration. So if there is any change in the deceleration implementation it will not affect the functionality of the engine class.
Most developers define encapsulation as information hiding. However, this definition often leads to an incomplete understanding and implementation of encapsulation and misses out a tremendous opportunity that encapsulation provides: to hide not just data, but process and logic as well.
It is common to use a process in more than one location. Proper encapsulation combined with low coupling will help to ensure a system with high cohesion. For example, we have a circular saw to cut a piece of wood. But it is obvious that we will not be bothered about the mechanism of the motor. We will only care that when the trigger is pulled, the blade spins at a rapid rate & allows us to cut the wood easily. The saw has encapsulated the process of causing the blade to turn through a simple, public interface to handle with the trigger.
S.O.L.I.D to the Rescue
When it comes to the question of maintaining the OO principles SOLID comes to the rescue for the developers. It stands for,
S: Single Responsibility Principle (SRP)
O: Open-Closed Principle (OCP)
L: Liskov Substitution Principle (LSP)
I: Interface Segregation Principle (ISP)
D: Dependency Inversion Principle (DIP)
Originally compiled by Robert C. Martin aka Uncle Bob in the 1990s, these principles provide a clear pathway for moving from tightly coupled code with poor cohesion and little encapsulation to desired results of loosely coupled code, operating very cohesively and encapsulating the real needs of the business appropriately.
Single Responsibility Principle
“There should never be more than one reason for a class to change” – Bob Martin
Martin described it as being based on the principle of cohesion, that is a class has only one reason to exist. The reason it is important for a class to be focused on a single concern is that it makes the class more robust.
It will be more vivid after this simple example. Suppose a software system has a Rectangle class. The Rectangle class has two methods, one returns the area of the rectangle object & another method is for rendering the rectangle. Now of the software system, a geometry service uses the area method whereas a graphical application uses the render method.
In this scenario, if there is a change in the geometry service it will impose change on the rectangle class. As a result the graphical application will have to be changed due to its dependency on the central rectangle class. This scenario is not following the Single Responsibility Principle as the rectangle class is existing for two reasons.
The solution is really simple. Splitting the rectangle class according to its responsibility. One part of the rectangle class would be responsible for the geometry calculations and another class would be responsible for the graphical work. Thus the two classes will exist for a single responsibility.Contributor: Sajid Rabbani, Jr. Software Engineer, Nascenia