Elternklasse mit Referenzen auf Kindklasse
Beschreibung
Elternklasse mit Referenzen auf Kindklasse tritt auf, wenn eine Elternklasse eine Referenz oder einen Pointer auf eine Kindklasse enthält, entweder direkt oder indirekt durch eine andere Klasse. Dies erzeugt eine zirkulare Abhängigkeit zwischen Eltern- und Kindklassen und verletzt das Prinzip der Modularität und ordnungsgemäßer Vererbungshierarchien. Eine Elternklasse sollte ihre Kinder nicht kennen, da Kinder die Eltern erweitern - nicht umgekehrt. Dieses Anti-Pattern macht die Codebasis schwerer zu warten, zu erweitern und zu testen.
Risiko
Obwohl hauptsächlich ein Code-Qualitätsproblem, erzeugt dieses Muster indirekte Sicherheitsrisiken. Die zirkulare Abhängigkeit erschwert die ordnungsgemäße Prüfung von Sicherheitskontrollen, da Änderungen in Kindklassen unerwartet das Elternverhalten beeinflussen können. Unit-Tests werden kompliziert, was möglicherweise zu inadäquater Sicherheitstestabdeckung führt. Die enge Kopplung erschwert den Austausch oder das Upgrade sicherheitskritischer Komponenten. Code-Refactoring wird riskant, und Entwickler können notwendige Sicherheitsverbesserungen wegen der Komplexität vermeiden. Das Muster verletzt auch SOLID-Prinzipien (Open/Closed, Dependency Inversion), was die Codebasis fragiler macht.
Lösung
Wenden Sie das Dependency Inversion Principle an - High-Level-Module sollten nicht von Low-Level-Modulen abhängen, beide sollten von Abstraktionen abhängen. Verwenden Sie Interfaces oder abstrakte Klassen, um Verträge zu definieren, die Kindklassen implementieren. Wenden Sie das Factory-Pattern oder Dependency Injection an, um Instanzen ohne direkte Referenzen zu erstellen. Refaktorisieren Sie gemeinsame Funktionalität, die sowohl von Eltern als auch Kind benötigt wird, in separate Hilfsklassen. Verwenden Sie ereignisgesteuerte Architekturen oder Observer-Patterns, wenn Elternklassen auf Kindklassenaktionen reagieren müssen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Andere | Bereich: Ändere Reduzierte Wartbarkeit - Zirkulare Abhängigkeiten machen die Codebasis schwerer zu verstehen, zu testen und sicher zu modifizieren. |
| Andere | Bereich: Ändere Qualitätsverschlechterung - Enge Kopplung führt zu fragilem Code, wo Änderungen unerwartete Auswirkungen haben. |
| Andere | Bereich: Ändere Reduzierte Zuverlässigkeit - Testen wird schwieriger, was möglicherweise Fehler und Schwachstellen unentdeckt lässt. |
Beispielcode
Anfälliger Code
// Anfällig: Elternklasse referenziert Kindklasse direkt
public class VulnerableBaseDocument {
protected String content;
protected String author;
// Anfällig: Eltern kennt spezifische Kindklasse!
public VulnerablePDFDocument convertToPDF() {
// Elternklasse erstellt und gibt Kindklasseninstanz zurück
VulnerablePDFDocument pdf = new VulnerablePDFDocument();
pdf.setContent(this.content);
pdf.setAuthor(this.author);
pdf.generatePDF();
return pdf;
}
// Anfällig: Weitere Referenz auf Kindklasse
public VulnerableWordDocument convertToWord() {
VulnerableWordDocument word = new VulnerableWordDocument();
word.setContent(this.content);
word.setAuthor(this.author);
return word;
}
// Anfällig: Typprüfung für Kindklassen
public void process(VulnerableBaseDocument doc) {
if (doc instanceof VulnerablePDFDocument) {
((VulnerablePDFDocument) doc).compress();
} else if (doc instanceof VulnerableWordDocument) {
((VulnerableWordDocument) doc).applyStyles();
}
}
}
// Kindklassen
public class VulnerablePDFDocument extends VulnerableBaseDocument {
public void generatePDF() { /* ... */ }
public void compress() { /* ... */ }
}
public class VulnerableWordDocument extends VulnerableBaseDocument {
public void applyStyles() { /* ... */ }
}
// Probleme:
// 1. Hinzufügen neuer Dokumenttypen erfordert Modifikation der Elternklasse
// 2. Elternklasse ist eng an alle Kinder gekoppelt
// 3. Verletzt Open/Closed Principle
# Anfällig: Elternklasse mit Kindklassen-Imports
class VulnerableAnimal:
def __init__(self, name):
self.name = name
# Anfällig: Eltern erstellt Kindinstanzen
def create_offspring(self, offspring_type):
# Direkte Referenz auf Kindklassen im Eltern
if offspring_type == "dog":
from animals import VulnerableDog # Zirkularer Import!
return VulnerableDog(f"{self.name}'s Welpe")
elif offspring_type == "cat":
from animals import VulnerableCat # Zirkularer Import!
return VulnerableCat(f"{self.name}'s Kätzchen")
else:
raise ValueError(f"Unbekannter Typ: {offspring_type}")
# Anfällig: Typspezifische Logik im Eltern
def get_sound(self):
from animals import VulnerableDog, VulnerableCat
if isinstance(self, VulnerableDog):
return "Wuff!"
elif isinstance(self, VulnerableCat):
return "Miau!"
return "Unbekannt"
Korrigierter Code
// Korrigiert: Verwendung von Interfaces und Factory-Pattern
public abstract class FixedBaseDocument {
protected String content;
protected String author;
public abstract String getFormat();
// Korrigiert: Keine Referenzen auf Kindklassen
// Konvertierung durch separate Konverterklassen behandelt
public String getContent() {
return content;
}
public String getAuthor() {
return author;
}
public void setContent(String content) {
this.content = content;
}
public void setAuthor(String author) {
this.author = author;
}
}
// Korrigiert: Kindklassen sind unabhängig
public class FixedPDFDocument extends FixedBaseDocument {
@Override
public String getFormat() {
return "PDF";
}
public void generatePDF() { /* ... */ }
public void compress() { /* ... */ }
}
public class FixedWordDocument extends FixedBaseDocument {
@Override
public String getFormat() {
return "DOCX";
}
public void applyStyles() { /* ... */ }
}
// Korrigiert: Factory-Pattern für Dokumenterstellung
public interface DocumentFactory {
FixedBaseDocument createDocument();
}
public class PDFDocumentFactory implements DocumentFactory {
@Override
public FixedBaseDocument createDocument() {
return new FixedPDFDocument();
}
}
// Korrigiert: Konverter-Interface für Formatkonvertierung
public interface DocumentConverter<T extends FixedBaseDocument> {
T convert(FixedBaseDocument source);
}
public class PDFConverter implements DocumentConverter<FixedPDFDocument> {
@Override
public FixedPDFDocument convert(FixedBaseDocument source) {
FixedPDFDocument pdf = new FixedPDFDocument();
pdf.setContent(source.getContent());
pdf.setAuthor(source.getAuthor());
pdf.generatePDF();
return pdf;
}
}
# Korrigiert: Verwendung von abstrakter Basisklasse und Factory-Pattern
from abc import ABC, abstractmethod
from typing import Dict, Type, Callable
class FixedAnimal(ABC):
def __init__(self, name: str):
self.name = name
@abstractmethod
def get_sound(self) -> str:
"""Jedes Tier implementiert seinen eigenen Laut"""
pass
# Korrigiert: Keine Referenzen auf Kindklassen
# Nachkommen-Erstellung an Factory delegiert
class FixedDog(FixedAnimal):
def get_sound(self) -> str:
return "Wuff!"
def bark(self):
print(self.get_sound())
class FixedCat(FixedAnimal):
def get_sound(self) -> str:
return "Miau!"
def meow(self):
print(self.get_sound())
# Korrigiert: Factory-Pattern in separatem Modul
class AnimalFactory:
"""Factory für Tiererstellung - hält Eltern unwissend über Kinder"""
_registry: Dict[str, Type[FixedAnimal]] = {}
@classmethod
def register(cls, animal_type: str, animal_class: Type[FixedAnimal]):
cls._registry[animal_type] = animal_class
@classmethod
def create(cls, animal_type: str, name: str) -> FixedAnimal:
if animal_type not in cls._registry:
raise ValueError(f"Unbekannter Tiertyp: {animal_type}")
return cls._registry[animal_type](name)
# Registrierung geschieht im Anwendungs-Setup, nicht in Elternklasse
AnimalFactory.register("dog", FixedDog)
AnimalFactory.register("cat", FixedCat)
# Verwendung
animal = AnimalFactory.create("dog", "Bello")
print(animal.get_sound()) # "Wuff!"
CVE-Beispiele
Diese CWE ist für direkte CVE-Zuordnung als VERBOTEN markiert, da sie ein Code-Qualitäts-/Design-Problem und keine direkte Sicherheitsschwachstelle darstellt.
Verwandte CWEs
- CWE-710: Improper Adherence to Coding Standards (Eltern)
- CWE-1047: Circular Dependency (verwandt)
- CWE-1055: Multiple Inheritance from Concrete Classes (verwandt)
- CWE-1227: Encapsulation Issues (Kategoriemitglied)
Referenzen
-
MITRE Corporation. "CWE-1062: Parent Class with References to Child Class." https://cwe.mitre.org/data/definitions/1062.html
-
Martin, Robert C. "Clean Architecture: A Craftsman's Guide to Software Structure and Design."
-
Gamma, Erich et al. "Design Patterns: Elements of Reusable Object-Oriented Software."