skip to content

How does Separation of Concerns relate to the Single Responsibility Principle, and where do the two differ?

level: middleimportance: must knowfreq 66%

answer

  1. SRP = SoC at class scope
  2. tangling (SRP) vs scattering (SoC)
  3. "one reason to change" = one actor
  4. cross-cutting → decorators/middleware/AOP
  5. SRP-clean codebase can still violate SoC

basics

~20 s

They overlap: SRP says one class should have one reason to change, which is SoC applied to a class. SoC is broader — it applies to functions, files, layers and whole systems, including concerns spread across many classes.

solid answer

~50 s

Separation of Concerns is the general principle: partition the system so each part handles one distinct area of interest. The Single Responsibility Principle is its class-level specialization — Robert C. Martin's formulation is "a module should have one, and only one, reason to change", later clarified as "be responsible to one actor/stakeholder". Differences: (1) **Scope** — SRP targets a class or module; SoC applies from a single function up to layers, services and deployment artifacts. (2) **Direction** — SRP is mostly about *not putting too much in one unit*; SoC also demands the converse, that one concern not be *scattered* across many units (duplicate logging code, business rules spread through controllers). (3) **Cross-cutting concerns** — logging, transactions, authorization inherently span all classes; SRP alone can't express them, so SoC reaches for decorators, middleware, interceptors or AOP. In practice: satisfy SRP class by class, and use SoC to ask whether the *set* of classes localizes each concern.

go deeper

for a junior

Say SRP is one class = one job, and SoC is the same idea applied more broadly to files, layers and the whole system.

for a middle

Give the scope difference plus 'one reason to change / one actor', and note cross-cutting concerns need middleware or decorators rather than SRP.

for a senior

Contrast tangling vs scattering, show an SRP-clean but SoC-violating codebase, and connect to cohesion and the Common Closure Principle.

for a principal

Frame both as change-cost heuristics; discuss picking the separation axis from actual change history and team topology, and when merging concerns is the right call.

## Definitions first **Separation of Concerns (SoC)** — decompose a system so each part addresses one *concern* (a distinct area of interest: persistence, presentation, domain rules, security, logging), and so that a concern is handled in as few places as possible. **Single Responsibility Principle (SRP)** — the "S" of the SOLID acronym (Robert C. Martin). Original phrasing: *a class should have only one reason to change.* Because "reason to change" is vague, Martin later restated it as: *a module should be responsible to one, and only one, actor* — where an actor is the person or role who requests the change (the CFO, the DBA, the operations team). ## The overlap Applied to a class, SRP *is* SoC. If a class handles both report formatting (requested by the business) and database access (requested by the DBA), it mixes concerns and has two reasons to change. Fix either way: split it. ## Four real differences ### 1. Scope / granularity SRP is stated for a class or module. SoC is scale-free: | Scale | SoC example | Does SRP say anything? | |---|---|---| | Function | Extract validation out of a render loop | Only by analogy | | File | HTML / CSS / JS split | No | | Class | Invoice vs. InvoicePrinter | Yes — this is SRP | | Layer | Domain vs. infrastructure | Indirectly | | Service | Payments vs. catalog | Indirectly | | Ops | Code vs. config vs. secrets | No | ### 2. Scattering vs. tangling Two distinct pathologies, named in the AOP literature: - **Tangling** — one module contains several concerns. SRP addresses this directly. - **Scattering** — one concern is spread over many modules (retry logic copy-pasted into 40 clients; business rules smeared across controllers). Every one of those 40 classes can satisfy SRP individually, yet the *concern* is not separated. SoC names this problem; SRP does not. This is the most important difference in interviews: **a codebase can be fully SRP-compliant and still violate SoC.** ### 3. Cross-cutting concerns Logging, authorization, transaction demarcation, metrics, caching, and audit trails apply to nearly every operation. They can't be given "their own class that everything else ignores" using ordinary composition alone without touching every call site. SoC therefore motivates mechanisms that inject a concern from outside: decorators/proxies, HTTP middleware pipelines, interceptors, aspects (AOP), annotations processed by a container, or sidecars/service meshes at the infrastructure level. SRP has nothing to say about how to weave a concern in. ### 4. The definition of the "one" thing SRP's unit of separation is the **actor / reason to change** — a people-and-change criterion. SoC's unit is the **concern** — a conceptual criterion. They usually agree, but not always: two concerns owned by the same actor (e.g. "parse CSV" and "validate CSV", both requested by the same team) may legitimately live together under SRP while still being separable concerns; conversely one concern (pricing) may be requested by two actors, which SRP would want split. ## Common confusions to avoid - **"SRP means a class does one thing"** — too literal; taken to extremes it produces hundreds of one-method classes and *scatters* concerns, harming SoC. "One reason to change" is the operative phrase. - **"SoC is just SRP for architecture"** — closer, but it still misses scattering and cross-cutting concerns. - **"Both mean maximum decomposition"** — no. Both are about putting things that change together in the same place and things that change apart in different places. Cohesion is the other half of the story: Constantine/Yourdon's *cohesion* and the Common Closure Principle ("classes that change together belong together") capture it. ## How to use both in practice 1. Identify the concerns of the feature (transport, validation, domain rule, persistence, presentation, plus cross-cutting ones). 2. Give each concern a home — a module, a layer, or a middleware/decorator for cross-cutting ones. 3. Then check each class with SRP: does it serve more than one actor? Split if so. 4. Then check the inverse with SoC: is any concern scattered? Consolidate if so. 5. Sanity check by change: pick three likely future requirements and count the modules each one touches.

  • Give an example of a codebase that satisfies SRP everywhere but still violates Separation of Concerns.
    Forty HTTP clients each with hand-written retry, timeout and logging code. Each class has one reason to change from its owner's perspective, but the resilience/logging concern is scattered across forty places, so changing the retry policy means forty edits. The fix is to localize the concern in a decorator or middleware.
  • Why did Robert C. Martin restate SRP as "responsible to one actor" rather than "does one thing"?
    Because "one thing" has no objective boundary and pushes people toward absurdly small classes. Tying responsibility to the actor who requests changes makes the criterion testable: if two different stakeholders can independently demand edits to the same module, their changes will collide, so split it.
  • Does splitting every class into the smallest possible units improve SoC?
    No — beyond a point it scatters a single concern across many units, raising coupling and making a change touch more files. Cohesion and the Common Closure Principle ("what changes together stays together") bound the split.

context