011 min
The problem modularity addresses
Every program contains decisions that will probably change. The format of the input, the way records are stored and the order of processing are typical ones. If many parts of the code know the exact choice, changing it means editing all of those parts. A small decision then becomes an expensive project.
Modularity addresses this by controlling who is allowed to know a decision. The rule is to give each likely change a single owner. Everyone else talks to the owner through an agreed interface, which is a short list of operations the module promises to support. The rest of the code can be rewritten behind that list without anyone outside noticing.
021 min
Where the idea comes from
The word was in use before the method was explained. At a 1968 NATO conference on software engineering, Douglas McIlroy said that "the idea of interchangeable parts corresponds roughly to our term" modularity. He was comparing software with factories, where parts made to a standard size can be swapped. He added that software had no suppliers of standard parts yet.
The design rule came four years later. David L. Parnas, then at Carnegie Mellon University, published "On the Criteria To Be Used in Decomposing Systems into Modules" in Communications of the ACM in December 1972. In it he asked a question that the earlier talk had not: along which lines should a system be cut? His answer is still the core of the topic.
032 min
Parnas's example: a keyword index in two designs
Parnas used a small program to compare two ways of cutting a system. The program reads lines of text, produces every circular shift of each line (moving the first word to the end, one word at a time), sorts the shifted lines alphabetically and prints them. This is a keyword-in-context index.
The first design follows the steps of the processing: a module to read input, one to shift, one to sort, one to print and one to control the order. This is the way most programmers would divide it. Parnas called it the conventional design.
The second design is divided by decision. One module owns how lines are stored. Another owns how circular shifts are produced, another how sorting is done, and so on. Each module offers a few functions and keeps its own choices private.
Parnas then imagined changes: a different input format, storing lines on disk instead of in memory, a different storage layout. In the first design these changes spread across the program. In the first version, "the format of the line storage in core must be used by all of the programs." In the second design the effect was local. He wrote that "knowledge of the exact way that the lines are stored is entirely hidden from all but module 1. Any change in the manner of storage can be confined to that module!"
Both designs ran correctly and could share the same data. The difference lay only in what each module knew about the others.
041 min
How modularity works: hide the decision, publish the interface
Parnas stated the principle in terms of what the second design did. Of the second version Parnas wrote: "Every module in the second decomposition is characterized by its knowledge of a design decision which it hides from all others. Its interface or definition was chosen to reveal as little as possible about its inner workings."
Three parts follow from this statement.
- A hidden decision. Each module owns one choice that might change, such as a data format or an algorithm.
- An interface. This is the smallest set of operations other modules need. A smaller interface leaves more room to change what is behind it.
- A direction of dependency. Other modules call the interface. They never read the module's internal data.
The starting point is a list of decisions, not a list of steps. Parnas's conclusion reaches past the one example: "it is almost always incorrect to begin the decomposition of a system into modules on the basis of a flowchart. We propose instead that one begins with a list of difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others." A flowchart records what the program does in order. A list of likely changes records what the team expects to be wrong later, and that second list is the better guide for drawing boundaries.
051 min
What modularity is expected to give
Parnas named three expected benefits. Parnas listed three benefits that people expected from modular programs, and the first was that "development time should be shortened because separate groups would work on each module with little need for communication." The second was flexibility: it should be possible to make large changes to one module without changing the others. The third was comprehensibility: a person can study one module at a time.
The first benefit is the one that matters for a team. If the interfaces are agreed, two groups can work in parallel and meet only when the interface needs to change. The cost is that the interface must be right early, since changing it affects every caller. This is why Communication overhead grows when module boundaries do not match the way people are organised.
061 min
How modularity shows up in product and engineering work
Here is an illustrative case. A staff engineer on a subscription product notices that billing rules are checked in the checkout page, the invoice generator and the reporting jobs. When pricing changes, three teams must edit three places and agree on timing. The engineer proposes a billing module with a short interface: get the price for a plan, apply a discount, produce an invoice line. The checkout page, the invoices and the reports all call it. The next price change touches one module.
The same reasoning applies to any public contract. A well-defined API is an interface in Parnas's sense. A product manager who agrees an API with another team is fixing the boundary of a module, and should ask the question Parnas asked: which decision does each side want to keep free to change?
Modularity also changes how duplication is handled. Two copies of one decision are two places that can drift apart. Moving the decision behind one interface removes the second copy.
071 min
Applying modularity
- Write down the decisions in the system that are hard to get right or likely to change. Include data formats, storage choices, third-party services and business rules.
- Give each decision one module as its owner.
- Define the interface from the callers' side. Include only what they need.
- Check by imagining a change. If swapping the decision forces edits outside its module, the boundary is in the wrong place.
- Revisit the list after each release. The decisions that actually changed show where the boundaries should have been.
When the boundaries turn out wrong, refactoring is the tool for moving them. It changes the structure of the code without changing what it does.
081 min
When modularity is the wrong tool
Modularity has a cost, and it is easy to pay it too early. Every interface is a promise. If the team does not yet know which decisions will change, the boundaries are guesses, and guesses often turn out wrong. Gall's law gives the usual advice: a complex system that works evolved from a simple system that worked. Splitting a new product into many modules before it works is a way to freeze the wrong design.
The tell is a change that must edit several modules every time. This means the cut follows the steps of the processing, as in Parnas's first design, and not the decisions.
A second failure is an interface that exposes the internals. If callers can read a module's private data, the decision is no longer hidden and the module only looks separate.
091 min
Modularity versus refactoring, coupling and encapsulation
| Concept | What it is | Question it answers |
|---|---|---|
| Modularity | Dividing a system by hidden decisions | Where should the boundaries be? |
| Refactoring | Restructuring code without changing behaviour | How do I improve the structure I have? |
| Coupling | How much one module depends on another | How tightly are these joined? |
| Encapsulation | Keeping a unit's data private behind its operations | What can outsiders touch? |
Coupling is the measurement and modularity is the practice. A modular design aims for low coupling between modules. Encapsulation is the language-level mechanism that most often enforces the hiding. Modularity is the design decision about what to hide and from whom.
101 min
Frequently asked questions
What is modularity in software?
Modularity is dividing a program into modules that each hide one design decision. Other modules use a stable interface and cannot depend on the hidden choice.
Who defined modularity as information hiding?
David L. Parnas did, in a 1972 paper in Communications of the ACM. He compared two ways of dividing a keyword-index program.
Is a module the same as a file or a class?
No. Parnas used the word for a responsibility assigned to a team or a unit of code. A module can be one file, many files, or a service.
Does modularity mean microservices?
No. Microservices are one way to deploy modules as separate programs. A single program can be modular, and a set of services can fail to be.
How small should a module be?
Size is the wrong measure. A module is right when one likely change stays inside it.
?3 questions
Questions people ask
What is modularity in software?
Who defined modularity as information hiding?
Does modularity mean microservices?
§2 sources
Sources
D. L. Parnas, "On the Criteria To Be Used in Decomposing Systems into Modules", Communications of the ACM 15(12), 1972. win.tue.nl
M. D. McIlroy, "Mass Produced Software Components", NATO Software Engineering Conference, Garmisch, 1968. cs.dartmouth.edu


