Dekompozycja to podział dużego zadania na mniejsze, zarządzalne podzadania lub funkcje. Historycznie dekompozycja powstała jako kluczowa zasada programowania modułowego: upraszcza zarządzanie złożonością, testowalność i ponowne wykorzystanie kodu.
Problem: Bez dekompozycji kod staje się "monolitem": trudno go czytać, utrzymywać i zmieniać, trudniej pisać testy i ponownie wykorzystywać części programu.
Rozwiązanie: W Pythonie dekompozycja realizowana jest poprzez: podział logiki na funkcje, klasy, moduły; jasne nazewnictwo; użycie kompozycji i abstrahowania. To pozwala pisać czytelny i skalowalny kod.
Przykład kodu:
# Niekompaktowy monolityczny kod numbers = [1, 2, 3, 4] squares = [] for n in numbers: if n % 2 == 0: squares.append(n**2) print(squares) # Dekompozycyjna wersja 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)
Kluczowe cechy:
Czy jedna funkcja może realizować całą logikę biznesową, jeśli jest mała?
Często uważa się, że jeśli zadanie jest małe, można pisać "funkcję na 100 linii". To antywzorzec: nawet małe zadanie komplikuje się przy najmniejszych zmianach; mikrofunkcje są znacznie łatwiejsze do testowania i utrzymywania.
Czy funkcje o tej samej logice, ale różnych nazwach mogą być traktowane jako dekompozycja?
Nie, duplikacja kodu to zła dekompozycja. Powtarzający się kod wskazuje na niewłaściwie dobrane granice podzadań. Zawsze należy wydzielać powtarzającą się funkcjonalność do pomocniczych funkcji.
Przykład:
def add_user(): pass # logika def add_admin(): pass # ta sama logika, co powyżej!
Czy należy dekomponować zadania pomocnicze, jeśli są używane tylko w jednym miejscu?
Tak, często takie funkcje pomagają uprościć kod nawet przy jednostkowym użyciu (na przykład wydzielając warunki lub filtrowanie do osobnej funkcji).
Projekt z przetwarzaniem danych przychodził przez jedną ogromną funkcję na 300 linii. Każdy błąd powodował panikę: trudno szybko zrozumieć, co i gdzie się wydarzyło, testowanie praktycznie niemożliwe.
Zalety:
Wady:
Ten sam projekt, refaktoryzacja — kod podzielony na małe funkcje i klasy według głównej logiki (czytanie, walidacja, przetwarzanie, zapisywanie danych).
Zalety:
Wady: