There are many descriptions of engineering software "the old way." After years of software development experience, the software industry has learned many lessons and formulated many principles. This section describes one view of today's software engineering principles as a benchmark for introducing the primary themes discussed throughout the remainder of the book. The benchmark I have chosen is a brief article titled "Fifteen Principles of Software Engineering" [Davis, 1994], The article was subsequently expanded into a book [Davis, 1995] that enumerates 201 principles. Despite its title, the article describes the top 30 principles, and it is as good a summary as any of the conventional wisdom within the software industry. While I endorse much of this wisdom, I believe some of it is obsolete. Davis's top 30 principles are quoted next, in italics. For each principle, I comment on whether the perspective provided later in this book would endorse or change it. I make several assertions here that are left unsubstantiated until later chapters.
1. Make quality #1. Quality must be quantified and mechanisms put into place to motivate its achievement.
a Defining quality commensurate with the project at hand is important but is not easily done at the outset of a project. Consequently, a modern process framework strives to understand the trade-offs among features, quality, cost, and schedule as early in the life cycle as possible. Until this understanding is achieved, it is not possible to specify or manage the achievement of quality.
2. High-quality software is possible. Techniques that have been demonstrated to increase quality include involving the customer, prototyping, simplifying design, conducting inspections, and hiring the best people.
a This principle is mostly redundant with the others.
3. Give products to customers early. No matter how hard you try to learn users' needs during the requirements phase, the most effective way to determine real needs is to give users a product and let them play with it.
a This is a key tenet of a modern process framework, and there must be several mechanisms to involve the customer throughout the life cycle. Depending on the domain, these mechanisms may include demonstrable prototypes, demonstration-based milestones, and alpha/beta releases.
4. Determine the problem before writing the requirements. When faced with what they believe is a problem, most engineers rush to offer a solution. Before you try to solve a problem, be sure to explore all the alternatives and don't be blinded by the obvious solution.
a This principle is a clear indication of the issues involved with the conventional requirements specification process. The parameters of the problem become more tangible as a solution evolves. A modern process framework evolves the problem and the solution together until the problem is well enough understood to commit to full production.
5. Evaluate design alternatives. After the requirements are agreed upon, you must examine a variety of architectures and algorithms. You certainly do not want to use an "architecture" simply because it was used in the requirements specification.
▲ This principle seems anchored in the waterfall mentality in two ways: (1) The requirements precede the architecture rather than evolving together. (2) The architecture is incorporated in the requirements specification. While a modern process clearly promotes the analysis of design alternatives, these activities are done concurrently with requirements specification, and the notations and artifacts for requirements and architecture are explicitly decoupled.
6. Use an appropriate process model. Each project must select a process that makes the most sense for that project on the basis of corporate culture, willingness to take risks, application area, volatility of requirements, and the extent to which requirements are well understood.
a It's true that no individual process is universal. I use the term process framework to represent a flexible class of processes rather than a single rigid instance. Chapter 14 discusses configuration and tailoring of the process to the various needs of a project.
7. Use different languages for different phases. Our industry's eternal thirst for simple solutions to complex problems has driven many to declare that the best development method is one that uses the same notation throughout the life cycle. Why should software engineers use Ada for requirements, design, and code unless Ada were optimal for all these phases?
a This is an important principle. Chapter 6 describes an appropriate organization and recommended languages/notations for the primitive artifacts of the process.
8. Minimize intellectual distance. To minimize intellectual distance, the software's structure should be as close as possible to the real-world structure.
a This principle has been the primary motivation for the development of object-oriented techniques, component-based development, and visual modeling.
9. Put techniques before tools. An undisciplined software engineer with a tool becomes a dangerous, undisciplined software engineer.
a Although this principle is valid, it misses two important points: (1) A disciplined software engineer with good tools will outproduce disciplined software experts with no tools. (2) One of the best ways to promote, standardize, and deliver good techniques is through automation.
10. Get it right before you make it faster. It is far easier to make a working program run faster than it is to make a fast program work. Don't worry about optimization during initial coding.
▲ This is an insightful statement. It has been misstated by several software experts more or less as follows: "Early performance problems in a software system are a sure sign of downstream risk." Every successful, nontrivial software project I know of had performance issues arise early in the life cycle. I would argue that almost all immature architectures (especially large-scale ones) have performance issues in their first executable iterations. Having something executing (working) early is a prerequisite to understanding the complex performance trade-offs. It is just too difficult to get this insight through analysis.
11. Inspect code. Inspecting the detailed design and code is a much better way to find errors than testing.
▲ The value of this principle is overhyped for all but the simplest software systems. Today's hardware resources, programming languages, and automated environments enable automated analyses and testing to be done efficiently throughout the life cycle. Continuous and automated life-cycle testing is a necessity in any modem iterative development. General, undirected inspections (as opposed to inspections focused on known issues) rarely uncover architectural issues or global design tradeoffs. This is not to say that all inspections are ineffective. When used judiciously and focused on a known issue, inspections are extremely effective at resolving problems. But this principle should not be in the top 15, especially considering that the industry's default practice is to overinspect.
12. Good management is more important than good technology. The best technology will not compensate for poor management, and a good manager can produce great results even with meager resources. Good management motivates people to do their best, but there are no universal "right" styles of management.
▲ My belief in this principle caused me to write this book. My only argument here is that the term meager resources is ambiguous. A great, well-managed team can do great things with a meager budget and schedule. Good management and a team meager in quality, on the other hand, are mutually exclusive, because a good manager will attract, configure, and retain a quality team.
13. People are the key to success. Highly skilled people with appropriate experience, talent, and training are key. The right people with insufficient tools, languages, and process will succeed. The wrong people with appropriate tools, languages, and process will probably fail.
▲ This principle is too low on the list.
14. Follow with care. Just because everybody is doing something does not make it right for you. It may be right, but you must carefully assess its applicability to your environment. Object orientation, measurement, reuse, process improvement, CASE, prototyping—all these might increase quality, decrease cost, and increase user satisfaction. The potential of such techniques is often oversold, and benefits are by no means guaranteed or universal.
▲ This is sage advice, especially in a rapidly growing industry in which technology fads are difficult to distinguish from technology improvements. Trading off features, costs, and schedules does not always favor the most modern technologies.
15. Take responsibility. When a bridge collapses we ask, "What did the engineers do wrong?" Even when software fails, we rarely ask this. The fact is that in any engineering discipline, the best methods can be used to produce awful designs, and the most antiquated methods to produce elegant designs.
▲ This is a great corollary to item 14. It takes more than good methods, tools, and components to succeed. It also takes good people, good management, and a learning culture that is focused on forward progress even when confronted with numerous and inevitable intermediate setbacks.
16. Understand the customer's priorities. It is possible the customer would tolerate 90% of the functionality delivered late if they could have 10% of it on time.
a Understanding the customer's priorities is important, but only in balance with other stakeholder priorities. "The customer is always right" is a mentality that has probably resulted in more squandering of money than any other misconception. Particularly in the government contracting domain, but more generally whenever a customer contracts with a system integrator, the customer is frequently wrong.
17. The more they see, the more they need. The more functionality (or performance) you provide a user, the more functionality (or performance) the user wants.
a This principle is true, but it suggests that you would never want to show a user anything. It should read, "The more users see, the better they understand." Not all stakeholders are 100% driven by greed. They know that they have limited resources and that developers have constraints. Demonstrating intermediate results is a high-visibility activity that is necessary to synchronize stakeholder expectations. The ramification of this principle on a modern process is that the software project manager needs to have objective data with which to argue the inevitable change requests and maintain a balance of affordability, features, and risk.
18. Plan to throw one away. One of the most important critical success factors is whether or not a product is entirely new. Such brand-new applications, architectures, interfaces, or algorithms rarely work the first time.
▲ You should not plan to throw one away. Rather, you should plan to evolve a product from an immature prototype to a mature baseline. If you have to throw it away, OK, but don't plan on it from the outset. This may have been sage advice for the 100% custom, leading-edge software development projects of the past. In today's software systems, however, much of the componentry exists (at least the operating system, DBMS, GUI, network, and middleware), and much of what is built in the first pass can be conserved.
19. Design for change. The architectures, components, and specification techniques you use must accommodate change.
a This is a very simple statement that has proven to be exceedingly complex to realize. Basically, it says that we must predict the future and construct a framework that can accommodate change that is not yet well defined. Nevertheless, I endorse this principle wholeheartedly because it is critical to success. It is difficult to predict the future accurately, but attempting to predict the sorts of changes that are likely to occur in a system's life cycle is a useful exercise in risk management and a recurring theme of successful software projects.
20. Design without documentation is not design. I have often heard software engineers say, "I have finished the design. All that is left is the documentation. "
a This principle is also anchored in the document-driven approach of the past, in which the documentation was separate from the software itself. With visual modeling and higher order programming languages, it is usually counterproductive to maintain separate documents for the purpose of describing the software design. High-level architecture documents can be extremely helpful if they are written crisply and concisely, but the primary artifacts used by the engineering team are the design notations, source code, and test baselines. I would modify this principle as follows, to better exploit today's technological advances: "Software artifacts should be mostly self-documenting." This principle is discussed at length in Chapter 6.
21. Use tools, but be realistic. Software tools make their users more efficient.
a This principle trivializes a crucial aspect of modern software engineering: the importance of the development environment. A mature process must be well established, automated, and instrumented. Iterative development projects require extensive automation. It is unwise to underinvest in the capital environment.
22. Avoid tricks. Many programmers love to create programs with tricks— constructs that perform a function correctly, but in an obscure way. Show the world how smart you are by avoiding tricky code.
▲ I find it hard to believe that this is one of the top 30 principles. It is difficult to draw the line between a "trick" and an innovative solution. I know exactly what Davis is getting at, but I would not want to enact a principle that has any connotation of stifling innovation. Obfuscated coding techniques should be avoided unless there are compelling reasons to use them. Unfortunately, such compelling reasons are common in nontrivial projects.
23. Encapsulate. Information-hiding is a simple, proven concept that results in software that is easier to test and much easier to maintain.
▲ Component-based design, object-oriented design, and modern design and programming notations have advanced this principle into mainstream practice. Encapsulation is as fundamental a technique to a software engineer as mathematics is to a physicist. It should be the sole subject of a semester course in universities that teach software engineering.
24. Use coupling and cohesion. Coupling and cohesion are the best ways to measure software's inherent maintainability and adaptability.
a This vital principle is difficult to apply. Coupling and cohesion are abstract descriptions of components for which I know of no well-established, objective definitions. Coupling and cohesion are therefore difficult to measure. Modern metrics for addressing maintainability and adaptability are centered on measuring the amount of software scrap and rework. Cohesive components with minimal coupling are more easily adapted with less scrap and rework. We can reason about the disease (too much coupling and too little cohesion) only by observing and measuring the symptoms (scrap and rework).
25. Use the McCabe complexity measure. Although there are many metrics available to report the inherent complexity of software, none is as intuitive and easy to use as Tom McCabe's.
a Complexity metrics are important for identifying some of the critical components that need special attention. In my experience, however, the really complex stuff is obvious, and it is rare to see these complexity measures used in field applications to manage a project or make decisions. These metrics are interesting from an academic perspective (metaproject research and strategic decision making) and can be useful in project management (if automated), but they do not belong in the top principles.
26. Don't test your own software. Software developers should never be the primary testers of their own software.
▲ This principle is often debated. On one hand, an independent test team offers an objective perspective. On the other hand, software developers need to take ownership of the quality of their products. In Chapter 11,1 endorse both perspectives: Developers should test their own software, and so should a separate team.
27. Analyze causes for errors. It is far more cost-effective to reduce the effect of an error by preventing it than it is to find and fix it. One way to do this is to analyze the causes of errors as they are detected.
▲ On the surface, this is a good principle, especially in the construction phase, when errors are likely to repeat. But analyses of errors in complex software systems have found one of the critical sources to be overanalysis and overdesign on paper in the early stages of a project. To some degree, these activities were "error prevention" efforts. They resulted in a lower return on investment than would have been realized from committing to prototyping and construction activities, which would have made the errors more obvious and tangible. Therefore, I would restate this as two principles: (1) Don't be afraid to make errors in the engineering stage. (2) Analyze the cause for errors in the production stage.
28. Realize that software's entropy increases. Any software system that undergoes continuous change will grow in complexity and will become more and more disorganized.
▲ This is another remnant of conventional software architectures. Almost all software systems undergo continuous change, and the sign of a poor architecture is that its entropy increases in a way that is difficult to manage. Entropy tends to increase dangerously when interfaces are changed for tactical reasons. The integrity of an architecture is primarily strategic and inherent in its interfaces, and it must be controlled with intense scrutiny. Modern change management tools force a project to respect and enforce interface integrity. A quality architecture is one in which entropy increases minimally and change can be accommodated with stable, predictable results. An ideal architecture would permit change without any increase in entropy.
29. People and time are not interchangeable. Measuring a project solely by person-months makes little sense.
A This principle is timeless.
30. Expect excellence. Your employees will do much better if you have high expectations for them.
▲ This principle applies to all disciplines, not just software management.
I have used some provocative words in my comments. My purpose was neither to endorse nor to refute specifically Davis's principles, but rather to expose my biases and provoke thought. While I see tremendous merit in about half of the principles, the other half either need a change in priority or have been obsolesced by new technology.
Was this article helpful?
What you need to know about… Project Management Made Easy! Project management consists of more than just a large building project and can encompass small projects as well. No matter what the size of your project, you need to have some sort of project management. How you manage your project has everything to do with its outcome.