Decomposition is the process of breaking a large task into smaller, manageable subtasks or functions. Historically, decomposition emerged as a key principle of modular programming: it simplifies the management of complexity, testability, and code reuse.
Problem: Without decomposition, code becomes a "monolith": it is hard to read, maintain, and modify, and more difficult to write tests and reuse parts of the program.
Solution: In Python, decomposition is implemented by breaking the logic into functions, classes, and modules; using clear naming; and employing composition and abstractions. This allows for writing readable and scalable code.
Code Example:
# Non-compact monolithic code numbers = [1, 2, 3, 4] squares = [] for n in numbers: if n % 2 == 0: squares.append(n**2) print(squares) # Decomposed version 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)
Key features:
Can a single function implement all business logic if it is small?
It is often believed that if a task is small, it is acceptable to write a "100-line function". This is an anti-pattern: even a small task becomes complicated with the slightest changes; micro-functions are much easier to test and maintain.
Can functions with the same logic but different names be considered as decomposition?
No, code duplication is poor decomposition. Repeated code indicates incorrectly chosen boundaries of subtasks. You should always extract repeated functionality into helper functions.
Example:
def add_user(): pass # logic def add_admin(): pass # the same logic as above!
Is it necessary to decompose auxiliary tasks if they are used only in one place?
Yes, often such functions help simplify code even with single use (for example, isolating conditions or filtering into a separate function).
A data processing project was handled through one huge function of 300 lines. Every bug caused panic: it was impossible to quickly understand what happened and where, testing was virtually impossible.
Pros:
Cons:
The same project, refactoring — the code is split into small functions and classes based on the core logic (reading, validating, processing, writing data).
Pros:
Cons: