Design

  • Watch the initial design. There should be a clear "high-level" design to the system, and it should be fairly clean. (For example, the operating systems class has a simulation. The people who drove their program by the next input card had a horrible time - had to worry about events occurring all over the place. Those who treated it as a simulation, finding the next event (card or internal), had a program structure that matched the problem structure, and it worked much better.)
  • Use Parnas' information hiding approach. Basically, this says that each module should have a secret (e.g., its true representation). No other module should rely on the secret, but only the interface. If the secret changes, it should only affect one module. This goes to the level of the program specification as well: if the spec says "do 100 things", there should only be one place that knows the number is 100. Another interpretation of this is: never have the same thing in two places, because that provides an opportunity for inconsistency.
  • Insert "points of leverage". For example, in the simulation program above, the "right" structure has only one place where the next event is generated. This provides a single place you can look at to make sure it's right.
  • Get everything "const-correct". If a routine shouldn't modify its arguments, it should say so with "const". This is especially important in C++. (And it's best to get it right from the beginning - trying to fix it causes "ripples".) C++ lets you say whether methods are "const", which matches up with the accessor/mutator/iterator breakdown.

Copyright 1994-2010, William C. Wake - William.Wake@acm.org