when reviewing a system, I will pick a
random message or output symbol and
ask, “When does that happen?” I never
get a satisfactory answer.
There are methods of design and
documentation that facilitate checking that a programmer has considered
all possible cases (including such undesired events as incorrect input or the
need to correct an earlier transaction)
and provided appropriate mechanisms
for responding to them. When such
methods are used, people find serious
errors in software that has been tested
and used for years. When I talk or write
about such methods, I am often told by
colleagues, experienced students, and
reviewers that, “Nobody does that.”
They are right—that’s the problem!
Much of the fault lies with our
teaching. Computer science students
are not taught to work in disciplined
ways. In fact, the importance of disciplined analysis is hardly mentioned. Of
course, just telling students to be diligent is not enough. We need to:
˲ ˲ teach them what to do and how to
do it—even in the first course;
˲ ˲ use those methods ourselves in
every example we present;
˲ ˲ insist they use a disciplined approach in every assignment in every
course where they write programs;
˲ ˲ check they have inspected and tested their programs diligently, and
˲ ˲ test their ability to check code systematically on examinations.
Many of us preach about the importance of determining the requirements
a software product must satisfy, but we
do not show students how to organize
their work so they can systematically
produce a requirements specification
that removes all user-visible choices
from the province of the programmer.
Some of us advise students to avoid
dull work by automating it, but do not
explain that this does not relieve an engineer of the responsibility to be sure
the work was done correctly.
innovation and Disciplined Design
It has become modish to talk about
teaching creativity and innovation. We
need to tell students that inventiveness
is not a substitute for disciplined attention to the little details that make the
difference between a product we like
and a product we curse. Students need
to be told how to create and use check-
even sophisticated and
experienced purchasers
do not demand the
documentation that
would be evidence
of disciplined design
and testing.
lists more than they need to hear about
the importance of creativity.
It is obviously important to give
courses on picking the most efficient
algorithms and to make sure that students graduate prepared to understand current technology and use new
technology as it comes along, but neither substitutes for teaching them to
be disciplined developers.
Disciplined design is both teachable
and doable. It requires the use of the
most basic logic, nothing as fancy as
temporal logic or any of the best-known
formal methods. Simple procedures
can be remarkably effective at finding
flaws and improving trustworthiness.
Unfortunately, they are time-consuming and most decidedly not done by senior colleagues and competitors.
Disciplined software design requires three steps:
1. Determine and describe the set of
possible inputs to the software.
2. Partition the input set in such a
way that the inputs within each partition are all handled according to a
simple rule.
3. State that rule.
Each of these steps requires careful
review:
1. Those who know the application
must confirm that no other inputs can
ever occur.
2. Use basic logic to confirm that every input is in one—and only one—of
the partitions.
3. Those who know the application, for example, those who will use
the program, must confirm the stated rule is correct for every element of
the partition.
These rules seem simple, but reality
complicates them:
1. If the software has internal memory, the input space will comprise
event sequences, not just current values. Characterizing the set of possible
input sequences, including those that
should not, but could, happen is difficult. It is very easy to overlook sequences that should not happen.
2. Function names may appear in
the characterization of the input set.
Verifying the correctness of the proposed partitioning requires knowing
the properties of the functions named.
3. The rule describing the output
value for some of the partitions may
turn out to be complex. This is generally a sign that the partitioning must be
revised, usually by refining a partition
into two or more smaller partitions. The
description of the required behavior for
a partition should always be simple but
this may imply having more partitions.
Similar “divide and conquer” approaches are available for inspection
and testing.
While our failure to teach students
to work in disciplined ways is the primary problem, the low standards of
purchasers are also a contributing factor. We accept the many bugs we find
when a product is first delivered, and
the need for frequent error-correcting
updates, as inevitable. Even sophisticated and experienced purchasers do
not demand the documentation that
would be evidence of disciplined design and testing.
We are caught in a catch- 22 situation:
˲ ˲ Until customers demand evidence
that the designers were qualified and
disciplined, they will continue to get
sloppy software.
˲ ˲ As long as there is no better software, we will buy sloppy software.
˲ ˲ As long as we buy sloppy software,
developers will continue to use undisciplined development methods.
˲ ˲ As long as we fail to demand that
developers use disciplined methods,
we run the risk—nay, certainty—that
we will continue to encounter software
full of bugs.
David L. Parnas ( parnas@mcmaster.ca) is Professor
emeritus at McMaster university and the university of
Limerick as well as President of Middle road software.
he has been looking for, and teaching, better software
development methods for more than 40 years. he is still
looking!
copyright held by author.