Code Complete Quotes

Rate this book
Clear rating
Code Complete: A Practical Handbook of Software Construction Code Complete: A Practical Handbook of Software Construction by Steve McConnell
9,456 ratings, 4.30 average rating, 446 reviews
Open Preview
Code Complete Quotes Showing 31-60 of 130
“The point of loose coupling is that an effective module provides an additional level of abstraction—once you write it, you can take it for granted. It reduces overall program complexity and allows you to focus on one thing at a time. If using a module requires you to focus on more than one thing at once—knowledge of its internal workings, modification to global data, uncertain functionality—the abstractive power is lost and the module's ability to help manage complexity is reduced or eliminated. Classes and routines are first and foremost intellectual tools for reducing complexity. If they're not making your job simpler, they're not doing their jobs.”
Steve McConnell, Code Complete
“Specific Architectural Topics Is the overall organization of the program clear, including a good architectural overview and justification? Are major building blocks well defined, including their areas of responsibility and their interfaces to other building blocks? Are all the functions listed in the requirements covered sensibly, by neither too many nor too few building blocks? Are the most critical classes described and justified? Is the data design described and justified? Is the database organization and content specified? Are all key business rules identified and their impact on the system described? Is a strategy for the user interface design described? Is the user interface modularized so that changes in it won’t affect the rest of the program? Is a strategy for handling I/O described and justified? Are resource-use estimates and a strategy for resource management described and justified for scarce resources like threads, database connections, handles, network bandwidth, and so on? Are the architecture’s security requirements described? Does the architecture set space and speed budgets for each class, subsystem, or functionality area? Does the architecture describe how scalability will be achieved? Does the architecture address interoperability? Is a strategy for internationalization/localization described? Is a coherent error-handling strategy provided? Is the approach to fault tolerance defined (if any is needed)? Has technical feasibility of all parts of the system been established? Is an approach to overengineering specified? Are necessary buy-vs.-build decisions included? Does the architecture describe how reused code will be made to conform to other architectural objectives? Is the architecture designed to accommodate likely changes? General Architectural Quality Does the architecture account for all the requirements? Is any part overarchitected or underarchitected? Are expectations in this area set out explicitly? Does the whole architecture hang together conceptually? Is the top-level design independent of the machine and language that will be used to implement it? Are the motivations for all major decisions provided? Are you, as a programmer who will implement the system, comfortable with the architecture?”
Steve McConnell, Code Complete
“Global data is generally subject to two problems: routines operate on global data without knowing that other routines are operating on it, and routines are aware that other routines are operating on the global data but they don't know exactly what they're doing to it.”
Steve McConnell, Code Complete: A Practical Handbook of Software Construction
“[...] you shouldn't be uneasy about any parts of the architecture. It shouldn't
contain anything just to please the boss. It shouldn't contain anything that's hard for you
to understand. You're the one who'll implement it; if it doesn't make sense to you, how
can you implement it?”
Steve McConnell, Code Complete: A Practical Handbook of Software Construction
“You save time when you don't need to have an awards ceremony every time a C statement does what it's supposed to. Moreover,”
Steve McConnell, Code Complete
“The gap between the best software engineering practice and the average practice is very wide—perhaps wider than in any other engineering discipline. A tool that disseminates good practice would be important. — Fred Brooks”
Steve McConnell, Code Complete
“The words available in a programming language for expressing your programming thoughts certainly determine how you express your thoughts and might even determine what thoughts you can express.”
Steve McConnell, Code Complete
“In the case of natural languages, the linguists Sapir and Whorf hypothesize a relationship between the expressive power of a language and the ability to think certain thoughts. The Sapir-Whorf hypothesis says that your ability to think a thought depends on knowing words capable of expressing the thought. If you don't know the words, you can't express the thought and”
Steve McConnell, Code Complete
“By relieving the brain of all unnecessary work, a good notation sets it free to concentrate on more advanced problems, and in effect increases the mental power of the race. Before the introduction of the Arabic notation, multiplication was difficult, and the division even of integers called into play the highest mathematical faculties. Probably nothing in the modern world would have more astonished a Greek mathematician than to learn that … a huge proportion of the population of Western Europe could perform the operation of division for the largest numbers. This fact would have seemed to him a sheer impossibility…. Our modern power of easy reckoning with decimal fractions is the almost miraculous result of the gradual discovery of a perfect notation. —Alfred North Whitehead”
Steve McConnell, Code Complete
“Notably, the core of NASA's approach to creating reusable classes does not involve "designing for reuse." NASA identifies reuse candidates at the ends of their projects. They then perform the work needed to make the classes reusable as a special project at the end of the main project or as the first step in a new project. This approach helps prevent "gold-plating"—creation of functionality that isn't required and that unnecessarily adds complexity.”
Steve McConnell, Code Complete
“The most challenging part of programming is conceptualizing the problem, and many errors in programming are conceptual errors. Because”
Steve McConnell, Code Complete
“classic General Motors analysis found that 50 to 80 percent of if statements should have had an else clause (Elshoff 1976). One option is to code the else clause—with a null statement if necessary—to show that the else case has been considered. Coding null elses just to show that that case has been considered might be overkill, but at the very least, take the else case into account. When you have an if test without an else, unless the reason is obvious, use comments to explain why the else clause isn't necessary, like so:”
Steve McConnell, Code Complete
“In most instances, global data is really class data for a class that hasn't been designed or implemented very well. In a few instances, data really does need to be global, but accesses to it can be wrapped with access routines to minimize potential problems. In a tiny number of remaining instances, you really do need to use global data.”
Steve McConnell, Code Complete
“Use locking to control access to global variables. Similar to concurrency control in a multiuser database environment, locking requires that before the value of a global variable can be used or updated, the variable must be "checked out." After the variable is used, it's checked back in. During the time it's in use (checked out), if some other part of the program tries to check it out, the lock/unlock routine displays an error message or fires an assertion.”
Steve McConnell, Code Complete
“Additional Resources on Data Types These books are good sources of information about data types: Cormen, H. Thomas, Charles E. Leiserson, Ronald L. Rivest. Introduction to Algorithms. New York, NY: McGraw Hill. 1990. Sedgewick, Robert. Algorithms in C++, Parts I-IV, 3d ed. Boston, MA: Addison-Wesley, 1998. Sedgewick, Robert. Algorithms in C++, Part V, 3d ed. Boston, MA: Addison-Wesley, 2002.”
Steve McConnell, Code Complete
“The Pseudocode Programming Process Have you checked that the prerequisites have been satisfied? Have you defined the problem that the class will solve? Is the high-level design clear enough to give the class and each of its routines a good name? Have you thought about how to test the class and each of its routines? Have you thought about efficiency mainly in terms of stable interfaces and readable implementations or mainly in terms of meeting resource and speed budgets? Have you checked the standard libraries and other code libraries for applicable routines or components? Have you checked reference books for helpful algorithms? Have you designed each routine by using detailed pseudocode? Have you mentally checked the pseudocode? Is it easy to understand? Have you paid attention to warnings that would send you back to design (use of global data, operations that seem better suited to another class or another routine, and so on)? Did you translate the pseudocode to code accurately? Did you apply the PPP recursively, breaking routines into smaller routines when needed? Did you document assumptions as you made them? Did you remove comments that turned out to be redundant? Have you chosen the best of several iterations, rather than merely stopping after your first iteration? Do you thoroughly understand your code? Is it easy to understand?”
Steve McConnell, Code Complete
“Hacking? Some programmers try to hack their way toward working code rather than using a systematic approach like the PPP. If you've ever found that you've coded yourself into a corner in a routine and have to start over, that's an indication that the PPP might work better. If you find yourself losing your train of thought in the middle of coding a routine, that's another indication that the PPP would be beneficial. Have you ever simply forgotten to write part of a class or part of routine? That hardly ever happens if you're using the PPP. If you find yourself staring at the computer screen not knowing where to start, that's a surefire sign that the PPP would make your programming life easier.”
Steve McConnell, Code Complete
“Here are the benefits you can expect from using this style of pseudocode: Pseudocode makes reviews easier. You can review detailed designs without examining source code. Pseudocode makes low-level design reviews easier and reduces the need to review the code itself. Pseudocode supports the idea of iterative refinement. You start with a high-level design, refine the design to pseudocode, and then refine the pseudocode to source code. This successive refinement in small steps allows you to check your design as you drive it to lower levels of detail. The result is that you catch high-level errors at the highest level, mid-level errors at the middle level, and low-level errors at the lowest level—before any of them becomes a problem or contaminates work at more detailed levels. Pseudocode makes changes easier. A few lines of pseudocode are easier to change than a page of code. Would you rather change a line on a blueprint or rip out a wall and nail in the two-by-fours somewhere else? The effects aren't as physically dramatic in software, but the principle of changing the product when it's most malleable is the same. One of the keys to the success of a project is to catch errors at the "least-value stage," the stage at which the least effort has been invested. Much less has been invested at the pseudocode stage than after full coding, testing, and debugging, so it makes economic sense to catch the errors early.”
Steve McConnell, Code Complete
“Steps in Building a Routine Many of a class's routines will be simple and straightforward to implement: accessor routines, pass-throughs to other objects' routines, and the like. Implementation of other routines will be more complicated, and creation of those routines benefits from a systematic approach. The major activities involved in creating a routine—designing the routine, checking the design, coding the routine, and checking the code—are typically performed in the order shown in Figure 9-2. Figure 9-2. These are the major activities that go into constructing a routine. They're usually performed in the order”
Steve McConnell, Code Complete
“Steps in Building a Routine Many of a class's routines will be simple and straightforward to implement: accessor routines, pass-throughs to other objects' routines, and the like. Implementation of other routines will be more complicated, and creation of those routines benefits from a systematic approach. The major activities involved in creating a routine—designing the routine, checking the design, coding the routine, and checking the code—are typically performed in the order shown in Figure 9-2. Figure 9-2. These are the major activities that go into constructing a routine. They're usually performed in the order shown”
Steve McConnell, Code Complete
“During production, your users need a chance to save their work before the program crashes and they are probably willing to tolerate a few anomalies in exchange for keeping the program going long enough for them to do that. Users don't appreciate anything that results in the loss of their work, regardless of how much it helps debugging and ultimately improves the quality of the program. If your program contains debugging code that could cause a loss of data, take it out of the production version.”
Steve McConnell, Code Complete
“Correctness means never returning an inaccurate result; returning no result is better than returning an inaccurate result. Robustness means always trying to do something that will allow the software to keep operating, even if that leads to results that are inaccurate sometimes. Safety-critical applications tend to favor correctness to robustness. It is better to return no result than to return a wrong result. The radiation machine is a good example of this principle. Consumer applications tend to favor robustness to correctness. Any result whatsoever is usually better than the software shutting down. The word processor I'm using occasionally displays a fraction of a line of text at the bottom of the screen. If it detects that condition, do I want the word processor to shut down? No. I know that the next time I hit Page Up or Page Down, the screen will refresh and the display will be back to normal.”
Steve McConnell, Code Complete
“Call an error-processing routine/object. Another approach is to centralize error handling in a global error-handling routine or error-handling object. The advantage of this approach is that error-processing responsibility can be centralized, which can make debugging easier. The tradeoff is that the whole program will know about this central capability and will be coupled to it. If you ever want to reuse any of the code from the system in another system, you'll have to drag the error-handling machinery along with the code you reuse.”
Steve McConnell, Code Complete
“Return an error code. You could decide that only certain parts of a system will handle errors. Other parts will not handle errors locally; they will simply report that an error has been detected and trust that some other routine higher up in the calling hierarchy will handle the error. The specific mechanism for notifying the rest of the system that an error has occurred could be any of the following: Set the value of a status variable Return status as the function's return value Throw an exception by using the language's built-in exception mechanism”
Steve McConnell, Code Complete
“Avoid duplicate code. Undoubtedly the most popular reason for creating a routine is to avoid duplicate code. Indeed, creation of similar code in two routines implies an error in decomposition. Pull the duplicate code from both routines, put a generic version of the common code into a base class, and then move the two specialized routines into subclasses.”
Steve McConnell, Code Complete
“One indication that a routine needs to be broken out of another routine is deep nesting of an inner loop or a conditional. Reduce the containing routine's complexity by pulling the nested part out and putting it into its own routine.”
Steve McConnell, Code Complete
“Class Quality Abstract Data Types Have you thought of the classes in your program as abstract data types and evaluated their interfaces from that point of view? Abstraction Does the class have a central purpose? Is the class well named, and does its name describe its central purpose? Does the class's interface present a consistent abstraction? Does the class's interface make obvious how you should use the class? Is the class's interface abstract enough that you don't have to think about how its services are implemented? Can you treat the class as a black box? Are the class's services complete enough that other classes don't have to meddle with its internal data? Has unrelated information been moved out of the class? Have you thought about subdividing the class into component classes, and have you subdivided it as much as you can? Are you preserving the integrity of the class's interface as you modify the class? Encapsulation Does the class minimize accessibility to its members? Does the class avoid exposing member data? Does the class hide its implementation details from other classes as much as the programming language permits? Does the class avoid making assumptions about its users, including its derived classes? Is the class independent of other classes? Is it loosely coupled? Inheritance Is inheritance used only to model "is a" relationships—that is, do derived classes adhere to the Liskov Substitution Principle? Does the class documentation describe the inheritance strategy? Do derived classes avoid "overriding" non-overridable routines? Are common interfaces, data, and behavior as high as possible in the inheritance tree? Are inheritance trees fairly shallow? Are all data members in the base class private rather than protected? Other Implementation Issues Does the class contain about seven data members or fewer? Does the class minimize direct and indirect routine calls to other classes? Does the class collaborate with other classes only to the extent absolutely necessary? Is all member data initialized in the constructor? Is the class designed to be used as deep copies rather than shallow copies unless there's a measured reason to create shallow copies?”
Steve McConnell, Code Complete
“Here's a summary list of the valid reasons to create a class: Model real-world objects Model abstract objects Reduce complexity Isolate complexity Hide implementation details Limit effects of changes Hide global data Streamline parameter passing Make central points of control Facilitate reusable code Plan for a family of programs Package related operations Accomplish a specific refactoring”
Steve McConnell, Code Complete
“NASA identifies reuse candidates at the ends of their projects. They then perform the work needed to make the classes reusable as a special project at the end of the main project or as the first step in a new project. This approach helps prevent "gold-plating"—creation of functionality that isn't required and that unnecessarily adds complexity.”
Steve McConnell, Code Complete
“NASA's Software Engineering Laboratory studied ten projects that pursued reuse aggressively (McGarry, Waligora, and McDermott 1989). In both the object-oriented and the functionally oriented approaches, the initial projects weren't able to take much of their code from previous projects because previous projects hadn't established a sufficient code base. Subsequently, the projects that used functional design were able to take about 35 percent of their code from previous projects. Projects that used an object-oriented approach were able to take more than 70 percent of their code from previous projects. If you can avoid writing 70 percent of your code by planning ahead, do it!”
Steve McConnell, Code Complete