Coupling and Cohesion
The primary OO goals are loose coupling and high cohesion. The key to creating maintainable code is adhering to loose coupling, high cohesion.
Coupling in simple words, is how much one component knows about the inner workings or inner components of another one, i.e. how much knowledge it has of the other components.
Components should be as independent as possible from other components, so that changes to component don’t heavily impact other components.
Tight coupling is where components are so tied to one another, that you cannot possibly change the one without changing the other.
Tight coupling would mean that your module knows the way too much about the inner workings of other modules. Modules that know too much about other modules make changes hard to coordinate and make modules brittle. If Module A knows too much about Module B, changes to the internals of Module B may break functionality in Module A.
Loose coupling is a method of interconnecting the components in a system or network so that those components depend on each other to the least extent practically possible.
By aiming for loose coupling, you can easily make changes to the internals of modules without worrying about their impact on other modules in the system. Low coupling also makes it easier to design, write, and test code since our modules are not interdependent on each other. We also get the benefit of easy to reuse and compose-able modules. Problems are also isolated to small, self-contained units of code.
- Inversion Of Control (IoC) / Dependency Injection (DI)
Example of using DI to implement a loosely coupled class:
Cohesion often refers to how the elements of a components belong together. Related code should be close to each other to make it highly cohesive.
There are 2 types of Cohesions: Low Cohesion and High Cohesion.
Low cohesion would mean that the code that makes up some functionality is spread out all over your code-base. Not only is it hard to discover what code is related to your module, it is difficult to jump between different modules and keep track of all the code in your head.
If a class has for example three private fields and three methods; when all three methods use just one of the three fields then the class is poorly cohesive.
Example when a class is designed to perform many different tasks instead of focusing on any specific task then that class is called “Low Cohesive class”. This kind of approach is the bad programming design approach. It required a lot of modifications for small change.
By keeping high cohesion within our code, we end up trying DRY code and reduce duplication of knowledge in our modules. We can easily design, write, and test our code since the code for a module is all located together and works together.
If a class has for example one private field and three methods; when all three methods use this field to perform an operation then the class is very cohesive.
Example when a class is designed to perform any specific task then that class is called as “High Cohesive class”. This kind of approach is good programming design approach. It can easily maintain and less modifiable.
- Cohesion can represent relationships within a component. Coupling can represent links between components.
- Cohesion can represent the power of linking functions. Coupling can represent a system that depends on many components.
- Cohesion evaluates the quality with which a component/module focuses on a unit of work. Coupling is being evaluated to what extent a component/module is associated with other modules.
Writing maintainable code helps increase productivity for developers. Having highly maintainable code makes it easier to design new features and write code. Modular, component-based, and layered code increases productivity and reduces risk when making changes.
By keeping code loosely coupled, we can write code within one module without impacting other modules. And by keeping code cohesive, we make it easier to write DRY code that is easy to work with.
While you are writing and working with your code base, ask yourself:
- 1.How many modules am I touching to fix this or create this functionality?
- 2.How many different places does this change need to take place?
- 3.How hard is it to test my code?
- 4.Can we improve this by making code more loosely coupled? Can this be improved by making our code more cohesive?