The Whole and the Parts is the thirteenth essay of The Mythical Man-Month by Fred P. Brooks. In this essay, Brooks posits the question “How do you build a program or system to work?” The components of a system that “works” must operate together while delivering the functionality needed in a dependable manner.
The process of ensuring what is built “works” begins by designing bugs out. Brooks breaks this section down into four steps that build on each other.
- Bug-proofing the definition: The word “definition” combines the wants and needs of the users with the assumptions of developers or authors. Mismatched assumptions cause the most harmful and subtle bugs. Brooks circles back to the idea of conceptual integrity discussed in the essay, Aristocracy, Democracy and System Design. Conceptual integrity (the whole systems proceeds from one overall design) makes any piece of work easier to use, easier to build and less subject to bugs. Conceptual integrity also supports simplicity, one of the core principles of Agile.
- Testing the specification: Brooks suggests handing the specifications over to the testers before software code is written. The testers will review the specs for completeness and clarity. Peer review processes or test first development practices deliver feedback that improve the chances that the system will work.
- Top-down design: The concepts of top-down design are based on the work of Niklaus Wirth. Wirth’s methods are to identify the design as a sequence of refinement steps. Brooks describes the procedure as sketching out a rough definition and rough solution that achieves the principal result. The next step is to examine the definition more closely to see how the results differ from what is wanted (feedback). Based on the refinements, the next step is to break the large components into smaller steps (grooming).The interactive process of breaking working into smaller and smaller chunks while generating feedback sounds suspiciously like lean and Agile.A good top-down design avoids bugs in several ways. First, the clarity of structure makes the precise statement of the requirements and functionality easier. Second, the partitioning and independence of modules avoids system bugs. Three, the suppression of details makes flaws in the structure more apparent. Four, the design can be tested at each step during its refinement.
- Structured programming: Focuses on using loops, subroutines, and other structures to avoid unmaintainable spaghetti code.
In the second major section of the essay on component debugging, Brooks describes four types of debugging, including machine debugging, memory dumps, snapshots and interactive debugging. While each of these types of component-level debugging are still in use today, how they are done are fundamentally different. Very few developers under forty have ever read a dump or had to translate hex to decimal. While much of the section is a walk down memory lane, it is a reminder that testing and defect removal is not just an event after all the code is written.
In the third section, Brooks builds on his earlier comments about the unexpected difficulty of system testing. Brooks argues that the difficulty and complexity of system testing justifies a systematic approach. First begin by using debugged components for system testing. Beginning with buggy components will yield unpredictable. In other words, do system testing after component debugging. Second, build plenty of scaffolding. Scaffolding provides teams with the ability to begin system testing before all components are done generating earlier feedback. Third, control changes to the system. Testing a system that is subject to random changes will generate results that will not understandable, which increases the chance of delivering poor quality. Fourth, Brooks suggests adding one component at a time to the system test (incremental integration and testing). Building on a known system generates understandable results, and when a problem appears the source can be isolated quicker. Fifth, quantize updates (make changes of fixed size), which suggests that changes to the system should either be large (releases) or very small (continuous integration), although Brooks states the later induces instability. Today’s methods and tools have reduced the potential for problems caused by smaller quanta of change.
The ideas in this essay are a path to verifying and validating software. While it might seem like a truism, Brooks reminds us that building software that works starts well before the first line of code is eveN written.
Previous installments of the Re-read of The Mythical Man-Month