26.2 Design Factors
Now that we know what we want in a design, let's see
what we need to get there. As the science of programming has
developed, people have discovered several factors that go into a good
program design. You don't have to create a program
with these factors in mind, but most programs that do a good job of
satisfying the design goals listed above are designed with these
factors in mind:
- Simplicity
-
The simplest code that does the job is usually the best.
It's the most reliable because it has the fewest
things that can go wrong. Doing as little as possible also means that
the code is cost-efficient to produce.
There are other benefits as well. Simple code is easy to maintain and
enhance, so future programming costs are reduced, too.
Finally, the less you give a user to do, the less he can screw up.
That generally means that the simplest software is the easiest to
use.
- Information hiding
-
A good design provides a minimal interface to the user and hides as many
of the details as possible.
- Expandability
-
Can the program be quickly and easily expanded? For example,
suppose you are writing a word processor. How difficult would it be
to use a different character set, such as Spanish or Korean? Better
yet, how difficult would it be to adapt it to a more complex
character set, such as Hebrew or Chinese?
Remember when PCs first came out: the maximum amount of memory you
could have was 640K, and the early MS-DOS filesystem (FAT12)
couldn't handle a disk bigger than 16MB. Both these
limits have proven to be terribly inadequate.
- Testable
-
If your program can be tested
and
tested easily, it will be tested. Testing leads to reliability. (Note
that extensive testing should never be used as a substitute for a
good design. Testing can only show the presence of defects, not their
absence.)
But programs have a life of their own. They don't
stop with version 1.0. There are a few design attributes that are
appreciated by the people who have to maintain and enhance your code.
- Reusability/generality
-
Writing code takes a lot of time and effort. Using already written
code (assuming it does the job) takes very little time and effort.
Good code design calls for your code to be reusable whenever
possible.
For example, the linked list structure is extremely useful. In C
everyone tends to create her own linked list package (a linked list
of names, a list of messages, a list of events, etc.). The result is
a lot of redundant code.
C++ has the STL, which contains a container class
(std::list) that gives you all the features of a
linked list. (Most of the time it's implemented as a
linked list, but you don't have to know about the
implementation details.) Because this container is generic, C++
programmers don't have to keep re-creating the same
code over and over again.
A good design makes maximum use of reusable code and at the same time
is itself designed so that it can be reused.
Different circumstances require different design criteria. I know of
one oil company that spends lots and lots of money on making sure
that their software is correct and extremely accurate. This software
has one job: simulating how one pipe threads on to another. I asked
them why they had a whole department devoted to pipe threads and they
told me, "When a thread fails, we generally lose
about fifty million dollars and a dozen lives."
Their design values accuracy and verifiability. They want to be
really sure that their numbers are right. Lives depend on them.
On the other hand, I wrote a program to replace the standard Unix
command vacation because the existing Unix
command wouldn't work with our security system. The
command was released with minimal testing and other reliability
checks. After all, the existing command didn't work,
and if the new command didn't work, the
users didn't really lose anything.
|