Unit 11 · lesson

Change One Component Without Rebuilding the System

Good boundaries show their value when requirements change.

Suppose this system exists:

ScoreService
  |-- ScorePolicy
  `-- MessageSink

Version 1 uses:

BasicScorePolicy
ConsoleSink

New requirement:

Keep score calculation the same, but produce a compact message format for a small display.

If formatting is mixed into score calculation, the change can ripple through unrelated code.

If formatting is a collaborator, substitute the component that owns that responsibility.

Change-impact matrix

For each requirement, predict which component should change.

requirementexpected component
scoring threshold changesscoring policy
output destination changessink
message wording changesformatter
orchestration sends two messagesservice/coordinator

If every change requires editing every class, your boundaries are not isolating responsibilities.

Replace behavior through composition

Formatter normal = new NormalFormatter();
Formatter compact = new CompactFormatter();

var serviceA = new NotificationService(normal, new ConsoleSink());
var serviceB = new NotificationService(compact, new ConsoleSink());

The service behavior changes through its collaborator configuration.

No inheritance is required between NotificationService variants because the service itself did not become a different conceptual type.

Beware configuration explosion

Composition can also become excessive if every tiny choice becomes a new object with no stable responsibility.

Ask:

  • Is this behavior likely to vary independently?
  • Does it have a clear contract?
  • Does separating it reduce the coordinator's knowledge?
  • Can the new boundary be tested meaningfully?

If not, a method may be enough.

Change experiment

Build a three-component system and capture passing output.

Then change exactly one requirement that belongs to one collaborator.

Version 2 should change that collaborator while leaving at least one other component source untouched.

Run regression cases that prove the unchanged responsibility still behaves the same.

Evidence

Create a before/after change-impact diagram. Mark:

  • requirement changed;
  • component edited;
  • components not edited;
  • regression cases rerun.

Then explain why inheritance would or would not improve this specific design.

The goal is not composition worship. The goal is being able to predict where a requirement change should land.