Skip to content

Single-Responsibility Principle

A module should have exactly one reason to change — read as one external change-driver, not one function — so that aligning each boundary with a single driver keeps every edit's blast radius contained.

Core Idea

The Single-Responsibility Principle, the S in the SOLID object-oriented design canon formalized by Robert C. Martin, holds that a module — class, function, microservice, or analogous unit — should have exactly one reason to change. "Reason to change" is the operative phrase: responsibility is read not as a functional description of what the unit does but as an identification of which actor or change-driver in the surrounding system could cause the unit to be edited. A class that computes payroll and formats payroll reports has two reasons to change — shifts in business policy governing overtime, and shifts in output format preferences — and thus two distinct sources of coupling to unrelated parts of the system. The principle prescribes decomposing such a unit along its change-axes, aligning each module boundary with exactly one change-driver, so that a change in business policy touches only the payroll-computation class and a change in formatting touches only the report-formatting class.

The mechanism by which this reduces maintenance cost is blast-radius containment: when a unit has a single reason to change, edits to it propagate no further than the scope of that reason. When a unit conflates two reasons, an edit driven by one concern can inadvertently alter the code path of the other, coupling development teams, generating merge conflicts between groups working on unrelated features, and requiring the test suite to re-verify unrelated behaviour after each change. The practical diagnostic is enumeration: list every cause that could drive a change to this module; if the list contains more than one unrelated driver, the module is a candidate for splitting. The principle does not prescribe a unique decomposition — it names the alignment criterion, not the algorithm for finding it — and its application requires judgment about which change-drivers are genuinely distinct versus which are aspects of a single coherent responsibility.

Structural Signature

Sig role-phrases:

  • the unit — a module, class, function, or microservice that bundles behaviors and is the candidate for decomposition
  • the change-drivers — the actors and concerns in the surrounding environment (business-policy owner, report-format owner, auth team, schema owner) that could force the unit to be edited
  • the responsibility-as-reason-to-change — responsibility re-read not as what the unit does but as which change-driver could cause it to be edited, replacing a grouping-of-verbs question with an enumerable environmental fact
  • the one-driver-per-unit alignment — the prescribed criterion: each module boundary aligned with exactly one change-driver, seams cut along change-axes
  • the enumeration test — the diagnostic: list every distinct driver that could edit this unit; more than one unrelated entry means the seam is misplaced and the unit is a split candidate
  • the blast-radius containment — the payoff: a single-driver unit confines an edit to its own scope, while a conflated unit lets one concern's edit reach another's code path, coupling teams, manufacturing merge conflicts, and forcing re-verification of untouched behavior
  • the residual distinctness judgment — the explicitly un-mechanized step: decide which candidate drivers are genuinely independent versus facets of one coherent responsibility, since the criterion names the alignment but supplies no algorithm for finding the seams

What It Is Not

  • Not "a unit should do one thing." The functional reading is hopelessly elastic — a class that parses, validates, and stores can be called one responsibility or three depending only on how the describer groups verbs. The operative criterion is one reason to change: one external change-driver, an enumerable fact about who requests edits, not a matter of how finely the behavior is described.
  • Not a recipe for a unique decomposition. The principle names the alignment criterion (one module per change-driver), not an algorithm for finding the seams. It tells the designer what good boundaries look like; it does not compute them, and a given system admits many valid SRP-conforming partitions.
  • Not a mechanical test that removes judgment. The enumeration ("list the drivers that could edit this") surfaces candidates, but deciding which candidate drivers are genuinely distinct versus facets of one coherent responsibility is explicitly left to judgment. Over-splitting fragments a coherent unit; under-splitting leaves the conflation — and the count alone settles neither.
  • Not a synonym for separation of concerns or modularity. It is the harder, more specific operationalization — "one reason to change" rather than "concerns kept apart" or "broken into units." The substrate-portable structural content (align boundaries with the problem's change-axes) belongs to those parent primes; what SRP adds is the change-driver enumeration test and software rule-force.
  • Not a general writing or org-design law with rule-force. Reaching for SRP outside a development-and-deployment regime — "each paragraph develops one idea," a department owns one mandate — is mostly analogical: the maintenance intuition rhymes, but the binding diagnostic that gives SRP its force (enumerate who edits this code) has no literal counterpart, and the cross-domain lesson is better carried by modularity and separation_of_concerns directly.

Scope of Application

The single-responsibility principle lives across the design subfields of software and computing, recurring at every unit of decomposition; its reach is bounded to that domain (the substrate-portable "align boundaries with the problem's change-axes" insight is carried by parent primes such as modularity, separation_of_concerns, and cohesion, while SRP's change-driver enumeration test and rule-force presuppose a development-and-deployment regime).

  • Object-oriented class design — the canonical home and the S of SOLID: split a payroll-computing-and-formatting class along its two change-drivers (business policy, output format).
  • Function design — a function that both validates and writes to disk forces every caller to inherit both concerns; align each function with one change-driver.
  • Microservice architecture — each service owns one business capability; a service aggregating two suffers joint deployment risk and conflicting scaling requirements.
  • Module and component boundaries — the same change-axis alignment governs where package and component seams are cut so an edit's blast radius stays contained.

Clarity

The principle's clarifying force is its redefinition of "responsibility." Read the ordinary way — as what a unit does — "one responsibility" is hopelessly elastic: a class that parses, validates, and stores can be described as having one responsibility ("handle the record") or three ("parse," "validate," "store") depending only on how the describer chooses to group verbs, so the rule "do one thing" gives no traction. By re-reading responsibility as reason to change — which actor or change-driver in the surrounding system could force this code to be edited — the principle replaces an argument about functional description with an enumerable question about the environment. The change-axes of a system are facts about who requests edits (the business-policy owner, the report-format owner), not matters of taste, and that makes the principle's central diagnostic concrete: list every distinct driver that could cause this module to change; if the list has more than one unrelated entry, the seam is in the wrong place.

That reframing also makes legible why a conflated module costs what it does, by giving the blast radius a name. When structural boundaries cut across change-axes rather than along them, an edit driven by one concern reaches into the code path of another — coupling the teams that own those concerns, manufacturing merge conflicts between groups working on unrelated features, and forcing the test suite to re-verify untouched behavior. Seeing the cost as blast radius escaping its reason sharpens the question a designer asks at a module boundary: not the unanswerable "does this class do one thing?" but "do all the edits this class will ever receive come from the same source?" The principle is careful about what it does not supply — it names the alignment criterion, not an algorithm for finding the seams, and leaves to judgment which change-drivers are genuinely distinct versus facets of one coherent responsibility — so its contribution is precisely to make the right question askable, not to answer it mechanically.

Manages Complexity

Deciding how to carve a system into modules is, in the general case, a combinatorial sprawl: a body of behaviors can be grouped into classes and services in astronomically many ways, and the everyday criterion — "make each unit do one thing" — gives no purchase, because "one thing" can be re-described at any grain and so admits almost any partition as defensible. The Single-Responsibility Principle compresses that open-ended carving problem onto one external coordinate. Instead of arguing about functional descriptions, the designer enumerates a finite, observable quantity — the change-drivers in the surrounding environment, the actors and concerns (business-policy owner, report-format owner, auth team, schema owner) that could force an edit — and the prescribed decomposition is read off directly: one module per distinct change-driver, seams aligned with the boundaries between drivers. The space of "where should the boundaries go" collapses from a taste-dependent infinity to a near-mechanical alignment against a list the designer can actually write down, because the change-axes of a system are facts about who requests edits, not matters of grouping preference.

What the principle lets a maintainer read off, given that alignment, is the blast radius of any future change — and this is where the compression pays maintenance cost. The diffuse worry "what will this edit break, and whom will it entangle?" reduces to tracking a single relationship: does each unit map to exactly one driver? When it does, an edit driven by one concern is contained within one module's scope and propagates no further; when a unit conflates two drivers, the consequences follow predictably — an edit for one concern reaches the code path of the other, coupling the owning teams, manufacturing merge conflicts between groups on unrelated features, and forcing the test suite to re-verify untouched behavior. So the maintainer no longer re-analyzes coupling case by case across the whole system; they apply one diagnostic per module — list the distinct drivers that could edit it; more than one unrelated entry means the seam is misplaced — and the qualitative maintenance outcome (contained change versus rippling change) is read straight off that count. The principle is deliberately partial about what it compresses: it supplies the alignment criterion and the enumeration test, not an algorithm for finding seams or for judging which drivers are genuinely distinct versus facets of one responsibility, so the sprawl it tames is the selection of boundaries against a known objective, with the residual judgment left explicit rather than hidden.

Abstract Reasoning

The principle's reasoning all flows from one reinterpretation — responsibility as reason to change — and the moves it licenses are about predicting and containing where edits propagate. The central diagnostic is enumeration run against the environment, not the code: confronted with a module, the designer lists every distinct actor or change-driver that could force it to be edited — the business-policy owner, the report-format owner, the auth team, the schema owner — and reads a verdict off the count. More than one unrelated driver means the seam is misplaced and the module is a split candidate. This is reasoning FROM the external set of change-drivers TO a structural defect in the module, and its power is that change-axes are facts about who requests edits, not matters of how one chooses to group verbs, so the test is enumerable rather than a matter of taste.

A predictive move follows from any given alignment. Given that each module maps to exactly one driver, the maintainer forecasts the blast radius of a future change before making it: an edit driven by one concern stays within that module's scope and propagates no further. Given a module that conflates two drivers, the prediction is specific and adverse — an edit for one concern will reach into the code path of the other, couple the teams that own those concerns, manufacture merge conflicts between groups working on unrelated features, and force the test suite to re-verify untouched behavior. Reasoning FROM "how many drivers does this unit serve" TO "what will the next edit entangle" is what lets a designer anticipate coupling rather than discover it after a regression.

The interventionist move is decomposition along the change-axes, with a stated effect: split the payroll-computing-and-formatting class along its two drivers and predict that a business-policy change thereafter touches only the computation module while a format change touches only the formatter, each edit's blast radius collapsing to a single reason. The principle is deliberately partial here — it names the alignment criterion (one module per change-driver) but supplies no algorithm for finding the seams, so the intervention is "align boundaries with drivers," not "here is the unique decomposition."

The boundary-drawing move is where the residual judgment lives, and the principle is explicit that it cannot be mechanized. The reasoner must decide which candidate change-drivers are genuinely distinct versus which are facets of one coherent responsibility — two ways of describing a single actor's edits should not be split, while two truly independent actors should. Drawing that line wrong in one direction fragments a coherent unit into needless pieces; wrong in the other leaves the conflation the principle exists to remove. So the move is FROM a list of candidate drivers TO a judgment about which are independent, and the principle's honesty is in marking this as judgment rather than pretending the enumeration settles it.

Knowledge Transfer

Within software the principle transfers as mechanism across every unit of decomposition, because its core reinterpretation — responsibility as reason to change, read off the external set of change-drivers — and its diagnostic (enumerate the distinct actors that could edit this unit; more than one unrelated entry means the seam is misplaced) and its blast-radius prediction carry intact regardless of the unit's grain. It is the S of SOLID at the class level (split a payroll-computing-and-formatting class along its two drivers). It governs function design (a function that both validates and writes to disk forces every caller to inherit both concerns). It scales to microservice architecture (each service owns one business capability; a service aggregating two suffers joint deployment risk and conflicting scaling requirements). Across these the change-axis alignment criterion and the enumeration test mean the same thing and prescribe the same move — align one module per change-driver — so the transfer through the software substrate is mechanism, recognised at every level of granularity, not analogy.

Beyond software the honest account is the shared-abstract-mechanism case, and the entry should be candid that the principle's distinctive force does not travel. The structural insight it carries — align boundaries with the change-axes already implicit in the problem so each unit's blast radius stays contained — is genuinely substrate-portable, but it is already carried at that level of generality by the parent primes modularity (the system property of breaking into units), separation_of_concerns (the broader heuristic of keeping concerns apart), and cohesion (elements that change together belong together). What stays home-bound is everything that makes SRP a named rule with rule-force: the "one reason to change" formulation, the change-driver enumeration test, and the whole SOLID/class/deployment-unit heritage, all of which presuppose a development-and-deployment regime in which "editing a module" is the unit of cost and risk. So when the principle is reached for outside that regime — "each paragraph should develop one idea," a department should own one mandate — it is mostly an analogical reach: the maintenance intuition (one reason to change → localized ripple) rhymes, but the binding diagnostic that gives SRP its force (enumerate who edits this code) has no literal counterpart, and the cross-domain lesson is better carried by modularity and separation_of_concerns directly. SRP adds no structural move that is not already inside those primes; what it adds is the software-specific operationalization and rule-force. The cross-domain reach therefore belongs to the parents; "single-responsibility principle," as named, stays the object-oriented and service-design rule (see Structural Core vs. Domain Accent).

Examples

Canonical

Robert C. Martin's own teaching example (in Clean Architecture, 2017) is an Employee class exposing three methods: calculatePay(), reportHours(), and save(). Functionally it looks cohesive — all about employees — but the three methods answer to three different parts of the organisation. calculatePay() is specified by the accounting department, reporting to the CFO; reportHours() is specified by human resources, reporting to the COO; save() is specified by the database administrators, reporting to the CTO. Because three different actors can each demand a change, the class has three reasons to change. Martin shows how a shared helper (say, regularHours()) used by both pay and reporting lets an edit requested by the CFO silently break the report the COO relies on. The prescribed fix is to separate the three along their actors.

Mapped back: The Employee class is the unit; the CFO, COO, and CTO organisations are the change-drivers. Reading the flaw as "three actors can force an edit," not "three verbs," is the responsibility-as-reason-to-change move, and listing those three actors is the enumeration test returning more than one. The CFO's edit corrupting the COO's report is blast-radius containment violated; splitting one class per actor restores it.

Applied / In Practice

Amazon's early-2000s re-architecture from a monolithic application ("Obidos") to a service-oriented architecture is a large-scale field deployment of the same criterion at service grain. The widely-reported internal mandate required teams to expose their functionality only through service interfaces, and the monolith was decomposed so that each service owned a distinct business capability — catalog, ordering, payments, and so on — with a single small team owning each. Because each service mapped to one capability and one owning team, a team could change and deploy its service without coordinating a joint release across the whole system, and scaling and failure were isolated per service. Aggregating two unrelated capabilities into one service would have reintroduced exactly the joint-deployment coupling the split removed.

Mapped back: Each service is the unit and its owning team plus the business capability it serves are the change-drivers. "One business capability per service" is the one-driver-per-unit alignment, and independent deployment without a system-wide release is blast-radius containment at architecture scale. Deciding that catalog and ordering are genuinely distinct capabilities — rather than facets of one — is the residual distinctness judgment the criterion leaves to the architects.

Structural Tensions

T1: The enumerable test versus the judgment it smuggles back in. SRP's clarifying move is to replace the elastic "does this do one thing?" with the enumerable "how many distinct actors could force an edit?" — trading a matter of taste for a fact about the environment. But the count only bites once you have decided which candidate drivers are genuinely distinct versus facets of one coherent responsibility, and that decision is the very same grouping judgment the reframing claimed to banish, now relocated one level down. Whether "parse" and "validate" are two drivers or one is no more mechanically settled than whether the class "does one thing." The tension is that the objectivity SRP advertises — enumerate the drivers — is real only after an irreducibly subjective distinctness call, so the principle both dispels and re-imports the taste-dependence at its core. Diagnostic: Is the driver count here reading off genuinely independent actors, or off a distinctness judgment that could be regrouped to yield a different count?

T2: Blast-radius containment versus fragmentation. Splitting a unit along its change-axes contains each edit's ripple — the CFO's change no longer breaks the COO's report. But every split is also a new boundary to cross, and over-applying the principle scatters what was one coherent behaviour across many tiny units, so a single conceptual change now requires coordinated edits across a dozen files or services (the "shotgun surgery" failure). Containment of one kind of coupling manufactures another: fewer edits reach the wrong code path, but more edits must touch many places to accomplish one intent. The tension is that the same cut which shrinks blast radius also raises fragmentation and navigation cost, and nothing in "one reason to change" says where the sweet spot between conflation and scatter lies. Diagnostic: Does splitting here contain a real cross-driver ripple, or fragment one coherent responsibility into pieces that will always have to change together?

T3: Change-drivers as objective facts versus their drift over time. The principle's strength is that change-axes are facts about who requests edits — the accounting department, HR, the DBAs — not matters of grouping preference, which is what makes the enumeration concrete. But those actors and their boundaries are themselves organizational artefacts that reorganize: departments merge, a capability that answered to one owner splits across two, an actor who never edited this code starts to. A seam aligned perfectly to today's driver map is misaligned the moment the org chart moves, and the "objective fact" the decomposition was pinned to turns out to be a moving target. The tension is that SRP grounds its objectivity in an external structure that is no more stable than the code, so a correct decomposition decays as the change-drivers it tracked rearrange. Diagnostic: Are the change-drivers this decomposition aligns to stable features of the domain, or a snapshot of an org structure that will re-partition them?

T4: Naming the criterion versus withholding the algorithm. SRP is scrupulously honest that it supplies the alignment criterion (one module per change-driver) but no procedure for finding the seams — which keeps it from overpromising. That honesty is also its practical limit: it tells a designer what a good boundary looks like without telling them how to compute one, so two competent designers applying the identical principle produce different valid decompositions and have no SRP-internal way to adjudicate between them. The principle diagnoses a misplaced seam but does not locate the right one. The tension is that the same restraint which makes SRP intellectually honest (it names a target, not a method) makes it operationally underdetermined (it cannot settle the design decisions it motivates), so its rule-force is weaker than its crisp statement suggests. Diagnostic: Does the principle actually pick the boundary here, or merely tell you that some boundaries are wrong while leaving the choice among the rest unresolved?

T5: Aligning to known change-axes versus the unanticipated one. The whole payoff is predicting blast radius before an edit by aligning seams to the change-drivers you can enumerate. But you can only align to the axes you foresee, and the change that hurts most is usually the one no one anticipated — a new regulatory driver, a cross-cutting concern like logging or security, a feature that slices across every existing module. When an unanticipated change-driver arrives, it cuts across even a perfectly SRP-aligned decomposition, because the seams were placed for a different axis. The tension is that SRP contains ripple only along the change-axes present at design time, and offers no protection — indeed can make things worse by over-committing to the wrong seams — against the future driver that was not on the list. Diagnostic: Is this decomposition robust to a plausible new change-driver, or optimized so tightly to today's known axes that an unforeseen one would cut across every seam?

T6: Autonomy versus reduction (a named software rule or the modularity/separation-of-concerns parents). SRP is a named rule with real rule-force and home-bound cargo — the "one reason to change" formulation, the change-driver enumeration test, the SOLID/class/deployment-unit heritage — and within software it transfers intact as mechanism across functions, classes, and services. But its portable structural content, "align boundaries with the change-axes implicit in the problem so each unit's blast radius stays contained," is already carried at that generality by the parents modularity, separation_of_concerns, and cohesion; SRP adds no structural move those primes lack, only a software-specific operationalization and rule-force. Reached outside a development-and-deployment regime ("each paragraph develops one idea") it becomes an analogical rhyme, since the binding diagnostic (enumerate who edits this code) has no literal counterpart. The tension is that the name's force is software-bound while its insight belongs to the parents. Diagnostic: Resolve toward modularity/separation-of-concerns when carrying the lesson beyond editable-deployable software; toward SRP when enumerating the change-drivers of a concrete module in situ.

Structural–Framed Character

The single-responsibility principle sits at the framed-leaning position on the structural–framed spectrum — a normative design rule with rule-force wrapped around a genuinely structural boundary-alignment insight. All five criteria pull framed, some hard. Evaluative_weight is high for a domain-specific entry: SRP is prescriptive, not descriptive — it says a module should have one reason to change, dividing boundaries into good and bad, so it renders a design verdict rather than naming a neutral mechanism. Human_practice_bound is high: the principle presupposes a development-and-deployment regime in which "editing a module" is the unit of cost and risk — its whole payoff, blast-radius containment, is defined over teams, merge conflicts, test suites, and deployments, and it dissolves the moment that engineering practice is removed. Institutional_origin is pronounced: SRP is the S of the SOLID canon, formalized by Robert C. Martin within an object-oriented design tradition — the "one reason to change" formulation, the change-driver enumeration test, and the class/service heritage are all artifacts of a software-engineering school, not facts of nature. Vocab_travels fails outside software: change-driver, blast radius, seam, deployment unit are pinned to editable-deployable code, and reached into writing or org-design the principle becomes an analogical rhyme whose binding diagnostic (enumerate who edits this code) has no literal counterpart. Correspondingly import_vs_recognize is import-by-analogy beyond software: "each paragraph develops one idea" borrows the maintenance intuition without the mechanism, and the real cross-domain lesson is carried by parent primes, not the named rule.

The portable structural skeleton is align each boundary with a single one of the change-axes already implicit in the problem, so every edit's blast radius stays contained — cut seams along the lines where change enters. That skeleton is genuinely substrate-portable and is exactly what SRP instantiates from its umbrella primes — modularity (breaking a system into units), separation_of_concerns (keeping distinct concerns apart), and cohesion (elements that change together belong together). But it is the umbrella that carries the cross-domain reach: the boundary-alignment insight belongs to those primes, and the entry is explicit that SRP adds no structural move they lack — only a software-specific operationalization (the change-driver enumeration test) and rule-force. Everything that makes "single-responsibility principle" the specific named rule — the "one reason to change" wording, the enumeration diagnostic, the SOLID/deployment heritage — stays home in software. Its character: a normative, practice-bound, institutionally-originated software design rule whose only substrate-spanning content is the align-boundaries-with-change-axes skeleton it instantiates from modularity, separation_of_concerns, and cohesion, dressed in a change-driver enumeration test that presupposes editable, deployable code.

Structural Core vs. Domain Accent

This section decides why the single-responsibility principle is a domain-specific abstraction and not a prime, and carries the case for its domain-specificity.

What is skeletal (could lift toward a cross-domain prime). Strip the software and a thin structure survives: align each boundary with a single one of the change-axes already implicit in the problem, so that every edit's blast radius stays contained. The portable pieces are abstract — a decomposable unit, the external change-drivers that could force it to change, and the prescription to cut one seam per driver so a disturbance stays within its own scope. That skeleton is genuinely substrate-portable, which is why it recurs as the parents SRP instantiates: breaking a system into units is modularity, keeping distinct concerns apart is separation_of_concerns, and elements-that-change-together-belong-together is cohesion. But it is the core SRP shares, not what makes it the single-responsibility principle.

What is domain-bound. Everything that gives SRP its rule-force is software-engineering furniture that does not survive extraction: the "one reason to change" reading of responsibility; the change-driver enumeration test; blast-radius containment defined over development teams, merge conflicts, test suites, and deployments; and the SOLID/class/microservice heritage formalized by Robert C. Martin. The entry's What It Is Not gives the decisive test: SRP is "not a general writing or org-design law with rule-force." Reached outside a development-and-deployment regime — "each paragraph develops one idea," a department owns one mandate — the maintenance intuition rhymes, but the binding diagnostic that gives SRP its force, enumerate who edits this code, has no literal counterpart. Remove editable, deployable code and "blast radius," "seam," and "deployment unit" lose their referents, leaving only bare boundary-alignment.

Why this does not clear the prime bar. A prime is a relational structure whose vocabulary travels and whose cross-domain transfer is recognition of the same mechanism, not analogy. SRP's transfer is bimodal. Within software it travels as mechanism across every unit of decomposition — function, class, microservice — the enumeration test and the blast-radius prediction meaning the same thing and prescribing the same move at each grain, recognition rather than analogy. Beyond a development-and-deployment regime it is analogical rhyme: the maintenance intuition carries, but the binding diagnostic does not, so the borrowing keeps the picture and drops the mechanism. And the entry is explicit that SRP "adds no structural move that is not already inside those primes" — its portable content, align boundaries with the problem's change-axes, is already carried at that generality by modularity, separation_of_concerns, and cohesion; what SRP adds is only the software-specific operationalization and rule-force. So when the bare cross-domain lesson is genuinely needed it is already carried, in more general form, by the parents; the named rule stays the object-oriented and service-design rule. The cross-domain reach belongs to the parents; "single-responsibility principle," as named, presupposes a development-and-deployment regime that should stay home.

Relationships to Other Abstractions

Local relationship map for Single-Responsibility PrincipleParents appear above the current abstraction, mutual partners to the right, and children below. Node labels state whether each abstraction is prime or domain-specific; colors identify relation types.Single-ResponsibilityPrincipleDOMAINPrime abstraction: Modularity — is a decomposition ofModularityPRIME

Current abstraction Single-Responsibility Principle Domain-specific

Parents (1) — more general patterns this builds on

  • Single-Responsibility Principle is a decomposition of Modularity Prime

    SRP is modular boundary drawing specialized to one external change-driver per software unit.

Hierarchy path (1) — routes to 1 parentless root

Not to Be Confused With

  • The Unix "do one thing well" philosophy. The design maxim that a program should perform a single narrow function and compose with others. It reads responsibility functionally — by what the unit does — which is exactly the elastic grouping-of-verbs reading SRP rejects in favour of one reason to change (one external change-driver). Tell: is the unit-of-account a behavior the tool performs (Unix "do one thing") or an actor who could demand an edit (SRP)? A tool can do one function yet answer to two change-drivers, and vice versa.
  • Interface Segregation Principle (the I of SOLID). A sibling SOLID rule: clients should not be forced to depend on interface methods they do not use, so fat interfaces are split into role-specific ones. It governs what a consumer depends on; SRP governs how many change-drivers a unit answers to. They often push the same split but from opposite ends. Tell: is the concern that callers are coupled to methods they never invoke (ISP) or that one module will be edited by several unrelated actors (SRP)? ISP is client-facing; SRP is change-driver-facing.
  • DRY (Don't Repeat Yourself). The principle that each piece of knowledge should have a single authoritative representation, targeting duplication. SRP targets conflation of change-drivers. They can conflict: aggressively de-duplicating shared code can force two unrelated change-drivers into one module, violating SRP to satisfy DRY. Tell: is the fault repeated knowledge in multiple places (DRY) or multiple reasons-to-change bundled in one place (SRP)? The remedies pull in opposite directions when a coincidental duplicate serves two masters.
  • Separation of concerns (parent). The broad heuristic of keeping distinct concerns apart. SRP is its harder, more specific operationalization — "one reason to change" plus a change-driver enumeration test — not a synonym. Tell: is the guidance the general "keep concerns apart" (separation of concerns) or the specific enumerate-the-editing-actors diagnostic with software rule-force (SRP)? The substrate-portable insight belongs to the parent; the enumeration test is SRP's addition. (Treated fully in a later section.)
  • Cohesion and modularity (parents). Cohesion is the system property that elements which change together belong together; modularity is decomposition into units as such. SRP instantiates both with a specific criterion — align each unit to a single change-driver — but is not identical to either. Tell: are you naming a measurable property of a design (how cohesive/modular it is) or the prescriptive rule for where to cut the seam (SRP)? SRP is the rule; cohesion and modularity are the properties a good cut produces. (Treated fully in a later section.)

Neighborhood in Abstraction Space

Single-Responsibility Principle sits in a sparse region of the domain-specific corpus (91st percentile for distinctiveness): few abstractions share its structure, so a faithful description tends to retrieve it precisely.

Family — Unclustered & Miscellaneous (309 abstractions)

Nearest neighbors

Computed from structural-signature embeddings · 2026-07-12