30 communicationS of the acm | deCeMBer 2013 | vOL. 56 | nO. 12
and in protecting software and data
from external errors. This has not been
easy given the vulnerabilities inherent
in the chain of transformations that
designers must master (see the accompanying figure):
1. The specification does not accurately represent the designer’s intention, or is based on misunderstandings
of user expectations.
2. The programmer makes mistakes, for example, by introducing
bugs or approximations that cause the
software to violate its specifications.
Moreover, the compiler might contain
bugs or Trojan horses that cause the
machine code to be not equivalent to
the source program.
3. The machine itself contains bugs,
defects, malfunctions, intrusions by
other buggy machines or attackers, and
other factors that cause it to misbehave
while executing its basic operations.
4. The users’ expectations of what
the machine’s job is differs from what
they see the machine doing.
When combined with the general
concern for getting work done on time,
these error sources have led to five traditional criteria for software design:
˲ Requirements—Does it have a clear
purpose? The designer knows what job
the machine is intended to perform and
can state the requirements precisely as
a specification. Articulating requirements is a challenge because interviewing the intended users about what they
want is notoriously unreliable.
˲ Correctness—Does it work properly?
The behavior of a source code program
provably meets precise specifications.
Correctness is challenging because requirements are often fuzzy and proofs
are often computationally infeasible.
Experimental methods are often the
only practical way to learn user requirements, arrive at precise specifications, avoid intractability, and test
˲ Fault tolerance—Does it keep working? The software and its host systems
can continue to function despite small
errors, and will refuse to function in
case of a large error. Redundancy supports fault tolerance by duplicating
hardware and data so that a failed component can be bypassed by other still-working components and datasets.
Error confinement supports fault tolerance by structuring the operating environment so that no process has access
to any object other than those it needs
for its computation and by limiting (or
eliminating) the super user state.
˲ Timeliness—Does it complete its
work in time to be useful? The system
completes its tasks within the expected deadlines. Supporting techniques
include algorithm analysis, queueing
network analysis, and real-time system
˲ Fitness—Does it align well with
the user environment? Fitness is chal-
lenging because assessments like
dependability, reliability, usability,
safety, and security are context sensi-
tive and much of the context is not ob-
vious even to the experienced design-
er. The famous architect Christopher
Alexander advocated an approach to
design that was immersed in the con-
text of how dwellers used buildings. 1
Alexander’s work inspired a group of
software designers to found a “soft-
ware pattern community” devoted
the ideals of good software design.
A software pattern characterizes a
large number of situations that a pro-
grammer is likely to encounter, and
offers guidance on how to structure
the program to best fit the pattern.
The pattern community appeals to
my sense of empiricism because they
are relentless about testing ideas with
potential users and learning from the
feedback. A good introductory book
on the topic is Pattern Languages of
Software Design (Addison-Wesley,
1995), by James Coplien and Douglas
Schmidt. Coplien is one of the found-
ers of the pattern community.
Software and computer
Despite their best efforts with tools,
languages, and project management,
software experts felt they could not
keep up with the demands for ever-larger reliable systems. In 1968, they
founded the field of software engineering to apply standard engineering
methods to meet two concerns:
1. Increasing reliability and managing
risk by eliminating or confining errors.
2. Seeing software projects through
to completion (delivery) and subsequent evolution (maintenance).
Within computing various schools
of thought have developed around
specific approaches to these concerns. These schools have advanced
“process models” like waterfall or
spiral, or “design approaches” such
as participatory, user centered, agile,
or pattern. They are all after the same
thing, but they weigh the criteria in
different ways. Barry Boehm argued
that the standard engineering design
approach of careful, almost rigid process was at the strict end of a planning
spectrum and agile methods were
at the flexible end. 2 He thought that
careful planning is needed when reliability, safety, and security are important and that agility is needed when
usability and evolvability are important. He exhorted the careful planning and the agile schools to collaborate on finding a common ground for
four sources of errors in computations.
specification of F
program for F
Y = F(X) 3