Java Cohesion and Coupling

lecture
java
cohesion
coupling

Introduced in 2026-04-02-refactoring (Lecture, Week 6, Part 2).

Modularization

The process of dividing a large system (a monolith) into smaller, more manageable pieces that can be worked on and tested independently before being reassembled into the final product. This raises a question: what if the resulting modules are highly dependent on each other?

Coupling

The degree of interdependence between different modules, classes, or components of a system.

  • High coupling — strong interconnections, where a change in one module can cascade through others.
  • Low coupling — greater independence and isolation between modules.

Levels of coupling (tightly → loosely coupled)

  1. Content — one class directly manipulates another’s data (e.g. public fields instead of private).
  2. Common — sharing access to the same global data/variables.
  3. External — sharing something imposed by an external source, e.g. a data format.
  4. Control — one class controls what happens in another by passing it information/instructions.
  5. Stamp — sharing a data structure, but each class only needs access to a select part of it.
  6. Data — sharing data through means such as parameter passing in methods.
  7. None — no dependency at all (most loosely coupled).

Worked classification examples

Classifying real code against the levels above (my own reasoned classification, following the definitions above — the lecture posed these as open discussion questions without a printed answer key):

public void sinh(int x) {...}
public void cosh(int x) {...}
public void tanh(int x) {
    return sinh(x) / cosh(x);
}

tanh only interacts with sinh/cosh by passing/receiving simple parameters — data coupling.

public class R { int x, y, z; char a, b, c; }
public static void compute(R r) {
    return r.x * r.y; // only touches x and y
}

compute is handed the whole R object but only needs two of its six fields — stamp coupling.

public static void compute(R r) {
    return r.x * r.y * r.z / r.a + r.b + r.c; // uses every field
}

Here every field of R is actually used, so passing the whole object is fully justified — this is just data coupling via a composite value, not stamp coupling (contrast with the previous example, which only used part of the structure).

public static runReport(String name, int age, String phone, Date birth, String address) {...}

Five separate simple parameters — still data coupling, though a long parameter list like this is itself often a separate code smell (see java-refactoring) worth considering bundling into an object.

Cohesion

The degree of interrelatedness and focus among the elements within a module, class, or component.

  • High cohesion — elements are closely related and contribute collectively to one specific functionality.
  • Low cohesion — elements are less focused, serving multiple unrelated purposes.

Levels of cohesion (low → high)

  1. Coincidental — elements grouped arbitrarily, with no clear relationship.
  2. Temporal — elements grouped because they execute at the same time/phase.
  3. Procedural — elements grouped by their involvement in a specific sequence of steps.
  4. Communicational — elements work together to manipulate a shared data structure.
  5. Sequential — elements organised in a linear sequence, where one’s output is the next’s input.
  6. Functional — elements grouped around a single, specific functionality or task (most cohesive).

Worked example

public void performTasks(int[] numbers, String text) {
    // Task 1: sum the numbers
    int sum = 0;
    for (int num : numbers) { sum += num; }
    System.out.println("Sum of numbers: " + sum);

    // Task 2: reverse the text
    StringBuilder reversedText = new StringBuilder();
    for (int i = text.length() - 1; i >= 0; i--) { reversedText.append(text.charAt(i)); }
    System.out.println("Reversed text: " + reversedText);
}

Summing numbers and reversing text share no real purpose — they’re only in the same method because they happen to run one after another. This is low (coincidental, or at best temporal) cohesion, and a sign performTasks should be split into two focused methods.

Is this class cohesive?

A Car class contains: Fuel, Steering, Speed, Route planner, Public holiday calculator.

Fuel/Steering/Speed are all core to a car’s own physical behaviour, but a route planner and (especially) a public-holiday calculator are unrelated concerns bolted onto the class — this is low cohesion, and a sign the class is trying to do too much (a “God class”); the unrelated pieces should be split into their own classes.

Considerations

  • Classes should be highly cohesive — a single, easily understood concept.
  • Classes should have loose coupling to each other — this reduces overall system complexity.

Good modularization (high cohesion, low coupling) groups tightly-interconnected elements together into the same module and minimises connections between modules, unlike bad modularization, where connections are scattered across module boundaries with no clear grouping.