2.2.9 · D1Design Principles

Foundations — Separation of concerns

2,045 words9 min readBack to topic

This page assumes nothing. Before you can reason about separating concerns, a handful of words and one or two symbols quietly appear in the parent note. We build each from the ground up — plain words first, then a picture, then why the topic needs it.


0. The picture we keep returning to

Everything below is about one move: taking a tangled blob and slicing it into focused pieces connected by thin lines. Hold this image in your head.

Figure — Separation of concerns

On the left, one shape does four jobs — the colours bleed together. On the right, four shapes each do one job, touching only through thin necks. That neck is the whole game.


1. "Module" — the box we draw a line around

  • Plain words: a module is a bag with a label. You use the label; you ignore what's in the bag.
  • The picture: a rounded rectangle. Anything inside the rectangle is private business; the edge of the rectangle is where other code touches it.
  • Why the topic needs it: Separation of Concerns is "put each concern in its own module". Without the idea of a box you have nothing to put concerns into. Every later word — coupling, cohesion, boundary — is measured relative to these boxes.

Related idea you'll meet later: hiding the inside so callers only see the label is Information Hiding, and a system built well out of such boxes has good Modularity.


2. "Concern" — one reason a box would ever change

The parent note leans on this word constantly, so we make it concrete.

  • Plain words: ask "Who would come to my desk and say 'change this', and why?" Each different answer is a different concern. "The tax office changed the rate" and "the designer wants a new colour" are two different people with two different reasons — two concerns.
  • The picture: imagine each line of code painted a colour, one colour per reason-to-change. A tangled module is a rainbow smear; a separated module is a single solid colour.
  • Why the topic needs it: "concern" is the unit we separate. This is the same idea as the Single Responsibility Principle — "one reason to change" — just named differently.
Figure — Separation of concerns

The left box is tangled (many colours in one box). The right shows the cure: sort by colour so each box is one solid colour.


3. Two failure words: tangling and scattering

  • The picture: tangling = many colours in one box (vertical mess). Scattering = one colour spread over many boxes (horizontal mess). They are opposite directions of the same disease.
  • Why the topic needs it: these two words name exactly the two ways SoC can be violated, and the "many files ≠ separation" mistake in the parent is precisely scattering that looks organised.

4. "Depends on" — the arrow between boxes

Before we can count anything, we need the single arrow the whole topic is built on.

  • Plain words: an arrow points from the one who needs to the one who is needed. "I call your phone number" → I depend on you.
  • The picture: a directed arrow . Read it as "A leans on B".
  • Why the topic needs it: every structural claim in the parent — "arrows point one way", "database swap never forces a UI rewrite" (Layered Architecture) — is a claim about which direction these arrows point. No arrow, no argument.
Figure — Separation of concerns

Left: arrows point every-which-way — a change anywhere ripples everywhere. Right: arrows point one direction only (top → down); a change at the bottom can't climb back up. That one-way rule is SoC made structural.


5. Coupling — counting the arrows leaving a box

Now the first symbol from the parent's formula.

Let's earn every part of that line:

  • is just a name standing in for any module — "pick a box, call it ".
  • is read "the coupling of " — a function here just means "a machine: feed it a box , it hands back a number". The number is a plain count.
  • Why counting? Because each outward arrow is a way the outside world can break . Fewer arrows out = fewer ways to break = easier to change in isolation. Counting turns a vague feeling ("this is too entangled") into a number you can compare.
  • The picture: stand at box , count the arrows leaving it. Three arrows out → .

6. Cohesion — how tightly the insides belong together

The second symbol, and the trickier one.

Building the symbol piece by piece — this is a fraction, so we need a top and a bottom:

  • An element = one small part inside the box (one function, one field, one variable).
  • A relation = "these two elements touch" — one calls the other, or they share data.
  • Bottom (denominator): total possible relations — if a box has elements, the number of possible pairs is That symbol (read "n choose 2") just counts how many pairs you can make from things. Why this? Because cohesion is a fraction and every fraction needs a "out of how many?" — the total pairs is that "out of".
  • Top (numerator): among those pairs, how many are actually working together on the same concern.
  • The fraction bar turns two counts into a score between and : = nothing inside relates (junk drawer), = everything inside pulls in the same direction (a laser).

The parent calls these two numbers the measurable side of SoC. Their names as a pair — low coupling, high cohesion — are the whole subject Coupling and Cohesion.


7. Why both numbers, and why you can't cheat

Cutting one concern into too many pieces overshoots into fragmentation (high coupling, a maze of crumbs). Cutting too few leaves tangling. SoC is the right-sized cut.


8. "Boundary" and "interface" — the thin neck

  • The picture: the thin neck connecting two boxes in figure s01. Everything wide (the box body) is private; only the thin neck is public.
  • Why the topic needs it: a boundary is how you keep coupling low — the fewer names on the neck, the fewer arrows can form. This is Information Hiding in action, and it's the "insert a boundary" step of the parent's recipe.

9. Prerequisite map

Module = a box of code

Concern = one reason to change

Dependency = arrow between boxes

Tangling and Scattering

Coupling = count outward arrows

Cohesion = fraction of shared-concern pairs

Boundary and Interface

Separation of Concerns

Read top to bottom: a module and a concern are the raw ideas; the arrow lets us count coupling; module + concern give cohesion; a boundary controls the arrows; all of it feeds Separation of Concerns at the bottom.


Equipment checklist

Self-test — can you answer each before revealing?

A module is
any named box of code (function, class, file, or layer) with a private inside and a public edge.
A concern is
one reason someone would ask you to change the code (a cause of change), not one line or one feature.
Tangling vs scattering
tangling = many concerns in one module; scattering = one concern spread across many modules.
The arrow means
A depends on B — A needs B, so if B changes A might break.
counts
the number of other modules M depends on (outward arrows); we want it low.
counts
the number of pairs you can form from elements, equal to .
is
the fraction of possible internal pairs that actually serve the same concern; between 0 and 1, we want it high.
Why optimise both coupling and cohesion
each is gameable alone (one giant box, or many chatty boxes); winning both forces cutting along real concern seams.
A boundary / interface is
the edge around a concern plus the narrow set of public names used to cross it — the label, not the contents.