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.
|