This is the best book I’ve read on software best practices: Steve McConnell’s Code Complete. It is full of gems. It is so good that I decided to summarise it and placed it on my desktop so I could look over it whenever I have the time. So here’s the summary. It’s far better to read the actual book.
Control Structures Issues
- Do expressions use true and false rather than 1 and 0?
- Are boolean values compared to true and false implicitly?
- Are numeric values compared to their test values explicitly?
- Have expressions been simplified by the addition of new boolean variables and the use of boolean functions and decision tables?
- Are boolean expressions stated positively?
- Do pairs of braces balance?
- Are braces used everywhere they’re needed for clarity?
- Are logical expressions fully parenthesized?
- Have tests been written in number-line order?
- Do Java tests uses cases a.equals(b) style instead of a==b when appropriate?
- Are null statements obvious?
- Have nested statements been simplified by retesting part of the conditional, converting to if-then-else or case statements, moving nested code into its own routine, converting to a more object oriented design, or have they been improved in some other way?
- If a routine has a decision count of more than 10, is there a good reason for not designing it?
Loops
Loop selection and creation
- Is a while loop used instead of a for loop if appropriate?
- Was the loop created from the inside out?
Entering the loop
- Is the loop entered from the top?
- Is initialisation code directly before the loop?
- If the loop is an infinite loop or an event loop, is it constructed cleanly rather than using a kludge such as for i = 1 to 9999?
- If the loop is a C++, C, or Java for loop, is the loop header reserved for loop control code?
Inside the loop
- Does the loop use {and} or their equivalent to enclose the loop body and prevent problems arising from improper modifications?
- Does the loop body have something in it? is it nonempty?
- Are housekeeping chores grouped, at the beginning or at the end of the loop?
- Does the loop perform one and only one function, as a well defined routine does?
- Is the loop short enough to view all at once?
- Is the loop nested to 3 levels or less?
- Have long loops contents been moved into their own routine?
- If the loop is long, is it especially clear?
Loop indexes
- If the loop is a for loop, does the code inside it avoid monkeying with the loop index?
- Is a variable used to save important loop-index values rather than using the loop index outside the loop?
- Is the loop index an ordinal type or an enumerated type – not floating point?
- Does the loop index have a meaningful name?
- Does the loop avoid index cross talk?
Exiting the loop
- Does the loop end under all possible conditions?
- Does the loop use safety counters – if you instituted a safety-counter standard?
- Is the loop’s termination condition obvious?
- If break or continue are used, are they correct?
Defensive Programming
General
- Does the routine protect itself from bad data?
- Have you used assertions to document assumptions, including preconditions and post conditions?
- Have assertions been used only to document conditions that should never occur?
- Does the architecture or high-level design specify a specific set of error handling techniques?
- Does the architecture or high level design specify whether error handling should favour robustness or correctness?
- Have barricades been created to contain the damaging effects of errors and reduce the amount of code that has to be concerned about error processing?
- Have debugging aids been used in the code?
- Have debugging aids been installed in such a way that they can be activated or deactivated without a great deal of fuss?
- Is the amount of defensive programming code appropriate – neither too much or too little?
- Have you used offensive programing techniques to make errors difficult to overlook during development?
Exceptions
- Has your project defined a standardized approach to exception handling?
- Have you considered alternatives to using an exception?
- Is the error handled locally rather rather than throwing a nonlocal exception, if possible?
- Does the code avoid throwing exceptions in constructors and destructors?
- Are all exceptions at the appropriate levels of abstraction for the routines that throw them?
- Does each exception include all relevant exception background information?
- Is the code free of empty catch blocks?(Or if an empty catch block truly is appropriate, is it documented?)
Security Issues
- Does the code that checks for bad data input data check for attempted buffer overflows, SQL injection, HTML injection, integer overflows, and other malicious inputs?
- Are all error-return codes checked?
- Are all exceptions caught?
- Do error messages avoid providing information that would help an attacker break into the system?
Design in Construction
Design Practices
- Have you iterated, selecting the best of several attempts rather than the first attempt?
- Have you tried decomposing the system in several different ways to see which way will work best?
- Have you approached the design problem both from the top down and from the bottom up?
- Have you prototyped risky or unfamiliar parts of the system, creating the absolute minimum amount of throwaway code needed to answer specific questions
- Have your design been reviewed, formally or informally by others?
- Have you driven the design to the point that its implementation seems obvious?
- Have you captured your design work using an appropriate technique such as a Wiki, email, flip charts, digital photography, UML, CRC cards, or comments in the code itself?
Design Goals
- Does the design adequately address issues that were identified and deferred at the architectural level?
- Is the design stratified into layers?
- Are you satisfied with the way the program has been decomposed into subsystems, packages and classes?
- Are you satisfied with the ways the classes have been decomposed into routines?
- Are classes designed for minimal interaction with each other?
- Are classes and subsystems designed so that you can use them in other systems?
- Will the program be easy to maintain?
- Is the design lean? Are all its parts strictly necessary?
- Does the design use standard techniques and avoid exotic, hard-to-understand elements?
- Overall, does the design help minimise both accidental and essential complexity?
Fundamental Data Types
Numbers in General
- Does the code avoid magic numbers?
- Does the code anticipate divide by zero errors?
- Are type conversions obvious?
- If variables with 2 different types are used in the same expression, will the expression be evaluated as you intend it to be? you know a float with an int, you know what will happen right?
- Does the code avoid mixed-type comparisons?
- Does the program compile with no warnings?
Integers
- Do expressions that use integer division work the way they’re meant to?
- Do integer expressions avoid integer-overflow problems?
Floating-point numbers
- Does the code avoid additions and subtractions on numbers with greatly different magnitudes?
- Does the code systematically prevent rounding errors?
- Does the code avoid comparing floating point numbers for equality?
Characters and Strings
- Does the code avoid magic characters and strings?
- Are references to strings free of off-by-one errors?
- Does C code treat string pointers and character arrays differently?
- Does C code follow the convention of declaring strings to be length CONSTANT + 1?
- Does C code use arrays of characters rather than pointers, when appropriate?
- Does C code initialise strings to NULLs to avoid endless strings?
- Does C code use strncpy() rather than strcpy()? And strncat() and strncmp()?
Boolean Variables
- Does the program use additional boolean variables to document conditional tests?
- Does the program use additional boolean variables to simplify conditional tests?
Enumerated Types
- Does the program use enumerated types instead of named constants for their improved readability, reliability, and modifiability?
- Does the program use enumerated types instead of boolean variables when a variable’s use cannot be completely be captured with true and false?
- Do tests using enumerated type reserved for invalid values?
- Is the first entry in an enumerated type reserved for invalid?
Named Constants
- Does the program use named constants for data declarations and loop limits rather than magic numbers?
- Have named constants been used consistently? – meaning its not used as named constants in some places and as literals in others?
Arrays
- Are all array indexes within the bonds of the array?
- Are all array references free of off-by-one errors?
- Are all subscripts on multidimensional arrays in the correct order?
- In nested loops, is the correct variable used as the array subscript, avoiding loop index cross talk?
Creating Types
- Does the program use a different type for each kind of data that might change?
- Are type names oriented toward the real-world entities the types represent rather than toward programming language types?
- Are the types names descriptive enough to help document data declarations?
- Have you avoided redefining predefined types?
- Have you considered creating a new class rather than simply redefining a type?
General Issues in using variables
Initialising variables
- Does each routine check input parameters for validity?
- Does the code declare variables close to where they’re first used?
- Does the code initialise variables as they’re declared, if possible?
- Does the code initialise variables close to where they’re first used, if it isn’t possible to declare and initialise them at the same time?
- Are counters and accumulators initialised properly and, if necessary, reintialised each time they are used?
- Are variables reinitialised properly in code that’s being executed repeatedly?
- Does the code compile with no warnings from the compiler?
- If your language uses implicit declarations, have you compensated for the problems they cause?
Other general issues in using data
- Do all variables have the smallest possible scope possible?
- Are all references to variables as close together as possible, both from each reference to a variable to the next reference and in total live time?
- Do control structures correspond to the data types?
- Are all declared variables being used?
- Are all variables bound at appropriate times – that is, are you striking a conscious balance between the flexibility of late binding and the increased complexity associated with late binding?
- Does each variable have one and only one purpose?
- Is each variable’s meaning explicit, with no hidden meanings?
High Quality Routines
Big Picture Issues
- Is the reason for creating the routine sufficient?
- Have all parts of the routine that would benefit from being put into routines of their own been put into routines of their own?
- Is the routine’s name a strong, clear verb-plus-object name for a procedure or a description of the return value for a function?
- Does the routine’s name describe everything the routine does?
- Have you established naming conventions for common operations?
- Does the routine have strong, functional cohesion – doing one and only one thing and doing it well?
- Do the routines have loose coupling – are the routine’s connections to other routines small, intimate, visible, and flexible?
- Is the length of the routine determined naturally by its function and logic, rather than by an artificial coding standard
Parameter- Passing issues
- Does the routine’s parameter list, taken as a whole, present a consistent interface abstraction?
- Are the routine’s parameters in a sensible order, including matching the order of parameters in similar routines?
- Are interface assumptions documented?
- Does the routine have 7 or fewer parameters?
- Is each input parameter used?
- Is each output parameter used?
- Does the routine avoid using input parameters as working variables?
- If the routine is a function, does it return a valid value under all possible circumstances?
Naming Variables
General Naming Considerations
- Does the name fully and accurately describe what the variable represents?
- Does the name refer to the real world problem rather than to the programming language solution?
- Is the name long enough that you don’t have to puzzle it out?
- Are computed value qualifiers, if any, at the end of the name?
- Does the name use Count or Index instead of Num?
Naming specific kinds of Data
- Are loop index names meaningful (something other than i, j, or k if the loop is more than one or two lines long or is nested)?
- Have all ‘temporary variables’ been renamed to something more meaningful?
- Are boolean variables names so that their meanings when they’re true are clear?
- Do enumerated-type names include a prefix or suffix that indicates the category-for example, Color_ for Color_red, color_green, color_blue and so on
- Are named constants named for the abstract entities they represent rather than the numbers they refer to?
Naming Conventions
- Does the convention distinguish among local, class, and global data?
- Does the convention distinguish among type names, named constants, enumerated types and variables?
- Does the convention identify input-only parameters to routines in languages that don’t enforce them?
- Is the convention as comparable as possible with standard conventions for the language?
- Are names formatted for readability?
Short Names
- Does the code use long names(unless it’s necessary to use short ones?)?
- Does the code avoid abbreviations that only save one character?
- Are all words abbreviated consistently?
- Are the names pronounceable?
- Are names that could be misread or mispronounced avoided?
- Are short names documented in translation tables?
Common Naming Problems: Have you avoided….
- Names that are misleading?
- Names with similar meaning?
- Names that are different by one or two characters?
- Names that sound familiar?
- Names that use numerals?
- Names intentionally mispelled to make them shorter?
- Names that are commonly misspelled in English?
- Names that conflict with standard library routines names or with predefined variable names?
- Totally arbitrary names?
- Hard to read characters?
Checklist: Summary of Refactoring
Data Level Refactoring
- Replace a magic number with a named constant
- Rename a variable with a clearer or more informative name
- Move an expression inline
- Replace an expression with a routine
- Introduce an intermediate variable
- Convert a multiuse variable to a multiple single-use variables
- Use a local variable for local purposes rather than a parameter
- Convert a data primitive to a class
- Convert a set of type codes to a class or an enumeration
- Convert a set of type codes to a class with subclasses
- Change an array to an object
- Encapsulate a collection
- Replace a traditional record with a data class
Statement Level Refactoring
- Decompose a boolean expression
- Move a complex boolean expression into a well-named boolean function
- Consolidate fragments that are duplicated within different parts of a conditional
- Use break or return instead of a loop control variable
- Return as soon as you know the answer instead of assigning a return value within nested if-then-else statements
- Replace conditionals(especially repeated case statements) with polymorphism
- Create and use null objects instead of testing for null values
Routine Level refactoring
- Extract a routine
- Move a routine’s code inline
- Convert a long routine to a class
- Substitute a simple algorithm for a complex algorithm
- Add a parameter
- Remove a parameter
- Separate query operations from modification operations
- Combine similar routines by parameterising them
- Separate routines whose behaviour depends on parameters passed in
- Pass a whole object rather than specific fields
- Pass specific fields rather than a whole object
- Encapsulate downcasting
Class Implementation Refactoring
- Change value objects to reference objects
- Change reference objects to value objects
- Replace virtual routines with data initializations
- Change member routine or data placement
- Extract specialised code into a subclass
- Combine similar code into a superclass
Class Interface refactorings
- Move a routine to another class
- Convert one class to two
- Eliminate a class
- Hide a delegate
- Remove a middleman
- Replace inheritance with delegation
- Replace delegation with inheritance
- Introduce a foreign routine
- Introduce an extension class
- Encapsulate an exposed member variable
- Remove Set() routines for fields that cannot be changed
- Hide routines that are not intended to be used outside the class
- Encapsulate unused routines
- Collapse a superclass and subclass if their implementations are very similar
System Level Refactorings
- Create a definitive reference source for data you can’t control
- Change unidirectional class association to bidirectional class association
- Change bidirectional class association to unidirectional class association
- Provide a factory routine rather than a simple constructor
- Replace error codes with exceptions or vice versa
Organising Straight line code
- Does the code make dependencies among statements obvious?
- Do the names of routines make dependencies obvious?
- Do parameters to routines make dependencies obvious?
- Do comments describe any dependencies that would otherwise be unclear?
- Have housekeeping variables been used to check for sequential dependencies in critical sections of the code?
- Does the code read from top to bottom?
- Are related statements grouped together?
- Have relatively independent groups of statements been moved into their own routines?
Table driven Methods
- Have you considered table-driven methods as an alternative to complicated logic?
- Have you considered table driven methods as an alternative to complicated inheritance structures?
- Have you considered storing the table’s data externally and reading it at run time so that the data can be modified without changing code?
- If the table cannot be accessed directly via a straightforward array index, have you put the access-key calculation into a routine rather than duplicating the index calculation in the code?
Unusual Control Structures
return
- Does each routine use return only when necessary?
- Do returns enhance readability?
Recursion
- Does the recursion routine include code to stop the recursion?
- Does the routine use a safety counter to guarantee that the routine stops?
- Is recursion limited to one routine?
- Is the routine’s depth of recursion within the limits imposed by the size of the program’s stack?
- Is recursion the best way to implement the routine? Is it better than simple iteration?
goto
- Are gotos used only as a last resort, and then only to make code more readable and maintanable?
- If a goto is used for the sake of efficiency, has the gain in efficiency been measured and documented?
- Are gotos limited to one label per routine?
- Do all gotos go forward, not backward?
- Are all goto labels used?
Unusual Data Types
Structures
- Have you used structures instead of naked variables to organise and manipulate groups of related data?
- Have you considered creating a class as an alternative to using structure?
Global data
- Are all variables local or of class scope unless they absolutely need to be global?
- Do variable naming convention differentiate among local, class and global data?
- Are all variables documented?
- Is the code free of pseudo-global data – mammoth objects containing a mishmash of data that’s passed to every routine?
- Are access routines used instead of global data?
- Do access routines provide a level of abstraction beyond the underlying data type implementations?
- Are all related access routines at the same level of abstraction?
Pointers
- Are pointer operations isolated in routines?
- Are pointer references valid, or could the pointer be dangling?
- Does the code check pointers for validity before using them?
- Is the variable that the pointer references checked for validity before it’s used?
- Are pointers set to null after they’re freed?
- Does the code use all the pointer variables needed for the sake of readability?
- Are pointers in linked list freed in the right order?
- Does the program allocate a reserve parachute of memory so that it can shut down gracefully if it runs out of memory?
- Are pointers used only as a last resort, when no other method is available?
Using Conditionals
if-then Statements
- Is the nominal path through the code clear?
- Do if-then tests branch correctly on equality?
- Is the else clause present and documented?
- Is the else clause correct?
- Are the if and else clauses used correctly – not reversed?
- Does the normal case follow the if rather than the else?
if-then-else-if chains
- Are complicated tests encapsulated in boolean function calls?
- Are the most common cases tested first?
- Are all cases covered?
- Is the if-then else-if chain the best implementation – better than a case statement?
Case statements
- Are cases ordered meaningfully?
- Are the actions for each case simple – calling other routines if necessary?
- Does the case statement test a real variable, not a phony one that’s made up solely to use and abuse the case statement?
- Is the use of the default clause legitimate?
- Is the default clause used to detect and report unexpected cases?
- In C, C++, Java, does the end of each case have a break?
- Use retesting to refactor nested if-else
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?
- Dos 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 overidding non-overridable routines?
- Are common interfaces, data, and behaviour 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 7 data members or fewer?
- Does the class minimise 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 initialised 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?
Language-Specific Issues
- Have you investigated the language-specific issues for classes in your specific programming language?


I recently read the book and I think its simply awesome. I got to learn so many things from it.
I didn’t really understand the chapter on Table-Driven Methods, do you know of any other resources related to this topic ? I want to learn more about this programming technique. It seems simply fascinating
hi tabman
sorry! i dont have any of the resources on table-driven methods.