God Base Component – Evolutionsmuster und Zerfall
Einordnung
Die „God Base Component“ entsteht selten aus schlechter Absicht.
Sie beginnt fast immer mit einer sinnvollen Idee:
„Wir wollen Code wiederverwenden.“
Was folgt, ist jedoch häufig eine schleichende architektonische Erosion.
Dieses Dokument beschreibt das typische Evolutionsmuster – und warum es im Angular-Frontend besonders gefährlich ist.
1. Phase 1 – Das harmlose Hilfskonstrukt
Ausgangspunkt ist meist Subscription-Handling:
export abstract class DestroyableComponent {
protected destroy$ = new Subject<void>();
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
Alle Komponenten erben:
export class UserComponent extends DestroyableComponent {}
Ziel:
- weniger Boilerplate
- einheitliches Unsubscribe-Handling
Noch kein Problem.
2. Phase 2 – Erste Erweiterungen
Neue Anforderungen kommen:
- Loading-Indikator
- Globales Error-Handling
- Logging
Basisklasse wächst:
protected loading = false;
protected handleError(error: unknown) {
this.loading = false;
console.error(error);
}
Argument:
„Das brauchen doch alle Komponenten.“
Die Kopplung steigt – aber noch fühlt es sich effizient an.
3. Phase 3 – Querschnittslogik sammelt sich
Weitere Features:
- Permissions
- Routing-Helper
- Feature-Flags
- Analytics-Tracking
- Translation-Helper
Die Basisklasse wird zum Infrastruktur-Hub.
Komponenten erben plötzlich:
- Zustand
- Services
- Lifecycle-Logik
- UI-Verhalten
Die Hierarchie stabilisiert sich.
Der Schaden wird unsichtbar.
4. Phase 4 – Implizite Abhängigkeiten
Komponenten wissen nicht mehr:
- woher loading kommt
- wer error setzt
- welche Hooks wann laufen
- welche Seiteneffekte passieren
Änderungen an der Basisklasse:
→ betreffen alle Komponenten.
Regression-Risiko steigt exponentiell.
5. Phase 5 – Architektur-Zerfall
Typische Symptome:
- Basisklasse > 500 Zeilen
- protected-Felder überall
- Super-Calls in Lifecycle-Hooks
- schwer testbare Komponenten
- implizite Seiteneffekte
Neue Entwickler brauchen:
mentales Mapping der gesamten Vererbungskette
Die UI wird hierarchisch statt flach.
6. Warum das im Angular-Frontend besonders kritisch ist
Angular ist:
- deklarativ
- reaktiv
- datenflussgetrieben
Die God Base Component hingegen:
- organisiert Verhalten hierarchisch
- kapselt implizite Logik
- erzeugt Kontrollfluss über Vererbung
Das widerspricht dem Paradigma des Frameworks.
7. Technische Nebenwirkungen
7.1 Lifecycle-Komplexität
ngOnInit() {
super.ngOnInit();
}
Oder schlimmer: Hooks werden überschrieben oder vergessen.
Lifecycle wird fragil.
7.2 Testbarkeit sinkt
Tests müssen:
- Basisklasse verstehen
- implizite Logik berücksichtigen
- Side-Effects isolieren
Isolation wird schwierig.
7.3 Refactoring wird riskant
Änderung an der Basisklasse:
→ beeinflusst alle Komponenten
→ oft ohne direkte Sichtbarkeit
7.4 Kopplung steigt systemisch
Alle Komponenten hängen an:
- gleicher Struktur
- gleicher Infrastruktur
- gleicher Lifecycle-Strategie
Das System wird monolithisch im Frontend.
8. Warum dieses Muster entsteht
Häufige Ursachen:
- Imperatives Subscription-Handling
- OOP-geprägtes Denken
- Wunsch nach DRY
- fehlende Kompositionsmuster
- Unkenntnis moderner Angular-Features
Die Basisklasse löst kurzfristig Boilerplate – vergrößert langfristig Systemkomplexität.
9. Der Paradigmenkonflikt
Vererbung ist:
- hierarchisch
- identitätsorientiert
- strukturell
Reaktive UI-Architektur ist:
- flach
- kompositorisch
- datenflussbasiert
Die God Base Component ist ein Versuch, ein hierarchisches Modell in ein flaches System zu pressen.
10. Der bessere Weg
10.1 Built-in Lifecycle-Tools
takeUntilDestroyed()asyncPipe- Signals
10.2 Komposition statt Hierarchie
Statt:
extends BaseComponent
besser:
- Utility-Funktionen
- RxJS-Operatoren
- Services mit klarer Verantwortung
- Signal-basierte Ableitung
10.3 Infrastruktur entkoppeln
- Logging-Service
- Error-Interceptor
- Route-Guard
- Feature-Service
Nicht:
- Basisklassen-Akkumulation
11. Architekturregel
UI-Hierarchien sollen Templates strukturieren, nicht Infrastruktur vererben.
12. Kernaussage
Die God Base Component entsteht:
- aus Wiederverwendungsabsicht
- aus Imperativ-Reflexen
- aus OOP-Gewohnheit
Sie endet in:
- versteckter Kopplung
- wachsender Komplexität
- sinkender Wartbarkeit
- architektonischer Fragilität
Reaktive Frontends benötigen:
- flache Struktur
- explizite Komposition
- sichtbaren Datenfluss
- minimale Hierarchie