The effects of cohesion and coupling on a software project

cohesioncouplingsoftware projectDesign Principles
Apr 30, 2023

Since my last post, I had the opportunity to give some interesting talks about design principles and clean code at workplace. As a result, today I want to discuss the characteristics and symptoms of software that are as important as knowing how to classify asymptotic analysis or model a database.

At some point, you may have heard of coupling and cohesion in software. A common context is that it is usually easy to maintain software with "low coupling" and "high cohesion." However, without a clear definition in mind, knowing this tendency is meaningless.

Basically, coupling refers to the degree of dependency between the modules of an application. Another definition that is the simplest I can imagine is "Things that should not be dependent or together but were put together anyway." In other words, the positive tendency in this context of the commonly repeated phrase "low coupling" means that the less dependent the modules of an application are, the better. These modules can be files, functions, or even classes, and their dependence on the available resources of the programming language you choose to use.

On the other hand, cohesion refers to modules implementing lean units of the same context. Another definition that is the simplest I can imagine is "things that belong together are put together." This would be a cohesive module, where each module can be responsible for only one thing and has only one reason to change. It has a lot to do with the Single Responsibility Principle, which is one of the design principles of SOLID. When we think of "high cohesion," it is a positive tendency for a module to have the smallest possible number of different contexts and few reasons or only one reason to change.

In this sense, a question I had when I first heard the jargon related to these characteristics is "why is low coupling and high cohesion positive characteristics?" And I believe that the answer to this question becomes clearer when we try to understand the effect of having the software made in a way opposite to this, in the case of high coupling and low cohesion.

The effects of low coupling and high cohesion are reflected in symptoms that indicate that the software in question is decaying. These symptoms are stiffness, fragility, viscosity, and immobility. Stiffness refers to the moment when developing new changes (creating or altering functionalities) tends to be slow because when you alter one module because it is coupled with another, you also need to alter the other module, and so on. This also shows low cohesion because if cohesion were high, the functionalities would be arranged in few modules in one place.

Fragility is noticeable when maintaining a module, and it becomes necessary to fix other modules that are not part of the same functionality or scope, thus demonstrating high coupling among these modules.

Immobility is the tendency not to be able to reuse knowledge. The more immobile it is, the less reusable it is. It makes it difficult to implement new functionalities related to existing resources in the software.

Viscosity is also informally known as "gambiarra" (variation of workaround) in Brazil. It is when it becomes easier to implement a "hack" than to preserve the design of your system with good practices. In other words, it is when it is easier to do the wrong thing than to do the right thing. And within this symptom, you can divide it into two spectrums: the viscosity of the design, which was the last one defined, but there is also another one called the viscosity of the environment, which is when you have a slow and inefficient development environment, full of processes so rigid that you tend to avoid or even circumvent such processes, for example, when compilation times are very long, engineers will be tempted to make changes that do not force large recompilations.

Note that all of the above can affect how a manager perceives and deals with your team. For example, in the case of rigidity, a manager who perceives that demands are taking longer to be met tends to demand fewer tasks per cycle to avoid them taking too long to be launched in production. In the case of a system with high fragility, a manager may even develop a certain fear of requesting new demands because they will never know when changing a small and less important functionality can lead to detonating the entire system. And I imagine, not only managers, but also developers who do not write tests and make software with low cohesion and high coupling tend to be more prone to feel adrenaline and panic with each new release.

To avoid such symptoms, there are several techniques and principles that can help you write software with high cohesion and low coupling that will avoid the 4 mentioned symptoms, such as the SOLID principles, DRY, KISS, YAGNI, WET, and many others that I still intend to address in the future.

Whenever you write code, consider these two characteristics of cohesion and coupling because in my view, they are two fundamental metrics of software engineering, as they will lead you to a system that is more easily maintainable and flexible. Many concepts, techniques, and processes revolve around adjusting software for better cohesion and lower coupling.

Sapere Aude.