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
Code Complete Quotes Showing 61-90 of 130
“Streamline parameter passing. If you're passing a parameter among several routines, that might indicate a need to factor those routines into a class that share the parameter as object data. Streamlining parameter passing isn't a goal, per se, but passing lots of data around suggests that a different class organization might work better.”
Steve McConnell, Code Complete
“Hide global data. If you need to use global data, you can hide its implementation details behind a class interface. Working with global data through access routines provides several benefits compared to working with global data directly. You can change the structure of the data without changing your program. You can monitor accesses to the data. The discipline of using access routines also encourages you to think about whether the data is really global; it often becomes apparent that the "global data" is really just object data.”
Steve McConnell, Code Complete
“Isolate complexity. Complexity in all forms—complicated algorithms, large data sets, intricate communications protocols, and so on—is prone to errors. If an error does occur, it will be easier to find if it isn't spread through the code but is localized within a class. Changes arising from fixing the error won't affect other code because only one class will have to be fixed—other code won't be touched. If you find a better, simpler, or more reliable algorithm, it will be easier to replace the old algorithm if it has been isolated into a class. During development, it will be easier to try several designs and keep the one that works best.”
Steve McConnell, Code Complete
“Another good reason to create a class is to model an abstract object—an object that isn't a concrete, real-world object but that provides an abstraction of other concrete objects. A good example is the classic Shape object. Circle and Square really exist, but Shape is an abstraction of other specific shapes.”
Steve McConnell, Code Complete
“Because it's a poor tradeoff to add complexity for dubious performance gains, a good approach to deep vs. shallow copies is to prefer deep copies until proven otherwise.”
Steve McConnell, Code Complete
“Example 6-11. Java Example of Enforcing a Singleton with a Private Constructor public class MaxId {    // constructors and destructors    private MaxId() {       <-- 1       ...    }    ...    // public routines    public static MaxId GetInstance() {       <-- 2       return m_instance;    }    ...    // private members    private static final MaxId m_instance = new MaxId();       <-- 3    ... } (1)Here is the private constructor. (2)Here is the public routine that provides access to the single instance. (3)Here is the single instance.”
Steve McConnell, Code Complete
“Here's a summary of when to use inheritance and when to use containment: If multiple classes share common data but not behavior, create a common object that those classes can contain. If multiple classes share common behavior but not data, derive them from a common base class that defines the common routines. If multiple classes share common data and behavior, inherit from a common base class that defines the common data and routines. Inherit when you want the base class to control your interface; contain when you want to control your interface.”
Steve McConnell, Code Complete
“The underlying message of all these rules is that inheritance tends to work against the primary technical imperative you have as a programmer, which is to manage complexity. For the sake of controlling complexity, you should maintain a heavy bias against inheritance.”
Steve McConnell, Code Complete
“inheritance is a powerful tool for reducing complexity because a programmer can focus on the generic attributes of an object without worrying about the details. If a programmer must be constantly thinking about semantic differences in subclass implementations, then inheritance is increasing complexity rather than reducing it.”
Steve McConnell, Code Complete
“If the derived class isn't going to adhere completely to the same interface contract defined by the base class, inheritance is not the right implementation technique. Consider containment or making a change further up the inheritance hierarchy.”
Steve McConnell, Code Complete
“Implement "is a" through public inheritance. When a programmer decides to create a new class by inheriting from an existing class, that programmer is saying that the new class "is a" more specialized version of the older class. The base class sets expectations about how the derived class will operate and imposes constraints on how the derived class can operate (Meyers 1998).”
Steve McConnell, Code Complete
“Inheritance is the idea that one class is a specialization of another class. The purpose of inheritance is to create simpler code by defining a base class that specifies common elements of two or more derived classes. The common elements can be routine interfaces, implementations, data members, or data types. Inheritance helps avoid the need to repeat code and data in multiple locations by centralizing it within a base class. When you decide to use inheritance, you have to make several decisions: For each member routine, will the routine be visible to derived classes? Will it have a default implementation? Will the default implementation be overridable? For each data member (including variables, named constants, enumerations, and so on), will the data member be visible to derived classes?”
Steve McConnell, Code Complete
“If a class contains more than about seven data members, consider whether the class should be decomposed into multiple smaller classes (Riel 1996). You might err more toward the high end of 7±2 if the data members are primitive data types like integers and strings, more toward the lower end of 7±2 if the data members are complex objects.”
Steve McConnell, Code Complete
“Be critical of classes that contain more than about seven data members. The”
Steve McConnell, Code Complete
“Containment is the simple idea that a class contains a primitive data element or object. A lot more is written about inheritance than about containment, but that's because inheritance is more tricky and error-prone, not because it's better. Containment is the work-horse technique in object-oriented programming.”
Steve McConnell, Code Complete
“Watch for coupling that's too tight. "Coupling" refers to how tight the connection is between two classes. In general, the looser the connection, the better. Several general guidelines flow from this concept: Minimize accessibility of classes and members. Avoid friend classes, because they're tightly coupled. Make data private rather than protected in a base class to make derived classes less tightly coupled to the base class. Avoid exposing member data in a class's public interface. Be wary of semantic violations of encapsulation. Observe the "Law of Demeter" (discussed in Design and Implementation Issues of this chapter). Coupling goes hand in glove with abstraction and encapsulation. Tight coupling occurs when an abstraction is leaky, or when encapsulation is broken.”
Steve McConnell, Code Complete
“The right response for the class author is to check out the class-interface file, modify the class-interface documentation, check the file back in, and then say "See if you can understand how it works now.”
Steve McConnell, Code Complete
“If you can't figure out how to use a class based solely on its interface documentation, the right response is not to pull up the source code and look at the implementation. That's good initiative but bad judgment. The right response is to contact the author of the class and say "I can't figure out how to use this class.”
Steve McConnell, Code Complete
“Make interfaces programmatic rather than semantic when possible. Each interface consists of a programmatic part and a semantic part. The programmatic part consists of the data types and other attributes of the interface that can be enforced by the compiler. The semantic part of the interface consists of the assumptions about how the interface will be used, which cannot be enforced by the compiler. The semantic interface includes considerations such as "RoutineA must be called before RoutineB" or "RoutineA will crash if dataMember1 isn't initialized before it's passed to RoutineA." The semantic interface should be documented in comments, but try to keep interfaces minimally dependent on documentation. Any aspect of an interface that can't be enforced by the compiler is an aspect that's likely to be misused. Look for ways to convert semantic interface elements to programmatic interface elements by using Asserts or other techniques.”
Steve McConnell, Code Complete
“One of the most effective guidelines is not to get stuck on a single approach. If diagramming the design in UML isn't working, write it in English. Write a short test program. Try a completely different approach. Think of a brute-force solution. Keep outlining and sketching with your pencil, and your brain will follow. If all else fails, walk away from the problem. Literally go for a walk, or think about something else before returning to the problem. If you've given it your best and are getting nowhere, putting it out of your mind for a time often produces results more quickly than sheer persistence can. You don't have to solve the whole design problem at once. If you get stuck, remember that a point needs to be decided but recognize that you don't yet have enough information to resolve that specific issue. Why fight your way through the last 20 percent of the design when it will drop into place easily the next time through? Why make bad decisions based on limited experience with the design when you can make good decisions based on more experience with it later? Some people are uncomfortable if they don't come to closure after a design cycle, but after you have created a few designs without resolving issues prematurely, it will seem natural to leave issues unresolved until you have more information (Zahniser 1992, Beck 2000).”
Steve McConnell, Code Complete
“A brute-force solution that works is better than an elegant solution that doesn't work. It can take a long time to get an elegant solution to work. In describing the history of searching algorithms, for example, Donald Knuth pointed out that even though the first description of a binary search algorithm was published in 1946, it took another 16 years for someone to publish an algorithm that correctly searched lists of all sizes (Knuth 1998). A binary search is more elegant, but a brute-force, sequential search is often sufficient. When in doubt, use brute force. — Butler Lampson”
Steve McConnell, Code Complete
“Summary of Design Heuristics Here's a summary of major design heuristics: More alarming, the same programmer is quite capable of doing the same task himself in two or three ways, sometimes unconsciously, but quite often simply for a change, or to provide elegant variation. — A. R. Brown W. A. Sampson Find Real-World Objects Form Consistent Abstractions Encapsulate Implementation Details Inherit When Possible Hide Secrets (Information Hiding) Identify Areas Likely to Change Keep Coupling Loose Look for Common Design Patterns The following heuristics are sometimes useful too: Aim for Strong Cohesion Build Hierarchies Formalize Class Contracts Assign Responsibilities Design for Test Avoid Failure Choose Binding Time Consciously Make Central Points of Control Consider Using Brute Force Draw a Diagram Keep Your Design Modular”
Steve McConnell, Code Complete
“The concept of modularity is related to information hiding, encapsulation, and other design heuristics. But sometimes thinking about how to assemble a system from a set of black boxes provides insights that information hiding and encapsulation don't, so the concept is worth having in your back pocket.”
Steve McConnell, Code Complete
“Keep Your Design Modular Modularity's goal is to make each routine or class like a "black box": You know what goes in, and you know what comes out, but you don't know what happens inside.”
Steve McConnell, Code Complete
“Keep Coupling Loose Coupling describes how tightly a class or routine is related to other classes or routines. The goal is to create classes and routines with small, direct, visible, and flexible relations to other classes and routines, which is known as "loose coupling." The concept of coupling applies equally to classes and routines, so for the rest of this discussion I'll use the word "module" to refer to both classes and routines. Good coupling between modules is loose enough that one module can easily be used by other modules.”
Steve McConnell, Code Complete
“Don't use a boolean variable as a status variable. Use an enumerated type instead. It's common to add a new state to a status variable, and adding a new type to an enumerated type requires a mere recompilation rather than a major revision of every line of code that checks the variable. Use access routines rather than checking the variable directly. By checking the access routine rather than the variable, you allow for the possibility of more sophisticated state detection. For example, if you wanted to check combinations of an error-state variable and a current-function-state variable, it would be easy to do if the test were hidden in a routine and hard to do if it were a complicated test hard-coded throughout the program.”
Steve McConnell, Code Complete
“Identify items that seem likely to change. If the requirements have been done well, they include a list of potential changes and the likelihood of each change. In such a case, identifying the likely changes is easy. If the requirements don't cover potential changes, see the discussion that follows of areas that are likely to change on any project. Separate items that are likely to change. Compartmentalize each volatile component identified in step 1 into its own class or into a class with other volatile components that are likely to change at the same time. Isolate items that seem likely to change. Design the interclass interfaces to be insensitive to the potential changes. Design the interfaces so that changes are limited to the inside of the class and the outside remains unaffected. Any other class using the changed class should be unaware that the change has occurred. The class's interface should protect its secrets. Here are a few areas that are likely to change: Business rules. Business rules tend to be the source of frequent software changes. Congress changes the tax structure, a union renegotiates its contract, or an insurance company changes its rate tables. If you follow the principle of information hiding, logic based on these rules won't be strewn throughout your program. The logic will stay hidden in a single dark corner of the system until it needs to be changed.”
Steve McConnell, Code Complete
“Encapsulation says that, not only are you allowed to take a simpler view of a complex concept, you are not allowed to look at any of the details of the complex concept. What you see is what you get—it's all you get!”
Steve McConnell, Code Complete
“Levels of Design Design is needed at several different levels of detail in a software system. Some design techniques apply at all levels, and some apply at only one or two. Figure 5-2 illustrates the levels. Figure 5-2. The levels of design in a program. The system (1) is first organized into subsystems (2). The subsystems are further divided into classes (3), and the classes are”
Steve McConnell, Code Complete
“modern software is inherently complex, and no matter how hard you try, you'll eventually bump into some level of complexity that's inherent in the real-world problem itself. This suggests a two-prong approach to managing complexity: Minimize the amount of essential complexity that anyone's brain has to deal with at any one time. Keep accidental complexity from needlessly proliferating. Once you understand that all other technical goals in software are secondary to managing complexity, many design considerations become straightforward.”
Steve McConnell, Code Complete