Lack of Cohesion of Methods

A cohesive class performs one function while a non-cohesive class performs two or more functions. This pass computes the number of disconnected components in your class. It considers components connected if they operate on the same properties, or call the same methods. When computing the connected components, this pass ignores some methods which are likely to operate on all properties such as constructors, destructors, and other special methods.

For example given a class with

  • methods: a(), b(), c(), d(), e(), and
  • properties: $x and $y

a non-cohesive class with non-connected components could look like this:

digraph lcom {
    node [fontsize=10]
    edge [fontsize=8]

    subgraph cluster1 {
        label = "Component #1";
        color=black

        "a()" [style=filled, fillcolor=grey, shape = rectangle]
        "b()" [style=filled, fillcolor=grey, shape = rectangle]
        "$x" [shape=circle]

        "a()" -> "b()" [label = "calls"]
        "b()" -> "$x" [label = "uses"]
    }

    subgraph cluster2 {
        label = "Component #2";
        color=black

        "c()" [style=filled, fillcolor=grey, shape = rectangle]
        "d()" [style=filled, fillcolor=grey, shape = rectangle]
        "e()" [style=filled, fillcolor=grey, shape = rectangle]
        "$y" [shape=circle]

        "c()" -> "$y" [label = "uses"]
        "d()" -> "e()" [label = "calls"]
        "d()" -> "$y" [label = "uses"]
    }
}

In such a case, you likely want to split off one of the components into a separate class to increase cohesion and separate concerns.

How to use

The ideal value of this metric is 1. Anything above means that a class performs more than one function or concern. However, there are certain cases when low data cohesion is desirable.

Some examples of well designed, yet low cohesive classes are the following:

  • A class groups related methods, not data. If you use classes as a way to group utility functions (most of the time these will be static functions).
  • A class provides some stateless methods, f.e. you provide some static stateless helper methods on a class.
  • A class provides storage only, f.e. an entity which only contains set/get methods. It might still make sense to split the entity into multiple classes in such a case.