This is the penultimate working draft. I am tired and want to catch some ZZZs. I may go to work. The report still needs proofreading and a final closing paragraph. Read it and give me any criticism.
Fact 52: Efficiency stems more from good design than from good coding.
Discussion
Can you really argue that this fact is actually a fallacy? Does it not make sense that from a well thought out design an efficient program emerges? Obviously efficient programs start with good design, which is true to a degree. After all, there is the old management saw, “Measure twice. Cut once,” which speaks more truths about the importance of starting with a good blueprint before producing an item than any other platitude about production. Except, it is rather shortsighted to minimize the importance of code to a program. As Kent Beck said, “[C]ode is the one artifact that development can’t live without (44).” It is the most important activity in software development, because in the end it is the code that is compiled into the program not UML diagrams, not requirement statements, not use cases, nor any other artifact that is generated when software is created. Robert Glass seems to disregard in that fact that code is what implements the efficiency of a good design.
To see the fallacy in that fact, let’s add words to it so that it reads more factual. Since, it is generally agreed that the best software development processes use a feedback loop, so let’s restate the fact merging the design and code into one phase, “Efficiency stems more from good implementation (design and coding together).” When restated, the fact makes more sense because it includes the importance of code as well as introduces the concept that design and code are irrevocably linked together in the development cycle. It is hard to divorce the two during development, and it is hard to see where one ends and the other begins. Design really is a part of the coding as Steve McConnell explains, “[T]he design might be intended to be detailed enough for coding to be fairly mechanical, but is design rarely complete – the coder usually designs part of the program, officially or otherwise (139).” Not all design is done up front. Some of it happens as the developer implements the design. Not all coding should be done after design for example code that is written as a “proof of concept.” If efficiency is desirable in design, then it is also desirable in implementing the design, and therefore efficiency too can come from coding.
If the developer seeks efficiency, how is she to know if the design she has laid out meets that criterion? She must seek feedback to the design either through desk checking the design, conducting a peer review, or through implementing it in code. It may take several iterations until an acceptable design emerges. In fact Glass agrees that the implementation phase should be cyclical when he states in fact 28, “Design is a complex, iterative process. The initial design solution will likely be wrong and certainly not optimal (81).” Sometimes the design is implemented in code to make sure that it works and is feasible. Design should be iterative, because it is fraught with many difficult choices to make. McConnell declares that “design is a sloppy process… because the right answer is often hard to distinguish from the wrong one (161).” Glass also echoes the sentiment in fact 27, “There is seldom one best design solution to a software problem (79).” So if there is more than one way at achieving the optimal design, then it is best to let the implementation decide on the efficiency aspects to address. Designing an efficient program will be difficult because the developer won’t know until it is implemented if it is truly efficient.
So design and coding can happen concurrently in the same phase, and design is difficult so that it should be attempted in an iterative fashion, but should seeking efficiency happen even during the design phase? McConnell argues that efficiency should not be considered during design because “[i]t’s almost impossible to identify performance bottlenecks before a program is working completely (681).” The design can make note of certain areas to be of concern and can choose the appropriate algorithms or data structures to minimize their impact to the working program, but not until the code is written will the actual inefficiencies be found. Not until coding, does the developer know how successful the design is. He further argues that “[f]ocusing on optimization during initial development detracts from achieving other program objective (681).” Efficiency should not be the main focus of the early design phase, but can be left to later after the primary objectives of good code are defined.
In his discussion of the fact, Glass describes the areas that a good design can optimize, “external input/output…, clumsy interfaces, … and internal time wastage (140),” and makes a strong case that these are the areas that a design should attempt to make efficient, but these areas are already well known as bottlenecks to performance. Hardware access is a fundamental performance bottleneck, extra function calls and indirect access methods add performance overhead, and ill-designed program logic can waste CPU cycles, but at design time effort should be made to reduce their impact. In fact these areas are so well known that they are already taken into account by most developers, so efficiency can only be gained during the coding process.
Now let’s change the statement again, “Good design is not necessarily efficient.” This may be counterintuitive, but sometimes designs that seem to be optimal, when they are coded, can produce an inefficient program. For an example, a design, which relies heavily on template functions and classes, may cause the size of the program to be larger because of the number of types of instances of these template classes causing inefficient use of memory. Another example is a design, which misuses design patterns; Abstract factories building Composites of Strategies kicked off by a change of State seems rather complicated to implement. Increase complexity through deeper class hierarchies and the need for virtual tables to store the method calls add levels of indirection or as Glass said a clumsy interface.
Glass focuses on the most notorious of inefficiencies, but does not mention that design may add inefficient compilation of the program. Like the example above of deep class hierarchies and their resultant virtual tables, the compiler must make these linkages before producing the executable. Also by designing a class hierarchy with many concrete classes compilation time may take longer. It may be a good design, but having a long compile time would make the developers waste their time waiting for the compilation to be finished.
Implementing the design in code may not always end up with an efficient program. Glass, in fact 29, states, “Designer ‘primitives’ (solutions programmers can readily code) rarely match programmer ‘primitives’ (84).” Admittedly, this is true only if the project is large enough to have stratified team members’ roles and separated the designers from the programmers. A good design may be translated into inefficient code by the developer tasked to implement the design. It is dependent upon the coder to be able to code the design correctly. Here, it is the single most important fact about the relationship code has to design. Code is where “the rubber meets the road.” If the code is poor, it will not matter how well the design was laid out.
Finally, is it efficiency that should be the focus of design? McConnell sums up succinctly the goal of design, “It’s hardly ever true that programs need to be fast or small before they need to be correct (682).” He argues for producing a good, correct design before thinking about the need for optimizing for efficiency. Design should focus on “highly modular code that’s easy to understand and modify (693).” Afterwards, measurements are taken of the bottlenecks in the performance of the program in order to tune and optimize the program for proficiency (693), but this is after successive iterations of the developed program not before. Design should focus on quality and let efficiency arise through good practices.
Controversy
The controversy of calling this fact a fallacy can be easily focused upon by restating the fact by placing code before design: “Efficiency stems more from good code than good design.” This principle is the basis for Extreme Programming (XP), which emphasizes code before design. It seems as though Glass is trying to belittle this new practice in software engineering, when he points out that the controversy is between “those who see design as being of little value and those who see it as an essential prelude to coding (141).” He seems to believe that the followers of XP focus more on the coding than on producing good design, but he misinterprets XP. Coding may be the primary activity found on an XP project. Coding of unit tests, coding the program to pass the unit tests, and refactoring existing code so that the program succeeds in addressing the most simple of requirements. There is a method to the XP madness. In fact, Kent Beck includes a chapter titled, “Design Strategy,” in his seminal book on XP, Extreme Programming Explained.
XP’s goal as related to design is to produce the simplest design, which can meet the current written code. Design’s role is sublimated to that of the code, yet it is still important. “We will continually refine the design of the system, starting from a very simple beginning. We will remove any flexibility that doesn’t prove useful (103).” Again, design is iterative, and it seeks to produce efficient code, but it is not the primary duty of the developer in XP to produce design documents. Rather the code is continuously refined until it becomes a rather simple and easy to understand design.
XP’s design strategy starts as writing unit tests to highlight the problem that the production code needs to solve. It moves to designing and implementing code to satisfy the test. Design and coding continuously happen until the test passes. If the design can be made simpler, than it should be. (106) This allows the XP developer to develop just enough to make the program work correctly, and whatever inefficiencies will not be coded. By starting with code, XP practitioners already are at the stage of knowing what code will be efficient rather than guessing at the beginning of the development by studying the design documents.
Sources
Beck,Kent. Extreme Programming Explained. Boston: Addison-Wesley, 2000.
McConnell, Steve. Code Complete. Redmond: Microsoft Press, 1993.
Glass, Robert L. Facts and Fallacies of Software Engineering. Boston: Addison-Wesley, 2003.
Broderic C Gonzales
October 21, 2004
Page 6 of 7