Lektion 4.1.2 hat ein Wort eingeführt, das jetzt seine eigene Lektion bekommt: Fitnessfunktion, ein Test, der nicht eine Funktion prüft, sondern eine Qualität des Systems. Das erste Beispiel war Q6, „der Kern kennt kein Rahmenwerk“, als Test im Build. Lektion 4.3.6 hat daraus den Architekturtest gemacht, der die erlaubten Richtungen zwischen allen Modulen hält, und Lektion 4.10.6 („Vergleich, Architekturtests und Entscheidung“) hat ihn so erweitert, dass er den gewählten Stil der Code-Architektur hält.
Der Begriff kommt aus der Literatur zur evolutionären Architektur; bekannt gemacht hat ihn das Buch „Building Evolutionary Architectures“ von Neal Ford, Rebecca Parsons und Patrick Kua. Die Idee ist einfach: Eine Architektur bleibt nur so lange, wie etwas sie bei jeder Änderung prüft. Was nur in einem Dokument steht, verfällt beim dritten eiligen Pull Request.
Diese Lektion sammelt, was die Kladde schon prüft, ergänzt drei Arten von Prüfungen, die noch fehlen, und zieht eine Grenze: Was lässt sich
automatisch prüfen, und was bleibt Aufgabe eines Menschen? Am Ende stehen drei Qualitätsszenarien aus docs/quality-goals.md mit je einer
automatischen Prüfung in der Pipeline.
Was eine Fitness Function ist, und wann sie läuft
Eine Fitness Function hat drei Eigenschaften: Sie prüft ein Ziel der Architektur, nicht eine Funktion; ihr Ergebnis ist objektiv, bestanden oder nicht, oder eine Zahl mit Grenze; und sie läuft von selbst, wieder und wieder. Lektion 4.1.2 hat vier Arten der Prüfung unterschieden: Test im Build, Messung im Betrieb, Probe, Review. Fitness Functions sind die ersten beiden, und es lohnt sich, sie nach dem Zeitpunkt zu ordnen:
| Zeitpunkt | Wann | Gut für | Grenze |
|---|---|---|---|
| bei jedem Pull Request | Minuten, vor dem Zusammenführen | Struktur, Verträge, Abhängigkeiten, schnelle Messungen | muss schnell und stabil sein, sonst wird sie abgeschaltet |
| nach Zeitplan | nachts, wöchentlich, vor einer Auslieferung | Lasttests in Azure, lange Läufe, Prüfungen gegen eine laufende Umgebung | ein Fund kommt Stunden oder Tage nach der Änderung |
| dauernd im Betrieb | jede Minute bis jeden Tag | Antwortzeiten echter Anfragen, Fehlerquoten, Kosten | findet, was schon passiert ist |
Für die Kladde sieht die Sammlung so aus. Die Spalte „seit“ nennt die Lektion, die die Prüfung gebaut hat:
| Ziel | Prüfung | Zeitpunkt | seit |
|---|---|---|---|
| Q6 Der Kern kennt kein Rahmenwerk | Architekturtest: Domänenmodelle kennen nur .NET und den Shared Kernel | Pull Request | 4.1.2, 4.3.6 |
| Module begegnen sich nur über Verträge | Architekturtest ModuleRulesTests |
Pull Request | 4.3.6 |
| der gewählte Stil der Code-Architektur | erweiterte Architekturtests | Pull Request | 4.10.6 |
| jede Registrierung löst auf | Registrierungstest | Pull Request | 4.3.5 |
| gespeicherte Formate ändern sich nur abwärtskompatibel | goldene Beispieldateien | Pull Request | 4.4.6, 4.5.4 |
| die HTTP-Schnittstelle bricht keinen Aufrufer | Vertragstest: das OpenAPI-Dokument gegen die eingecheckte Fassung | Pull Request | K2 2.12.2 |
| Q2 Antwortzeit | Lasttest mit Fehlerkriterien in Azure Load Testing | auf Knopfdruck | K3 3.8.6 |
| Q2 Antwortzeit | p95 aus Application Insights, Alarm | Betrieb | 4.1.2 |
| Q5 Kosten je Büro | Budget mit Warnung auf die Prognose | Betrieb, täglich | 4.1.5, 4.7.7 |
| Q1 Büros sehen einander nie | Isolationstests | Pull Request | noch offen, gebaut im Abschlussprojekt |
Drei Lücken fallen auf. Es gibt keine Prüfung der Pakete, weder auf bekannte Sicherheitslücken noch auf ihre Lizenzen. Q2 wird im Pull Request gar nicht geprüft und sonst nur, wenn jemand den Lasttest startet. Und Q7, „schnelle Tests ohne Netz“, hat seit Lektion 4.1.2 den Vermerk „noch offen“. Die folgenden Abschnitte schließen diese Lücken, so weit es geht.