As a Software Engineer and Manager (albeit for a short time), I am always trying to understand how to best manage projects, how to choose the correct tools, how to assign responsibilities to the team and ultimately how to make the best possible decisions.
This book was a huge surprise to me. Even though it was written more than 20 years ago, most of what is written is still relevant today. It helped me understand many issues and obstacles I’ve found in my own projects.
Notes and Highlights
To become a generally usable programming product, a program must be written in a generalized fashion.
With any creative activity come dreary hours of tedious, painstaking labor, and programming is no exception.
…when schedule slippage is recognized, the natural (and traditional) response is to add manpower. Like dousing a fire with gasoline, this makes matters worse, much worse. More fire requires more gasoline, and thus begins a regenerative cycle which end in disaster.
The programmer builds from pure thought-stuff: concepts and very flexible representations thereof. Because the medium is tractable, we expect few difficulties in implementation; hence our pervasive optimism. Because our ideas are faulty, we have bugs; hence our optimism is unjustified.
Failure to allow enough time for system test, in particular, is peculiarly disastrous. Since the delay comes at the end of the schedule, no one is aware of schedule trouble until almost delivery date. Bad news, late and without warning, is unsettling to customers and managers
Conceptual integrity is the most important consideration in system design. It is better to have a system omit certain anomalous features and improvements, but to reflect one set of design ideas, than to have one that contains many good but independent and uncoordinated ideas.
The architect of a system, like the architect of a building, is the user’s agent. It is his job to bring professional and technical knowledge to bear in the unalloyed interest of the user, as opposed to the interests of the salesman, the fabricator, etc.
In an unconstrained implementing group, most thought and debate goes into architectural decisions, and implementation proper gets short shrift.
The general tendency is to over-design the second system, using all the ideas and frills that were cautiously sidetracked on the first one. The result, as Ovid says, is a “big pile”.
How does the architect avoid the second-system effect? Well, obviously he can’t skip his second system. But he can be conscious of the peculiar hazards of the system, and exert extra self-discipline to avoid functional ornamentation and to avoid extrapolation of functions that are obviated by changes in assumptions and purposes
This is very important because it is hard to understand, when one is the designer, how many features are too many in the second iteration.
The job done least well by project managers is to utilize the technical genius who is not strong on management talent. :
Beyond craftsmanship lies invention, and it is here that lean, spare, fast programs are born. Almost always these are the result of strategic breakthrough rather than tactical cleverness.
Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables and I won’t usually need your flowcharts; they’ll be obvious.
(here tables refer to data representation or db tables)
…he comes to realize that a certain small set of these documents embodies and expresses much of his managerial work. The preparation of each one serves as a major occasion for focusing thought and crystallizing discussions that otherwise would wander endlessly. Its maintenance becomes his surveillance and warning mechanism. The document itself serves as a check-list, a status control, and a data base for his reporting.
The concerns of any management task are what, when, how much, where and who.
First, writing the decisions down is essential. Only when one writes do the gaps appear and the inconsistencies protrude. The act of writing turns out to require hundreds of mini-decisions, and it is the existence of these that distinguishes clear, exact policies from fuzzy ones. Second, the documents will communicate the decisions to others.
The management question, therefore, is not whether to build a pilot system and throw it away. You will do that. The only question is whether to plan in advance to build a throwaway, or promise to deliver the throwaway to customers.
Delivering the throwaway to customers buys time, but it does so only at the cost of agony for the user, distraction for the builders while they do the redesign, and a bad reputation for the product that the best redesign will find hard to live down.
On a large project the manager needs to keep to or three top programmers as a technical cavalry that can gallop to the rescue wherever the battle is thickest.
Managers need to be sent to technical refresher courses, senior technical people to management training. Project objectives, progress and management problems must be shared with the whole body of senior people.
The total cost of maintaining a widely used program is typically 40 percent or more of the cost of developing it. Surprisingly this cost is strongly affected by the number of users. More users find more bugs.
First, the essential problem is communication, and individualized tools hamper rather than aid communication. Second, the technology changes when one changes machines or working language, so tool lifetime is short. Finally, it is obviously much more efficient to have common development and maintenance of the general-purpose programming tools.
Milestones must be concrete, specific, measurable events, defined with knife-edge sharpness. Coding, for a counterexample, is “90 percent finished” for half of the total coding time. Debugging is “99 percent complete” most of the time. “Planning complete” is an event one can proclaim almost at will.
Concrete milestones, on the other hand, are 100-percent events. “Specifications signed by architects and implements,” “source coding 100 percent complete, keypunched, entered into disk library,” “debugged version passes all test cases.” These concrete milestones demark the vague phrases of planning, coding debugging.
Every user needs a prose description of the program. Most documentation fails in giving too little overview. The tress are described, the bark and leaves are commented, but there is no map of the forest. To write a useful prose description, stand way back and come in slowly:
- Purpose. What is the main function, the reason for the program?
- Environment. On what machines, hardware configurations, and operating system configurations will it run?
- Domain and range. What domain of input is valid? What range of output can legitimately appear?
- Functions realized and algorithms used. Precisely what does it do?
- Input-output formats, precise and complete.
- Operating instructions, including normal and abnormal ending behavior, as as seen at the console and on the outputs.
- Options. What choices does the user have about functions? Exactly how are those choices specified?
- Running time. How long does it take to do a problem of specified sized on a specified configuration?
- Accuracy and checking. How precise are the answers expected to be? What means of checking accuracy are incorporated?
The flow chart is the most thoroughly oversold piece of program documentation. Many programs don’t need flow charts at all; few programs need more than a one-page flow chart.
Flow charting is more preached than practiced. I have never seen an experienced programmer who routinely made detailed flow charts before beginning to write programs. Where organization standards require flow charts, there are almost invariable done after the fact.
There is no royal road, but there is a road.
Not only are there no silver bullets now in view, the very nature of software makes it unlikely that there will be any – no inventions that will do for software productivity, reliability, and simplicity what electronics, transistors, and large-scale integration did for computer hardware. We cannot expect ever to see two-fold gains every two years.
I believe the single most powerful software productivity strategy for many organizations today is to equip the computer-naive intellectual workers on the firing line with personal computers and good generalized writing, drawing, file, and spreadsheet programs, and turn them loose. The same strategy, with generalized mathematical and statistical packages and some simple programming capabilities, will also work for hundreds of laboratory scientists.
How to grow great designers? […]: * Systematically identify top designers as early as possible. The best are often not the most experienced. * Assign a career mentor to be responsible for the development of the prospect, and keep a careful career file. * Devise and maintain a career development plan for each prospect, including carefully selected apprenticeships with top designers, episodes of advanced formal education, and short courses, all interspersed with solo design and technical leadership assignments. * Provide opportunities for growing designers to interact with and stimulate each other.
This should be done across the board, not only for designers.
More programming projects have gone awry for lack of calendar time than for all other causes combined.
My rule of thumb is 1/3 of the schedule for design, 1/6 for coding, 1/4 for component testing, and 1/4 for system testing.
Brook’s Law: Adding manpower to a late software project makes it later.
“If a system is to have conceptual integrity, someone must control the concepts. That is an aristocracy that needs no apology.”
The second is the most dangerous system a person ever designs; the general tendency is to over-design it.
Delivering the first system, the throwaway, to uses will buy time, but only at the cost of agony for the user, distraction for the builders supporting it while they do the redesign, and a bad reputation for the product that will be hard to live down.
Day-by-day schedule slippage is harder to recognize, harder to prevent, and harder to make up than calamities.
The first step in controlling a big project on a tight schedule is to have a schedule, made up of milestones and dates for them.
Milestones must be concrete, specific, measurable events, defined with knife-edge sharpness.
Human history is a drama in which the stories stay the same, the scripts of those stories change slowly with evolving cultures and the stage settings change all the time.
…it is necessary for the system master architect to partition the system into subsystems. The subsystem boundaries must be at those places where interfaces between the subsystems are minimal and easiest to define rigorously. Then each piece will have its own architect, who must report to the system master architect with respect to the architecture. Clearly this process can proceed recursively as required.
One of the hardest issues facing software architects is exactly how to balance user power versus ease of use. Do they design for simple operation for the novice or the occasional user, or for efficient power for the professional user? The ideal answer is to provide both.
The waterfall model puts system test, and therefore by implication user testing, at the end of the construction process. Thus one can find impossible awkwardnesses for users, or unacceptable performance, or dangerous susceptibility to user error or malice, only after investing in full construction.
People with more time take more time.
“People are everything”
…a conviction that the quality of the people on a project, and their organization and management, are much more important factors in success than are the tools they use or the technical approaches they take.
This is similar to “getting the right people on the bus” from “Good to Great”.
…the quality of the team is by far the largest factor in its success, indeed four times more potent than the next largest factor. Most academic research on software engineering has concentrated on tools. I admire and covet sharp tools. Nevertheless, it is encouraging to see ongoing research efforts on the care, growing , and feeding of people and on the dynamics of software management.
…software engineering, like chemical engineering, is concerned with the nonlinear problems of scaling up into industrial-scale processes, and like industrial, engineering, it is permanently confounded by the complexities of human behavior.