Code Complete
Steve McConnell Microsoft Press 1995

Summary

Code Complete is programming classic. It is 900 pages of intelligent and fascinating discussion about coding software.

Introduction

This book is not about how to program in a particular language, how to use SSADM or other methodologies. This book is about improving the way that you work throughout the development cycle.

The author describes the development process as being everything from the technical, detailed design stage, right through to the integrated testing. This is the jurisdiction, or domain, of the programmer.

With an immense bibliography, the author has combined theories, common practices and hard data to make his points. Sometimes, however, he completely contradicts the commonplace practices. Here is a man who supports established practices, but backs his own convictions where they differ. Subjectivity surfaces on occasion with statements such as "If you come across one of these clowns, ask him the following". On the whole, there is the distinct impression that the author was motivated to write this book in order to help programmers, and related IT staff.

References to personal experience punctuate bibliographic references in order to put the point across. Clearly this man knows his stuff, and is not simply trying to pedal his own particular point of view that has never been proven. The author has developed his techniques over time, and has then decided to write a book on the subject. Where the purpose of his methodologies is nebulous, he backs them up with hard data.

Summary of Points

Here is a summary of the points that I believe are particularly of note.

  1. Software Accretion Method The author recommends an accretion approach to software construction. This means the method of initially building the most basic working system possible, and then adding on layers piece by piece.
  2. Prerequisites It seems obvious, but it is important to have all of the requirements in place before time is spent on detailed design or construction. Ensure that all the system prerequisites are outlined. The author also describes the "Myth of Stable Requirements". The important thing is to manage changes properly.
  3. Use of PDL This is a section that I found particularly fascinating, in the section dealing with designing Routine. PDL stands for Programming Definition Language. PDL is a language similar in purpose to pseudo code, but is more abstract, using statements that resemble spoken English. The method here is to design a routine in PDL and then use the statements to form the basis of the routine. The PDL statements become the comment lines in the routine, and the functionality is filled in between the comments. This method allows the design of the routine to remain a constant, and to be clearly visible when viewing the code.
  4. Routines and Modules The author spends a lot of time describing quality. This is particularly apparent with coding modules and routines. The author lists good and bad reasons for writing routines, and how to write quality routines and modules.
  5. Abstraction and Naming One of the most recurring themes throughout the book is abstraction. This theme is prominent when the author discusses naming standards. For routines, modules, variables, constants and literals, abstract naming standards are extremely useful. They allow code reading to be made easier, and help to describe the program in the problem domain.
  6. Layout and Style After mentioning quality in routine design and use, the author outlines the correct layout and styles of coding to use. Good and bad examples are shown, and the reasons for the choice of layout are mentioned. Also mentioned is how much of a sensitive area layout and programming styles are, including the hundred years war that is the GOTO debate.
  7. Management The book is not only focused on the programmer. There is a section that is for the attention of the Programming Manager. This deals with everything from planning and scheduling right through to managing the people. When discussing planning, the importance of measurement is also mentioned. Apart from progress, quality also needs to be measured. Several methods for measuring are suggested, including formal and informal reviews.
  8. Testing There are more opinions and suggestions for testing than just about anything else in software development. This book is no exception, however, the author describes testing in sections of Unit testing, Functional Testing, Integration Testing and Live Testing. Methodologies for all of these areas are outlined.
  9. Optimisation There may be times when a program needs to become more streamlined. The author discusses the use of code tuning techniques, and the most important issue of when to optimise and when to leave it alone.

Organising Straight Line Code.

Organising Straight Line Code.

Statements that must be in a specific order.

Statements who's order does not matter.

Using Conditions.

IF statements.

IF chains:

CASE statements.

Tips:

Controlling Loops.

Select the kind of Loop to use.

When to use WHILE:

When to use EXIT DO:

When to use FOR/NEXT:

Controlling the Loop.

Entry points:

Process the Middle of the Loop:

Exiting the Loop:

Checking End Points.

Using Loop Variables.

How Long should a Loop be?

Creating Loops form the inside out.

Correspondance between loops and arrays.

Use FOR EACH or other language functions where possible.

Unusual Control Structures.

GOTO.

RETURN/EXIT.

Recursion.

  • These are routines that call themselves.
  • They can provide very elegant solutions.
  • These can fill up stack space.

    Tips:

    General Control Issues.

    Boolean Expressions.

    Write Numeric expressions in numerical value order (MIN < X AND X < MAX)

    Compound Statements.

    NULL Statements.

    Taming Dangerously Deep Nesting.

    The Power of Structured Programming.

    Control Structures and Complexity.

    Good design reduces complexity.

    How to reduce complexity:

    Measure complexity by using a count:

    Evaluate Complexity:

    Consider other ways of measuring complexity:

    The Power of Data Names

    The Power of Data Names

    Considerations in choosing good names

    The main point of naming variables is that the name accurately describes the purpose.

    The name should be problem-orientated. This means that the name is related to what is being achieved not how it is being achieved.

    The optimum name length is suggested to be between 8 and 20 characters, typically about 16.

    The Effect of Scope on Variable names.

    Typically, longer names are better than shorter ones. This is not always the case: if a variable is to be used as a loop counter, it is acceptable to call it "a", or "i". The reason for this is that the variable is a temporary variable only, which will not exist outside of the scope of the procedure in which it is used.

    If a variable is to be used throughout a module, then it should be named more meaningfully.

    Basically, the length of a variable should reflect it's importance.

    Computed-Value Qualifiers in Variable Names.

    Many programmers use prefixes to denote calculated values (e.g. Ttl, Sum, Avg). If using this approach, the important thing to remember is to be consistent.

    Naming Specific Types of Data

    The Power of Naming Conventions

    Any naming convention is better than none at all.

    Informal Naming Conventions

    Here are some guidelines for creating a language-independent naming convention.

    Hungarian Notation

    This naming convention consists of naming the variable in three parts:

    1. Variable Type.
    2. Prefix.
    3. Qualifier.

    This convention is widely used in C.

    The main disadvantage with this is that the variables will never have abstract names.

    Short Names

    When using short names, follow these guidelines:

    It is noted that some programmers use phonetic names (before = b4), but I would not recommend this.

    Kinds of Names to avoid

    Summary

    General Issues in Using Variables

    Scope

    The key is to minimise the scope of variables. If variables are global, the program is likely to be easier to write, but if they are not, the program will be easier to read.

    Ensure that variable references are kept together.

    Persistence

    Binding Time

    There are three types of data binding.

    1. Code Time Binding This refers to hard-coded variables that are assigned values in the source code.
    2. Compiler Time Binding This refers to variables that are assigned values from constants.
    3. Run Time Binding This occurs when the program is running, and variables are assigned dynamic values.

    Relationship between Data Structures and Control Structures

    Use each Variable for one purpose only

    It is confusing to use a single variable for more than one purpose. It is possible to do so subtly, but it is not recommended.

    Avoid variable names with hidden meanings. The meaning may be clear to the developer, but not to anybody else.

    Declare all used variables and remove declarations of unused variables.

    Global Variables

    Global variables are tricky. They can be very useful, but also extremely risky to use.

    1. Common Problems
      • Inadvertent changes to global data.
      • Aliasing. This is a strange situation, where a global variable is passed to a routine as a parameter, and the routine changes the global data.
      • Re-entrant code problems. These can occur when multiple threads of an application use the same global data.
      • Hinders code re-use. A routine can't be plugged in if global data needs to be set up.
      • Can't Modularise. If global data is used, the system can't be separated into modules.
    2. Reasons to use Global Data
      • Preserves Global Values.
      • Allows substitution of named constants in languages that do not support this.
      • Streamlines use of very commonly used data.
      • Reduces "Tramp Data". This refers to data that is passed as parameters to a routine that are only passed to another routine within the first. They are not actually used within the first routine.
    3. How to Reduce the Risks of Using Global Data
      • Only use Global Data if necessary.
      • Differentiate between global data and module data.
      • Use Naming Conventions.
      • Create a list of Global Variables.
      • Lock Global Variables when they are in use. Do this by implementing a status variable for each global variable.
      • Don't simply create one single global structure and pass it everywhere. This is just pretending to not use Global Data.
    4. Use Access Routines instead of Global Data.
      Advantages are:
      • Centralised control.
      • Ensures that References are firewalled.
      • Promotes Information Hiding.
      • Allows Abstract Naming.
      Advantages:
      • All Routines must go through one Access Routine.
      • Splits Module Data and Global Data.
      • Builds a level of abstraction into the code.
      • Keeps accesses at the same level of abstraction.

    Summary

    Fundamental Data Types

    General Numbers

    General things to remember:

    Integers

    Floating Point Numbers

    Characters and Strings

    Use Named constants.

    Booleans

    Enumerations

    Named Constants

    Arrays

    Summary

    Always ensure that the correct data type is used for the correct purpose.


    ©John Mann, 2000