diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c81e8794..f45637d2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: files: \.adoc$ pass_filenames: true args: [--format, console, --config, .asciidoc-linter.yml] - stages: [commit] + stages: [pre-commit] # Trailing whitespace - repo: https://github.com/pre-commit/pre-commit-hooks diff --git a/docs/all-anchors.adoc b/docs/all-anchors.adoc index efa2d6e9..d9491342 100644 --- a/docs/all-anchors.adoc +++ b/docs/all-anchors.adoc @@ -109,6 +109,8 @@ include::anchors/kiss-principle.adoc[leveloffset=+2] include::anchors/single-level-of-abstraction-principle.adoc[leveloffset=+2] +include::anchors/iosp.adoc[leveloffset=+2] + include::anchors/solid-dip.adoc[leveloffset=+2] include::anchors/solid-isp.adoc[leveloffset=+2] diff --git a/docs/anchors/iosp.adoc b/docs/anchors/iosp.adoc new file mode 100644 index 00000000..2c687b21 --- /dev/null +++ b/docs/anchors/iosp.adoc @@ -0,0 +1,64 @@ += Integration Operation Segregation Principle (IOSP) +:categories: design-principles +:roles: software-developer, software-architect, consultant, educator +:related: single-level-of-abstraction-principle, solid-principles, solid-srp, cohesion-criteria, grasp, solid-dip, clean-architecture +:proponents: Ralf Westphal, Stefan Lieser +:tags: iosp, integration, operation, testability, flow-design, function-design, clean-code, functional-dependency +:tier: 2 + +[%collapsible] +==== +Full Name:: Integration Operation Segregation Principle + +Also known as:: IOSP, Integration-Operation Separation, N+1 Principle + +[discrete] +== *Core Concepts*: + +Core rule:: +Functions shall either only contain logic or they shall only call other functions — never both. + +Operation:: A function that contains logic but calls no other functions of the same solution. Logic includes transformations (`x + 2`), control structures (`if`, `for`, `while`), and third-party API calls (`Console.WriteLine`, `httpClient.Send()`). Operations are the *leaves* of the function tree — they have no functional dependencies on other code of the same codebase. + +Integration:: A function that calls other functions (operations or other integrations) but contains *no logic itself*. Its sole responsibility is composing lower-level functions into a coherent whole. Integrations are the *branches* of the function tree — they orchestrate, they do not compute. + +Hybrid:: A function that violates IOSP by mixing both logic and calls to other functions. Hybrids are the primary source of poor testability: the logic cannot be tested in isolation without mocking the called functions, and the calling structure cannot be understood without reading the embedded logic. + +Why it works:: +A reader encountering an integration can trust it to be a *readable summary* of the work at that level — pure orchestration without hidden decisions. An operation, conversely, contains only detailed logic — no distracting jumps to other parts of the codebase. This natural enforcement of the Single Level of Abstraction Principle (SLAP) is the key insight: IOSP makes SLAP *automatic* rather than aspirational. + +How it relates to DIP (Dependency Inversion Principle):: +Code that follows DIP often creates hybrids: a method both contains domain logic *and* calls abstractions (interfaces) that represent integrations. IOSP argues that these two responsibilities — logic and integration — should be separated into different functions. The result: operations no longer depend on abstractions, integrating functions do the wiring instead. This reduces the need for DIP and Dependency Injection significantly; DIP is retained only for genuine cases of alternative implementations, not for testability. + +Testability implications:: +Operations are trivially unit-testable — they have no functional dependencies that require mocking. Integrations contain no logic, so there is nothing to unit-test; integration tests verify the wiring. This is a categorical improvement over hybrid code, where every test requires mock setup for the called functions. + +Codebase structure:: +Following IOSP produces a strict tree structure: integrations form the upper layers (high abstraction, no logic), operations form the leaves (low abstraction, all logic). There are no functional dependencies — only "empty" dependencies from integrations to the functions they call. This makes the data flow visible and the graph acyclic by construction. + +Key Proponents:: +Ralf Westphal ("Integration Operation Segregation Principle (IOSP)", 2022 — substack; "IOSP 2.0", 2023; "Radical Object-Orientation #06", 2024), Stefan Lieser ("Three Questions about the IOSP", t2informatik interview, 2025; Clean Code Developer Initiative / CCD Akademie). Both are co-founders of the Clean Code Developer Initiative (2008). + +[discrete] +== *When to Use*: + +* Refactoring hybrid functions that mix high-level orchestration with low-level details — IOSP tells you *how* to split, not just *that* you should +* TDD: structuring code so that operations emerge naturally as testable leaves, with integrations as trivial wiring +* Code review: a concrete, checkable rule — a function either calls other functions *or* contains logic, never both. If a reviewer spots a hybrid, it's a clear finding +* Teaching clean code: unlike SRP (which is often debated), IOSP is *crystal clear at a glance* — there is no interpretation question +* Reducing DIP/IoC complexity: if the only reason for DIP is testability, IOSP eliminates that need +* Architecture design with IODA (Integration-Operation-Data-API): IOSP scales to module level, producing dependency-free operational modules composed by integration modules +* Designing data flows: integrations become explicit "ditch-diggers" for data to flow between operations +* .NET development with IospAnalyzer: automated Roslyn Analyzer catches IOSP violations at compile time + +[discrete] +== *Related Anchors*: + +* <> - IOSP naturally enforces SLAP: integrations are high-level, operations are low-level +* <> - IOSP applies SRP at the function level and can reduce the need for DIP +* <> - IOSP is a *special case* of SRP applied at the function level, separating the responsibility of "what to compute" from "how to compose" +* <> - IOSP produces functional cohesion by dedicating each function to a single kind of work (either logic or composition) +* <> - GRASP's "High Cohesion" and "Low Coupling" are structurally supported by IOSP's tree-like composition +* <> - IOSP can replace DIP for the purpose of testability; DIP is retained only for genuine alternative implementations +* <> - Layered abstraction at architecture scale mirrors IOSP's function-level separation +==== diff --git a/docs/anchors/iosp.de.adoc b/docs/anchors/iosp.de.adoc new file mode 100644 index 00000000..958915f0 --- /dev/null +++ b/docs/anchors/iosp.de.adoc @@ -0,0 +1,64 @@ += Integration Operation Segregation Principle (IOSP) +:categories: design-principles +:roles: software-developer, software-architect, consultant, educator +:related: single-level-of-abstraction-principle, solid-principles, solid-srp, cohesion-criteria, grasp, solid-dip, clean-architecture +:proponents: Ralf Westphal, Stefan Lieser +:tags: iosp, integration, operation, testbarkeit, flow-design, funktionsdesign, clean-code, funktionale-abhaengigkeit +:tier: 2 + +[%collapsible] +==== +Vollständiger Name:: Integration Operation Segregation Principle + +Auch bekannt als:: IOSP, Integrations-Operations-Trennung, N+1-Prinzip + +[discrete] +== *Kernkonzepte*: + +Grundregel:: +Funktionen sollen entweder nur Logik enthalten oder nur andere Funktionen aufrufen — niemals beides. + +Operation:: Eine Funktion, die Logik enthält, aber keine anderen Funktionen derselben Lösung aufruft. Logik umfasst Transformationen (`x + 2`), Kontrollstrukturen (`if`, `for`, `while`) und API-Aufrufe von Drittanbietern (`Console.WriteLine`, `httpClient.Send()`). Operationen sind die *Blätter* des Funktionsbaums — sie haben keine funktionalen Abhängigkeiten zu anderem Code derselben Codebasis. + +Integration:: Eine Funktion, die andere Funktionen aufruft (Operationen oder andere Integrationen), aber *selbst keine Logik enthält*. Ihre einzige Verantwortung ist die Komposition niedrigerer Funktionen zu einem kohärenten Ganzen. Integrationen sind die *Verzweigungen* des Funktionsbaums — sie orchestrieren, sie berechnen nicht. + +Hybrid:: Eine Funktion, die gegen IOSP verstößt, indem sie Logik und Funktionsaufrufe mischt. Hybride sind die Hauptursache schlechter Testbarkeit: Die Logik kann nicht isoliert getestet werden, ohne die aufgerufenen Funktionen zu mocken, und die Aufrufstruktur kann nicht verstanden werden, ohne die eingebettete Logik zu lesen. + +Warum es funktioniert:: +Ein Leser kann sich bei einer Integration darauf verlassen, dass sie eine *lesbare Zusammenfassung* der Arbeit auf dieser Ebene ist — reine Orchestrierung ohne versteckte Entscheidungen. Eine Operation hingegen enthält nur detaillierte Logik — keine ablenkenden Sprünge zu anderen Teilen der Codebasis. Diese natürliche Durchsetzung des Single Level of Abstraction Principle (SLAP) ist die Kern-Einsicht: IOSP macht SLAP *automatisch* statt wünschenswert. + +Beziehung zum DIP (Dependency Inversion Principle):: +Code, der DIP befolgt, erzeugt oft Hybride: Eine Methode enthält sowohl Domänenlogik *als auch* Aufrufe von Abstraktionen (Interfaces), die Integrationen darstellen. IOSP argumentiert, dass diese zwei Verantwortlichkeiten — Logik und Integration — in verschiedene Funktionen getrennt werden sollten. Das Ergebnis: Operationen hängen nicht mehr von Abstraktionen ab, integrierende Funktionen übernehmen stattdessen die Verschaltung. Dies reduziert die Notwendigkeit von DIP und Dependency Injection erheblich; DIP bleibt nur für echte Fälle alternativer Implementierungen erhalten, nicht für Testbarkeit. + +Auswirkungen auf die Testbarkeit:: +Operationen sind trivial unit-testbar — sie haben keine funktionalen Abhängigkeiten, die Mocking erfordern. Integrationen enthalten keine Logik, daher gibt es nichts zu unit-testen; Integrationstests verifizieren die Verschaltung. Dies ist eine grundlegende Verbesserung gegenüber Hybrid-Code, wo jeder Test Mock-Setup für die aufgerufenen Funktionen erfordert. + +Codebasis-Struktur:: +Die Befolgung von IOSP erzeugt eine strenge Baumstruktur: Integrationen bilden die oberen Schichten (hohe Abstraktion, keine Logik), Operationen bilden die Blätter (niedrige Abstraktion, gesamte Logik). Es gibt keine funktionalen Abhängigkeiten — nur "leere" Abhängigkeiten von Integrationen zu den von ihnen aufgerufenen Funktionen. Dies macht den Datenfluss sichtbar und den Graphen per Konstruktion azyklisch. + +Schlüsselvertreter:: +Ralf Westphal ("Integration Operation Segregation Principle (IOSP)", 2022 — substack; "IOSP 2.0", 2023; "Radical Object-Orientation #06", 2024), Stefan Lieser ("Three Questions about the IOSP", t2informatik Interview, 2025; Clean Code Developer Initiative / CCD Akademie). Beide sind Mitbegründer der Clean Code Developer Initiative (2008). + +[discrete] +== *Wann zu verwenden*: + +* Refactoring von Hybrid-Funktionen, die High-Level-Orchestrierung mit Low-Level-Details mischen — IOSP sagt dir *wie* du zerlegen sollst, nicht nur *dass* du es solltest +* TDD: Code so strukturieren, dass Operationen natürlich als testbare Blätter entstehen, mit Integrationen als trivialer Verschaltung +* Code Review: eine konkrete, prüfbare Regel — eine Funktion ruft entweder andere Funktionen auf *oder* enthält Logik, niemals beides. Wenn ein Reviewer einen Hybriden entdeckt, ist das ein klarer Befund +* Clean Code lehren: im Gegensatz zu SRP (über das oft diskutiert wird) ist IOSP *auf einen Blick glasklar* — es gibt keine Interpretationsfrage +* Reduzierung von DIP/IoC-Komplexität: wenn der einzige Grund für DIP die Testbarkeit ist, eliminiert IOSP diese Notwendigkeit +* Architektur-Design mit IODA (Integration-Operation-Data-API): IOSP skaliert auf Modulebene und erzeugt abhängigkeitsfreie operationale Module, die von Integrationsmodulen komponiert werden +* Datenflüsse entwerfen: Integrationen werden zu expliziten "Grabenbaggern" für Daten, die zwischen Operationen fließen +* .NET-Entwicklung mit IospAnalyzer: automatisierter Roslyn Analyzer erkennt IOSP-Verstöße zur Compilezeit + +[discrete] +== *Verwandte Anker*: + +* <> - IOSP setzt SLAP natürlich durch: Integrationen sind high-level, Operationen sind low-level +* <> - IOSP wendet SRP auf Funktionsebene an und reduziert die Notwendigkeit von DIP +* <> - IOSP ist ein *Spezialfall* von SRP auf Funktionsebene, der die Verantwortung von "was berechnet werden soll" von "wie komponiert werden soll" trennt +* <> - IOSP erzeugt funktionale Kohäsion, indem es jede Funktion einer einzigen Arbeitsart widmet (entweder Logik oder Komposition) +* <> - GRASPs "Hohe Kohäsion" und "Niedrige Kopplung" werden durch IOSP's baumartige Komposition strukturell unterstützt +* <> - IOSP kann DIP für den Zweck der Testbarkeit ersetzen; DIP bleibt nur für echte alternative Implementierungen erhalten +* <> - Geschichtete Abstraktion auf Architekturebene spiegelt IOSP's Trennung auf Funktionsebene wider +==== diff --git a/docs/changelog.adoc b/docs/changelog.adoc index 930d81ec..8ecdecad 100644 --- a/docs/changelog.adoc +++ b/docs/changelog.adoc @@ -2,6 +2,16 @@ A chronological record of all semantic anchors added to the catalog. Community contributors are credited with thanks. +== 2026-06-03 + +*New anchors:* + +* *IOSP (Integration Operation Segregation Principle)* — a function shall either contain logic (Operation) or call other functions (Integration), but never both; the formal refinement of SRP at function level; separates integration (coordination/sequencing) from operation (business logic/computation); eliminates mock-heavy tests by avoiding new'ing in functions that contain logic; formally checkable via IospAnalyzer (Roslyn); reduces the need for Dependency Injection (DIP) at the function level (Ralf Westphal, 2022; Stefan Lieser, 2025; proposed by https://github.com/JensGrote[@JensGrote] in https://github.com/LLM-Coding/Semantic-Anchors/issues/556[#556]) + +*New contracts:* + +* *TDD, Hamburg Style* — Ralf Westphal's design-led TDD recipe: close the requirements/logic gap before writing code via the ACD cycle (Analyze → Design → Code), then test at service boundaries with minimal mocking; composes Red-Green-Refactor, London School, Chicago School, and IOSP (proposed by https://github.com/kuerm[@kuerm] in https://github.com/LLM-Coding/Semantic-Anchors/issues/557[#557], follows from https://github.com/LLM-Coding/Semantic-Anchors/issues/458[#458]) + == 2026-06-02 *New anchors:* diff --git a/docs/metadata/roles.yml b/docs/metadata/roles.yml index a7abeb20..84f4b9e7 100644 --- a/docs/metadata/roles.yml +++ b/docs/metadata/roles.yml @@ -156,6 +156,14 @@ domain-driven-design: - team-lead rationale: "Domain modeling approach; architects design bounded contexts, developers implement, BAs provide domain expertise, team leads facilitate ubiquitous language" +iosp: + roles: + - software-developer + - software-architect + - educator + - consultant + rationale: "Integration Operation Segregation Principle; developers write testable functions, architects design for separation, educators teach IOSP, consultants coach Clean Code practices" + # CATEGORY: Requirements Engineering problem-space-nvc: diff --git a/skill/semantic-anchor-translator/references/catalog.md b/skill/semantic-anchor-translator/references/catalog.md index f6f10e8a..b906e08f 100644 --- a/skill/semantic-anchor-translator/references/catalog.md +++ b/skill/semantic-anchor-translator/references/catalog.md @@ -269,6 +269,11 @@ Source: https://github.com/LLM-Coding/Semantic-Anchors - **Proponents:** Kent Beck, Robert C. Martin - **Core:** All statements inside a function should live at one abstraction level; mixing orchestration with mechanics is the main driver of unreadable code; refactor by extracting low-level details into named helpers so the outer function reads like a table of contents; formal expression of Beck's Composed Method pattern, codified as a Clean Code function-design rule by Martin +### IOSP (Integration Operation Segregation Principle) +- **Also known as:** IOSP, Ralf Westphal's IOSP +- **Proponents:** Ralf Westphal, Stefan Lieser +- **Core:** A function shall either contain logic (Operation) or call other functions (Integration), but never both; the formal refinement of SRP at function level; separates integration (coordination/sequencing) from operation (business logic/computation); eliminates mock-heavy tests by avoiding new'ing in functions that contain logic; formally checkable via IospAnalyzer (Roslyn); reduces the need for Dependency Injection (DIP) at the function level; narrows the Applicator/Alternator distinction in IODA Architecture + ### Code Smells - **Also known as:** Bad Smells in Code, Refactoring Smells - **Proponents:** Kent Beck (coined term), Martin Fowler, Robert C. Martin diff --git a/website/public/data/contracts.json b/website/public/data/contracts.json index 11579deb..2f529632 100644 --- a/website/public/data/contracts.json +++ b/website/public/data/contracts.json @@ -202,5 +202,16 @@ "template": "Writing follows Gutes Deutsch nach Wolf Schneider (or Plain English according to Strunk & White).\n\nAdditionally:\n- Technical terms stay in English (LLM, Prompt, Token, Spec, etc.)\n- Address the reader directly, use first person sparingly but deliberately\n- Use analogies to human thinking to explain technical concepts\n- One thought per paragraph (5-8 sentences is fine)\n- Section headings are statements, not topic announcements\n- First sentence says what the paragraph is about\n- Show code and prompts, don't just claim things work\n- Conclusions make a clear statement — never end with 'it remains exciting'", "templateDe": "Schreibstil folgt Gutes Deutsch nach Wolf Schneider (oder Plain English nach Strunk & White).\n\nZusätzlich:\n- Fachbegriffe auf Englisch lassen (LLM, Prompt, Token, Spec, etc.)\n- Leser direkt ansprechen, Ich-Perspektive sparsam aber gezielt\n- Analogien zum menschlichen Denken für technische Konzepte\n- Ein Gedanke pro Absatz (5-8 Sätze OK)\n- Zwischenüberschriften als Aussagen, nicht Themenankündigungen\n- Erster Satz sagt sofort worum es geht\n- Code/Prompts zeigen, nicht nur behaupten\n- Fazit: klare Aussage, kein 'es bleibt spannend'", "category": "communication" + }, + { + "id": "tdd-hamburg-style", + "title": "TDD, Hamburg Style", + "titleDe": "TDD, Hamburg Style", + "description": "Design-led TDD recipe by Ralf Westphal — close the requirements/logic gap before writing code, then test at service boundaries with minimal mocking", + "descriptionDe": "Design-geführtes TDD-Rezept nach Ralf Westphal — die Lücke zwischen Anforderungen und Logik vor dem Codieren schließen, dann an Servicegrenzen mit minimalem Mocking testen", + "anchors": ["red-green-tdd", "tdd-london-school", "tdd-chicago-school", "iosp"], + "template": "Design-led TDD recipe by Ralf Westphal — close the requirements/logic gap before writing code, then test at service boundaries with minimal mocking. Use it when the problem is too complex for pure micro-step Red-Green-Refactor.\n\n- **ACD cycle (Analyze → Design → Code)** precedes the test loop: first model the solution to close the gap between requirements and logic, only then code.\n- **\"Right from the start\" philosophy** — implement correctly the first time so refactoring is a correction, not routine cleanup.\n- **Service-level testing** — test behind the public API, independent of API technology.\n- **Minimal mocking** — closer to *TDD, Chicago School* than *London School*.\n- **IOSP (Integration Operation Segregation Principle)** — a function is either composition (Integration) or logic (Operation), never both; structural support for simple unit tests.\n- **Deep Work over Small Steps** — accept that some problems can't be sliced into tiny green increments; stay red longer when the design demands it.\n\nComposes: *TDD, London School*, *TDD, Chicago School*, *Red-Green-Refactor*, *IOSP*.\nSources: https://ralfw.de/hamburg-style-tdd/, https://ralfw.de/tdd-how-it-can-be-done-right/", + "templateDe": "Design-geführtes TDD-Rezept nach Ralf Westphal — die Lücke zwischen Anforderungen und Logik vor dem Codieren schließen, dann an Servicegrenzen mit minimalem Mocking testen. Anwenden, wenn das Problem zu komplex für reines micro-step Red-Green-Refactor ist.\n\n- **ACD-Zyklus (Analyze → Design → Code)** geht dem Test-Loop voraus: zuerst die Lösung modellieren, um die Lücke zwischen Anforderungen und Logik zu schließen, erst dann codieren.\n- **\"Right from the start\"-Philosophie** — beim ersten Mal korrekt implementieren, sodass Refactoring eine Korrektur ist, keine Routinebereinigung.\n- **Service-Level-Testing** — hinter der öffentlichen API testen, unabhängig von der API-Technologie.\n- **Minimales Mocking** — näher an *TDD, Chicago School* als an *London School*.\n- **IOSP (Integration Operation Segregation Principle)** — eine Funktion ist entweder Komposition (Integration) oder Logik (Operation), niemals beides; strukturelle Unterstützung für einfache Unit-Tests.\n- **Deep Work statt Small Steps** — akzeptieren, dass manche Probleme nicht in kleine grüne Inkremente zerlegt werden können; länger rot bleiben, wenn das Design es erfordert.\n\nKomponiert: *TDD, London School*, *TDD, Chicago School*, *Red-Green-Refactor*, *IOSP*.\nQuellen: https://ralfw.de/hamburg-style-tdd/, https://ralfw.de/tdd-how-it-can-be-done-right/", + "category": "development" } ]