The Modularity Principle: Designing Internally Cohesive Classes

The methods of a cohesive class work together to achieve a common goal. Classes that try to do too many marginally related tasks are difficult to understand, reuse, and maintain.

Cohesion is the formal way of saying “Each <THING> should do one thing and one thing only” where <THING> can be a function, a class, a module, etc.

While there is no precise way to measure the cohesiveness of a class, we can a rough spectrum (from low to high, left to right) (inspired from here):

A class exhibits coincidental cohesion if the tasks its methods perform are totally unrelated. If most of your classes look like this, they are not cohesive:

class Foo {
  void initPrinter() { ... }
  double calcInterest() { ... }
  Date getDate() { ... }
}

One reason why coincidental, logical, and temporal cohesion are at the low end of our cohesion scale is because instances of such classes are unrelated to objects in the application domain. For example, suppose x and y are instances of the Initializer class:

Initializer x = Initializer(), y = new Initializer();

How can we interpret x, and y? What do they represent? How are they different?

Generally speaking, you won’t be able to create classes which are informationally cohesive ALL the time, but you should always write your classes to be as cohesive in ways on the higher end of the spectrum.