Komposition vor Vererbung anwenden
Schnellstart
- Die Variationsachse identifizieren: Datenvariante, Algorithmus, querschnittliches Verhalten oder Framework-Einschränkung.
- Standardmäßig Komposition verwenden, es sei denn, Vererbung ist durch Substituierbarkeit und Stabilität explizit gerechtfertigt.
- Wenn die Variantenmenge geschlossen und datenförmig ist, einem ADT/versiegelten Typ gegenüber offener Vererbung den Vorzug geben.
- Einen konkreten Migrationsplan mit Tests, Rollout-Reihenfolge und Überprüfungspunkten erstellen.
Referenznavigation (gestaffelte Offenlegung)
Nur die für die aktuelle Aufgabe benötigte Datei lesen:
- Grundlagen und Mechanismuswahl → references/01-foundations-and-decision-making.md
- ADTs, Kompositionsmuster, Frontend-Komposition → references/02-adts-patterns-and-frontend-composition.md
- Schrittweise Migration und Code-Review-Prüfungen → references/03-refactoring-and-review-checklist.md
- CI-Metriken, benutzerdefinierte statische Prüfungen, Team-Einführung → references/04-metrics-and-adoption.md
Standard-Workflow
-
Aktuelles Modell bewerten
- Basisklassen, Anzahl der Unterklassen, Hierarchietiefe und bekannte Problemstellen auflisten.
- Jede Variation als Datenvariante, Verhaltensstrategie oder Infrastrukturbelang markieren.
-
Mechanismus wählen (Standard zuerst)
- Komposition wählen für Verhaltensvariation, Austausch zur Laufzeit oder Änderung auf mehreren Achsen.
- ADT/versiegelten Typ wählen für geschlossene, datentragende Varianten, die eine erschöpfende Behandlung erfordern.
- Vererbung nur wählen, wenn alle Bedingungen zutreffen: echte Ist-ein-Beziehung, Liskov-konforme Substituierbarkeit und stabile Hierarchie.
-
Zielstruktur entwerfen
- Minimale Kollaborateur-Verträge definieren; Schnittstellen/Protokolle einführen, wo Flüchtigkeit, mehrere Implementierungen oder unabhängige Tests dies rechtfertigen.
- Konstruktorinjektion für erforderliche Kollaborateure verwenden.
- Vererbungstiefe flach halten (Ziel ≤2 unter unvermeidlichen Framework-Basen).
-
Migration inkrementell planen
- Zuerst Charakterisierungstests hinzufügen.
- Eine Nahtstelle (Schnittstelle/Fassade) einführen, bevor interne Teile ersetzt werden.
- Jeweils einen Unterklassenpfad migrieren.
- Tote Hierarchieteile erst entfernen, wenn Paritätstests bestanden sind.
-
Validieren und absichern
- Checklisten-gesteuertes Review durchführen.
- CI-Metriken/Prüfungen für DIT, Überschreibungsverhältnis und Dekorierertiefe hinzufügen.
- Explizite Ausnahmen für framework-erforderte Vererbung festhalten.
Nicht verhandelbare Standards
- Standardmäßig Komposition bevorzugen.
- Vererbung nicht nur zur Wiederverwendung von Code einführen.
- Kollaborateur-Schnittstellen schmal halten.
- Service-Locator-Muster vermeiden; Abhängigkeiten müssen explizit sein.
- Tiefe Dekoriererstapel (>3) und breite Vererbungsbäume als Design-Gerüche behandeln.
Ausgabe-Vertrag
Wenn um Beratung gebeten wird, diese Abschnitte in der angegebenen Reihenfolge zurückgeben:
- Entscheidung: Komposition, ADT oder Vererbung.
- Warum: Kopplung, Änderungsachse, Laufzeitanforderungen und Auswirkungen auf die Testbarkeit.
- Entwurfsskizze: Ziel-Schnittstellen/-Typen und Kompositionswurzel.
- Migrationsschritte: Kleine umkehrbare Schritte mit Validierungspunkten.
- Review-/CI-Prüfungen: Checklistenpunkte und messbare Schwellwerte.
Randfälle
- Framework-erzwungene Vererbung: Vererbung an der Grenze belassen; intern komponieren.
- Sprache fehlt Delegationssyntaktik: Kleine Hilfsgeneratoren/Vorlagen für die Weiterleitung verwenden.
- Leistungskritische Pfade: Dispatch-Overhead messen, bevor Indirektion hinzugefügt wird.
- Winzige stabile Domänen: Versiegelte Vererbung kann akzeptabel sein, wenn Erschöpfung erforderlich ist.
Beispiel
Eingabe: „Wir haben BaseReport mit 12 Unterklassen und jedes neue Format fügt eine weitere Unterklasse hinzu. Was sollen wir tun?“
Ausgabe (Form):
- Entscheidung: Hierarchie durch Komposition ersetzen (Strategy + optional Decorator).
- Begründung: Mehrdimensionale Variation und überschreibungsintensive Unterklassen deuten auf Taxonomie-Drift hin.
- Entwurfsskizze:
ReportRenderer,HeaderPolicy,FooterPolicy,OutputFormatter-Schnittstellen, komponiert in einemReportService. - Migration: Charakterisierungstests → Strategy-Extraktion → Migration pro Unterklasse → Löschen der Unterklassen.
- Absicherungen: DIT-Warnung >3, Überschreibungsverhältnis-Warnung >0.5, Dekorierertiefe-Warnung >3.