In a software module, cohesion defines how well the individual parts are related to each other. When those parts are highly connected, then we can say that module is highly cohesive. If they're not operating or depending on each other, then the module has low cohesion. It is also significantly linked to coupling, as can be seen from a quote by Larry Constantine who developed those concepts:
Attempting to divide a cohesive module would only result in increased coupling and decreased readability.
When we're talking about cohesion, we generally prefer high cohesion (and low coupling). However, it's also true that not all types of cohesion are benefiting the architecture and the codebase. It's a good practice to investigate how to achieve better cohesion and high cohesion — although it depends on a case-by-case basis.
To understand cohesion, we can benefit from Object-Oriented Programming and borrow the Class concept as our module example.
Functions in a class are not related at all. They've just been grouped arbitrarily like in a Utility class.
Class functions are logically related, although operationally different. Think of a class for sending a notification, for example. One function handles push notifications, the next one sends emails, and the third sends text messages. They're logically doing the same thing (sending notifications), but what they do is entirely different.
Functions in a class are related based on when they're run. Whenever an exception occurs in one of the functions, another function is called to do the cleanup. They're doing two different things, so they're only temporally cohesive.
If you can properly run a specific function only after a different function is run, then those two functions are procedurally cohesive. Think of a function that is checking user permissions. Only if the user is authorized, the target function is run. Then these two functions have procedural cohesion.
When two functions are operating on the same set of data, they're communicationally cohesive. Let's say we have a class that is handling the payments. One of the functions writes the successful payment information to the database. Then the other function reads that data to start the shipping process. In this case, these two functions have communicational cohesion.
If one function's output is another one's input, then those two functions are sequentially cohesive. Think of a function that is creating a user profile. It accepts certain user information as well as a username. Instead of asking the user for a username, another function creates a slug from the user's first and last names. In this case, these two functions have sequential cohesion.
When functions of a class all contribute to a single task, then they are functionally cohesive. Let's say we have a class implementing the builder pattern. The class is named
CarBuilder, and all of its functions are used to build a car. The class has functional cohesion.
Although functional cohesion can also be defined as the perfect cohesion, atomic cohesion moves the needle one more step. When the class achieves functional cohesion and doesn't have anything besides the bare essentials, it has atomic cohesion.
Cover photo by Boba Jaglicic
 WILw: What I Learned while
 Types of Cohesion