|
| 1 | += Workflow-Anpassung für Brownfield-Projekte |
| 2 | +Ralf D. Müller |
| 3 | +2026-03-31 |
| 4 | +:toc: |
| 5 | +:toc-placement: preamble |
| 6 | + |
| 7 | +== Einleitung |
| 8 | + |
| 9 | +Du hast den link:#/workflow[Greenfield-Workflow] gemeistert. |
| 10 | +Jetzt willst du ihn auf eine bestehende Codebasis anwenden. |
| 11 | + |
| 12 | +Die Grundprinzipien bleiben gleich: kleine Schritte, hohe Autonomie, Fehlerkorrektur-Schleifen. |
| 13 | +Aber Brownfield-Projekte bringen eine Herausforderung, die Greenfield-Projekte nicht haben: *das System existiert bereits*. |
| 14 | +Man kann nicht bei null anfangen. |
| 15 | +Man muss verstehen, was da ist, bevor man etwas ändert. |
| 16 | + |
| 17 | +Dieses Dokument beschreibt, wie man eine bestehende Codebasis in den Spec-Driven-Workflow überführt. |
| 18 | +Die zentrale Erkenntnis stammt aus Simon Martinellis https://unifiedprocess.ai/[AI Unified Process]: *Man muss nicht das gesamte System spezifizieren*. |
| 19 | +Man arbeitet einen Bounded Context nach dem anderen. |
| 20 | +Die Spec-Abdeckung wächst inkrementell, Feature für Feature. |
| 21 | + |
| 22 | +== Das Brownfield-Paradox |
| 23 | + |
| 24 | +Bei Greenfield-Projekten schreibt man zuerst die Spec, dann folgt der Code. |
| 25 | +Bei Brownfield-Projekten existiert der Code bereits -- aber die Spec oft nicht. |
| 26 | +Das System *ist* die Spezifikation, nur kann sie niemand lesen. |
| 27 | + |
| 28 | +Die Versuchung ist groß, das gesamte System vor jeder Änderung in Dokumentation zu überführen. |
| 29 | +Das ist Big Upfront Documentation, und es scheitert aus denselben Gründen wie Big Upfront Design. |
| 30 | + |
| 31 | +Stattdessen: Nur den Bounded Context spezifizieren, den man gerade ändern will, und auch nur so viel, wie für eine sichere Änderung nötig ist. |
| 32 | + |
| 33 | +== Phase 0: Bounded Context eingrenzen |
| 34 | + |
| 35 | +Vor jeder Code-Änderung den Bereich identifizieren, der geändert werden soll. |
| 36 | + |
| 37 | +Ein Bounded Context ist ein zusammenhängender Ausschnitt des Systems mit klaren Grenzen. |
| 38 | +Das kann ein Modul sein, ein Service, ein Feature-Bereich oder ein Bildschirm. |
| 39 | +Die Grenzen sollten klein genug sein, dass man den Kontext in einer einzigen Session verstehen kann. |
| 40 | + |
| 41 | +⚓ link:#/anchor/domain-driven-design[Domain-Driven Design] nutzen, um die Kontextgrenzen zu identifizieren. |
| 42 | +Die KI kann dabei helfen: auf den Code zeigen und nach Bounded Contexts und deren Schnittstellen fragen. |
| 43 | + |
| 44 | +.Prompt |
| 45 | +---- |
| 46 | +Analyze the codebase in src/. Identify bounded contexts using Domain-Driven Design. |
| 47 | +For each context, list: name, responsibility, key entities, interfaces to other contexts. |
| 48 | +Present as a table. |
| 49 | +---- |
| 50 | + |
| 51 | +Einen Bounded Context zum Starten auswählen. |
| 52 | +Einen wählen, der klein, gut isoliert ist und eine anstehende Änderungsanforderung hat. |
| 53 | + |
| 54 | +== Phase 0.5: Sicherheitsnetz aufbauen |
| 55 | + |
| 56 | +Vor jeder Änderung braucht man zwei Dinge: Verständnis und Tests. |
| 57 | + |
| 58 | +=== Bestehendes Verhalten als Use Cases extrahieren |
| 59 | + |
| 60 | +Die KI den Code im Bounded Context lesen lassen und extrahieren, was das System aktuell tut. |
| 61 | +Das Ergebnis sind Use Cases, die das *bestehende* Verhalten beschreiben -- nicht was man bauen will, sondern was bereits da ist. |
| 62 | + |
| 63 | +.Prompt |
| 64 | +---- |
| 65 | +Read the code in [bounded context path]. Extract the existing behavior as Use Cases. |
| 66 | +For each Use Case: ID, Trigger, Actors, Preconditions, Main Flow, Alternative Flows, Postconditions, Business Rules. |
| 67 | +Save as docs/specs/use-cases-[context-name].adoc. |
| 68 | +---- |
| 69 | + |
| 70 | +Die extrahierten Use Cases gegen das laufende System prüfen. |
| 71 | +Die KI kann implizites Verhalten übersehen oder Code falsch interpretieren. |
| 72 | +Das ist der eine Schritt, bei dem Domänenwissen unersetzlich ist. |
| 73 | + |
| 74 | +=== Basis-Tests aufbauen |
| 75 | + |
| 76 | +Tests schreiben, die das bestehende Verhalten verifizieren. |
| 77 | +Diese Tests sind das Sicherheitsnetz: Wenn eine Änderung etwas kaputt macht, fangen die Tests es ab. |
| 78 | + |
| 79 | +.Prompt |
| 80 | +---- |
| 81 | +Based on the Use Cases in docs/specs/use-cases-[context-name].adoc, write tests that verify the current behavior. |
| 82 | +Use TDD, London School. Each test references its Use Case ID for traceability. |
| 83 | +Do not change any production code. Only add tests. |
| 84 | +---- |
| 85 | + |
| 86 | +Tests ausführen. |
| 87 | +Jeder Test muss gegen den aktuellen Code bestehen. |
| 88 | +Wenn ein Test fehlschlägt, war der extrahierte Use Case falsch -- Use Case korrigieren, dann Test korrigieren. |
| 89 | + |
| 90 | +[IMPORTANT] |
| 91 | +==== |
| 92 | +Basis-Tests nicht überspringen. |
| 93 | +Ohne sie kann man nicht unterscheiden zwischen "meine Änderung hat etwas kaputt gemacht" und "es war schon vorher kaputt". |
| 94 | +Das ist die geschlossene Schleife, die Brownfield-Änderungen sicher macht. |
| 95 | +==== |
| 96 | + |
| 97 | +== Phase 1-12: Der Standard-Workflow |
| 98 | + |
| 99 | +Sobald Use Cases und Basis-Tests für den Bounded Context vorhanden sind, greift der normale Workflow. |
| 100 | + |
| 101 | +* *Neue Features* bekommen neue Use Cases, neue Akzeptanzkriterien und neue Tests -- genau wie bei Greenfield. |
| 102 | +* *Bug Fixes* beginnen damit, den verletzten Use Case zu identifizieren, dann folgt der TDD-Bug-Fix-Loop (Schritt 12). |
| 103 | +* *Refactoring* ist durch die Basis-Tests abgesichert. Solange die Tests grün bleiben, ist das Refactoring sicher. |
| 104 | + |
| 105 | +Der einzige Unterschied: Die arc42-Dokumentation ist vielleicht anfangs unvollständig. |
| 106 | +Das ist in Ordnung. |
| 107 | +Die Architektur-Abschnitte ausfüllen, während man das System kennenlernt. |
| 108 | +Nach ein paar Bounded Contexts deckt die Architekturdokumentation die relevanten Teile ab. |
| 109 | + |
| 110 | +== Inkrementelle Erweiterung |
| 111 | + |
| 112 | +Nach dem ersten Bounded Context den nächsten auswählen. |
| 113 | +Jeder eingeführte Kontext erweitert die Spec-Abdeckung des Systems. |
| 114 | + |
| 115 | +Mit der Zeit ergibt sich ein Muster: |
| 116 | + |
| 117 | +[cols="1,3"] |
| 118 | +|=== |
| 119 | +|Iteration |Abdeckung |
| 120 | + |
| 121 | +|Erster Kontext |
| 122 | +|Ein Feature-Bereich hat Use Cases, Tests und Architekturdokumentation. |
| 123 | + |
| 124 | +|3-5 Kontexte |
| 125 | +|Der Kern des Systems ist dokumentiert. Querschnittsthemen werden sichtbar. |
| 126 | + |
| 127 | +|10+ Kontexte |
| 128 | +|Die meisten Änderungen passieren in Bereichen mit bestehenden Specs. Neue Arbeit fühlt sich an wie Greenfield. |
| 129 | +|=== |
| 130 | + |
| 131 | +100% Abdeckung ist nicht nötig. |
| 132 | +Das Ziel ist, die Bereiche abzudecken, die sich am häufigsten ändern. |
| 133 | +Stabiler Code, den niemand anfasst, braucht keine Specs. |
| 134 | + |
| 135 | +== Prompt Cheat Sheet: Brownfield |
| 136 | + |
| 137 | +[cols="1,3,2"] |
| 138 | +|=== |
| 139 | +|Phase |Prompt |Anker |
| 140 | + |
| 141 | +|Scope |
| 142 | +|`Analyze the codebase in [path]. Identify bounded contexts using DDD. List name, responsibility, entities, interfaces.` |
| 143 | +|link:#/anchor/domain-driven-design[DDD] |
| 144 | + |
| 145 | +|Reverse-Engineering |
| 146 | +|`Read the code in [path]. Extract existing behavior as Use Cases with Trigger, Main Flow, Alternative Flows, Postconditions, Business Rules.` |
| 147 | +|{empty}-- |
| 148 | + |
| 149 | +|Basis-Tests |
| 150 | +|`Write tests for the Use Cases in [spec file]. Each test references its Use Case ID. Do not change production code.` |
| 151 | +|link:#/anchor/tdd-london-school[TDD London] / link:#/anchor/tdd-chicago-school[Chicago] |
| 152 | + |
| 153 | +|Weiter |
| 154 | +|Ab hier dem link:#/workflow[Standard-Workflow] ab Schritt 3 (PRD) oder Schritt 8 (Implementierung) folgen, je nachdem ob neue Features oder Bugs bearbeitet werden. |
| 155 | +|{empty}-- |
| 156 | +|=== |
| 157 | + |
| 158 | +== Wann dieser Ansatz nicht passt |
| 159 | + |
| 160 | +Dieser Workflow setzt voraus, dass man das bestehende System *weiterentwickeln* will. |
| 161 | +Wer einen kompletten Neubau plant, nimmt stattdessen den Greenfield-Workflow. |
| 162 | + |
| 163 | +Er setzt auch voraus, dass der bestehende Code lauffähig ist. |
| 164 | +Wenn das System nicht gebaut oder gestartet werden kann, liegt ein anderes Problem vor -- das zuerst lösen. |
| 165 | + |
| 166 | +== Weiterführende Literatur |
| 167 | + |
| 168 | +* Simon Martinelli, https://unifiedprocess.ai/[AI Unified Process] -- der Bounded-Context-Ansatz für Spec-Driven Development in bestehenden Systemen. |
| 169 | +* Eric Evans, https://www.domainlanguage.com/ddd/[Domain-Driven Design] -- das grundlegende Werk zu Bounded Contexts und strategischem Design. |
| 170 | +* Michael Feathers, _Working Effectively with Legacy Code_ -- Techniken zum Aufbau von Testabdeckung in Systemen ohne Tests. |
0 commit comments