Deep Modules
- Categories
- Complexity
- Sources
- A Philosophy of Software Design
A module is deep when it offers a simple interface over a powerful implementation. Depth is the ratio of functionality provided to interface exposed: the best modules hide a lot behind a little.
Why it Matters
A module's interface is a cost paid by every user; its implementation is a cost paid once. Deep modules maximize the benefit (functionality) relative to the cost (interface), which is how modular design actually reduces complexity rather than just redistributing it.
Signals
- A short, stable interface that rarely changes even as the implementation grows.
- Callers accomplish a lot without knowing how the work is done.
- The inverse, a shallow module, has an interface nearly as complex as its implementation, so it provides little abstraction for its cost.
Benefits
Each interface a developer learns unlocks significant capability. Fewer, deeper modules mean fewer interfaces to understand and fewer places for complexity to leak across boundaries.
Risks
Over-decomposition into many tiny classes/methods (the "classes should be small" reflex taken too far) produces shallow modules and more interfaces. Splitting a module can increase total complexity if it forces callers to manage the interaction.
Tensions
The advice to keep components small conflicts with depth: more, smaller units mean more interfaces. Depth favors fewer, larger units, bounded by the need to keep each implementation comprehensible.
Examples
A garbage collector exposes essentially no interface yet does enormous work: maximally deep. A wrapper that just forwards arguments to another call adds an interface while hiding nothing: shallow.