{ "category": "Core Modular Design", "check": { "population": "every class, module and package boundary in the codebase", "freshness": "a verdict stands until the module's contents, exports or imports change", "refusal": "the dependency, visibility or clone rule fails the build on the change that breaks the property", "observation": "cohesion, coupling, duplication and export metrics read from source and the import graph", "evidence": "none: the catalog states this check as a class, so a watched run belongs to each system that adopts it", "authority": "the declared module boundary, which every import and export conforms to" }, "records": [ { "id": "single-responsibility", "distinctFrom": [ { "id": "architecture:interface-segregation", "reason": "Single responsibility limits a module's reasons to change, while interface segregation limits what a client depends on." }, { "id": "architecture:open-closed", "reason": "Single responsibility limits reasons to change, while the open/closed principle governs adding behavior without editing." }, { "id": "architecture:composability", "reason": "Single responsibility limits what one part does, while composability governs how parts combine." }, { "id": "architecture:separation-of-concerns", "reason": "Single responsibility is one reason to change per class or module, while separation of concerns separates the named concerns of a system." } ], "aliases": [ "SRP", "Single Responsibility Principle" ], "name": "Single Responsibility Principle (SRP)", "definition": "A design rule that a class or module has one reason to change, because it serves one responsibility.", "type": "principle", "scope": [ "class", "module", "service" ], "requires": [ "High Cohesion", "Explicit Boundaries" ], "reinforces": [ "Separation of Concerns", "Modularity", "Testability" ], "enables": [ "Replaceability", "Reusability" ], "conflicts_with": [ "God Object", "Blob Class", "Divergent Change" ], "tensions_with": ["Excessive Fragmentation"], "violated_by": [ "architecture:god-object", "architecture:divergent-change" ], "detected_by": [ "high fan-in/fan-out", "unrelated methods", "unrelated dependencies" ], "measured_by": [ "cohesion score", "responsibility count", "change-coupling" ], "refactored_by": [ "lexicon:extract-class", "lexicon:extract-module", "lexicon:split-bounded-context", "lexicon:move-behavior-to-its-owner" ], "enforced_by": [ "architecture tests", "package boundaries", "static analysis" ], "severity": "mandatory", "exemplar": { "before": "class FooService {\n save(foo: Foo) { fooDb.insert(foo); }\n send(foo: Foo) { fooMail.send(foo); }\n report(foo: Foo) { return `${foo.id}:${foo.name}`; }\n}", "after": "class FooRepository { save(foo: Foo) { return fooDb.insert(foo); } }\nclass FooNotifier { send(foo: Foo) { return fooMail.send(foo); } }\nclass FooReporter { report(foo: Foo) { return `${foo.id}:${foo.name}`; } }", "lang": "ts" } }, { "id": "separation-of-concerns", "distinctFrom": [ { "id": "architecture:one-concern-per-file", "reason": "Separation of concerns splits code by responsibility, while one concern per file binds each file to one declared role tag." }, { "id": "architecture:open-closed", "reason": "Separation of concerns decides where concerns live, while the open/closed principle decides how behavior is added." }, { "id": "architecture:composability", "reason": "Separation of concerns keeps concerns apart, while composability lets parts combine." } ], "aliases": ["SoC"], "name": "Separation of Concerns", "definition": "A design rule that parsing, business logic, persistence and presentation each live in their own part of the code.", "canon": ["separation-of-concerns"], "type": "principle", "scope": [ "module", "package", "component", "system" ], "requires": [ "Explicit Boundaries", "Abstraction" ], "reinforces": [ "SRP", "Modularity", "Layered Architecture" ], "enables": [ "Maintainability", "Replaceability" ], "conflicts_with": [ "Cross-Cutting Leakage", "Mixed Layers" ], "tensions_with": ["Over-Layering"], "violated_by": ["lexicon:mixed-layers"], "detected_by": [ "layer imports", "mixed naming roles", "cross-boundary logic" ], "measured_by": [ "dependency direction", "layer purity", "concern overlap" ], "refactored_by": [ "lexicon:extract-module", "lexicon:move-behavior-to-its-owner", "lexicon:define-module-boundaries" ], "enforced_by": [ "import rules", "dependency graph checks" ], "severity": "mandatory", "exemplar": { "before": "function handleFoo(request: Request) {\n const foo = JSON.parse(request.body);\n fooDb.insert(foo);\n return `