Module
Context
Within a component, or within a system small enough not to need explicit component boundaries, code still needs to be organized. A module is a unit of code or behavior grouped around a single coherent responsibility. It operates at the architectural scale, bridging the gap between the large-scale structure of a system and the individual functions and classes that do the work.
In most languages, a module corresponds to a file, a package, a namespace, or a class. The specific mechanism varies, but the intent is the same: gather related things together and give them a shared identity.
Problem
How do you organize code so that related things are easy to find and unrelated things do not interfere with each other?
Forces
- Code that changes for the same reason should live together.
- Code that changes for different reasons should live apart.
- Too many small modules create a navigation burden. You spend more time finding things than reading them.
- Too few large modules create a comprehension burden. Each module does too much to hold in your head.
Solution
Group code by responsibility. A module should have one clear reason to exist, and everything inside it should relate to that reason. This is the principle of cohesion: the contents of a module belong together.
A good module has a name that tells you what it does (not how it does it), an interface that exposes what outsiders need, and an interior that hides the rest. The boundary between “public” and “private” is one of the most useful tools in a programmer’s kit. It lets you change the inside without breaking the outside.
When working with AI agents, well-defined modules are essential. An agent instructed to “modify the validation module” can open the relevant files, understand the scope, and make targeted changes. If “validation” logic is scattered across twenty files in three directories, the agent either misses pieces or has to load far more context than necessary.
How It Plays Out
A Python project organizes its code into modules: auth.py handles authentication, models.py defines data structures, api.py exposes HTTP endpoints. A new developer can orient herself by reading the file names. When a bug appears in authentication, she knows exactly where to look.
An AI agent is asked to add input validation to a REST API. The project has a validation module with a clear pattern: each endpoint has a corresponding validation schema. The agent follows the pattern, adds the new schema, and wires it in. The module’s structure served as a template the agent could follow.
When you find yourself writing a code comment like “TODO: move this somewhere better,” that is a signal that the current module boundaries are not right. Respect that signal — it is cheaper to reorganize modules early than to untangle them later.
“The validation logic is scattered across three files. Create a validation module with a clear pattern: one schema per endpoint. Move the existing validation code into this module and update the imports.”
Consequences
Good module boundaries reduce the mental load of working with a codebase. They give you a map: each module is a labeled region on that map. They support parallel work, so different people (or agents) can work on different modules with minimal coordination.
The downside is that modules impose a taxonomy, and taxonomies can become outdated. When the problem domain shifts, module boundaries may no longer reflect the natural groupings. Renaming, splitting, and merging modules is routine maintenance that too many teams defer.
Related Patterns
- Refines: Component — a module is a component at a finer grain.
- Measured by: Cohesion — a module’s quality depends on how well its contents belong together.
- Uses: Interface, Boundary — modules expose interfaces and maintain boundaries.
- Supports: Separation of Concerns — well-designed modules separate different concerns.
- Related: Big Ball of Mud – clear module boundaries resist mud formation.