Dekomposition ist das Zerteilen einer großen Aufgabe in kleinere, manageable Teilaufgaben oder Funktionen. Historisch gesehen entstand die Dekomposition als ein Schlüsselprinzip der modularen Programmierung: Sie vereinfacht das Management der Komplexität, die Testbarkeit und die Wiederverwendbarkeit von Code.
Problem: Ohne Dekomposition wird der Code zu einem "Monolithen": Er lässt sich schwer lesen, warten und ändern, sowie Tests sind schwieriger zu schreiben und Teile des Programms sind schwer wiederverwendbar.
Lösung: In Python wird Dekomposition erreicht durch: Aufteilen der Logik in Funktionen, Klassen, Module; eindeutige Benennung; Verwendung von Komposition und Abstraktionen. Dies ermöglicht es, lesbaren und skalierbaren Code zu schreiben.
Codebeispiel:
# Nicht kompakter monolithischer Code numbers = [1, 2, 3, 4] squares = [] for n in numbers: if n % 2 == 0: squares.append(n**2) print(squares) # Dekomponierte Variante def is_even(n): return n % 2 == 0 def square(n): return n ** 2 def filter_and_apply(numbers, predicate, func): return [func(n) for n in numbers if predicate(n)] numbers = [1, 2, 3, 4] result = filter_and_apply(numbers, is_even, square) print(result)
Hauptmerkmale:
Kann eine Funktion die gesamte Geschäftslogik implementieren, wenn sie klein ist?
Oft wird angenommen, dass es erlaubt ist, eine "Funktion mit 100 Zeilen" zu schreiben, wenn die Aufgabe klein ist. Dies ist ein Antipattern: Selbst kleine Aufgaben werden bei kleinsten Änderungen komplexer; Mikro-Funktionen sind viel einfacher zu testen und zu warten.
Können Funktionen mit identischer Logik, aber unterschiedlichen Namen als Dekomposition betrachtet werden?
Nein, Code-Duplikation ist keine gute Dekomposition. Wiederkehrender Code deutet auf falsch gewählte Grenzen der Teilaufgaben hin. Man sollte immer wiederkehrende Funktionalitäten in Hilfsfunktionen auslagern.
Beispiel:
def add_user(): pass # Logik def add_admin(): pass # Die gleiche Logik wie oben!
Muss man Hilfsaufgaben dekomponieren, wenn sie nur an einem Ort verwendet werden?
Ja, oft helfen solche Funktionen, den Code einfacher zu gestalten, selbst bei einzelner Verwendung (zum Beispiel Bedingungen oder Filter in eine separate Funktion auszulagern).
Ein Projekt mit Datenverarbeitung wurde über eine riesige Funktion mit 300 Zeilen hinweg bearbeitet. Jeder Bug verursachte Panik: Es war unmöglich, schnell zu verstehen, was und wo passiert ist, das Testen war nahezu unmöglich.
Vorteile:
Nachteile:
Dasselbe Projekt, Refactoring — der Code ist in kleine Funktionen und Klassen nach Hauptlogik (Lesen, Validierung, Verarbeitung, Datenaufzeichnung) aufgeteilt.
Vorteile:
Nachteile: