The degree to which elements in a module belong together, serve the same purpose, change for the same reasons. Do things that should be together actually stay together?

Low cohesion: a “utils” file. High cohesion: a module that implements a specific feature or functionality,.

The dual: coupling

The mistake of excessive decomposition: splitting a cohesive operation across many tiny functions scatters related logic. Each piece looks “clean” in isolation but the whole is harder to understand because you’re jumping between fragments that should be next to each other. This is separation of concerns taken too far, separating by technical layer (e.g. model, view, controller) instead of by what actually changes together.

The cohesion test

If you need the word “and” to describe what a module does (it handles authentication and sends notifications and logs metrics), low cohesion. But “it does X” where X is a coherent multi-step operation is fine. The steps are cohesive because they serve one purpose.

A cohesive module is one you can reason about it as a unit without holding its internals in.