Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions docs/all-anchors.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
64 changes: 64 additions & 0 deletions docs/anchors/iosp.adoc
Original file line number Diff line number Diff line change
@@ -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*:

* <<single-level-of-abstraction-principle,Single Level of Abstraction Principle (SLAP)>> - IOSP naturally enforces SLAP: integrations are high-level, operations are low-level
* <<solid-principles,SOLID Principles>> - IOSP applies SRP at the function level and can reduce the need for DIP
* <<solid-srp,SOLID SRP>> - IOSP is a *special case* of SRP applied at the function level, separating the responsibility of "what to compute" from "how to compose"
* <<cohesion-criteria,Cohesion Criteria>> - IOSP produces functional cohesion by dedicating each function to a single kind of work (either logic or composition)
* <<grasp,GRASP>> - GRASP's "High Cohesion" and "Low Coupling" are structurally supported by IOSP's tree-like composition
* <<solid-dip,SOLID DIP>> - IOSP can replace DIP for the purpose of testability; DIP is retained only for genuine alternative implementations
* <<clean-architecture,Clean Architecture>> - Layered abstraction at architecture scale mirrors IOSP's function-level separation
====
64 changes: 64 additions & 0 deletions docs/anchors/iosp.de.adoc
Original file line number Diff line number Diff line change
@@ -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*:

* <<single-level-of-abstraction-principle,Single Level of Abstraction Principle (SLAP)>> - IOSP setzt SLAP natürlich durch: Integrationen sind high-level, Operationen sind low-level
* <<solid-principles,SOLID Principles>> - IOSP wendet SRP auf Funktionsebene an und reduziert die Notwendigkeit von DIP
* <<solid-srp,SOLID SRP>> - IOSP ist ein *Spezialfall* von SRP auf Funktionsebene, der die Verantwortung von "was berechnet werden soll" von "wie komponiert werden soll" trennt
* <<cohesion-criteria,Kohäsionskriterien>> - IOSP erzeugt funktionale Kohäsion, indem es jede Funktion einer einzigen Arbeitsart widmet (entweder Logik oder Komposition)
* <<grasp,GRASP>> - GRASPs "Hohe Kohäsion" und "Niedrige Kopplung" werden durch IOSP's baumartige Komposition strukturell unterstützt
* <<solid-dip,SOLID DIP>> - IOSP kann DIP für den Zweck der Testbarkeit ersetzen; DIP bleibt nur für echte alternative Implementierungen erhalten
* <<clean-architecture,Clean Architecture>> - Geschichtete Abstraktion auf Architekturebene spiegelt IOSP's Trennung auf Funktionsebene wider
====
10 changes: 10 additions & 0 deletions docs/changelog.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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:*
Expand Down
8 changes: 8 additions & 0 deletions docs/metadata/roles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 5 additions & 0 deletions skill/semantic-anchor-translator/references/catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading