mum size of network packets supported by the hardware or how a related
protocol works), and those assumptions are incorrect or the environment
changes. Finally, and very commonly,
some implementers may find a need
to enhance the protocol to add new
functionality that isn’t defined by the
spec.
Writing standards (that is, any specification that defines interoperability
between different implementations)
is an art. Standards are essentially contracts, in the legal sense, but the law
has the advantage (or perhaps disadvantage) of a long history of definition,
redefinition, and refinement of definition, usually in case law. The goal of a
standard is to make interoperability
possible. That requires both precision
(to avoid ambiguity) and clarity (to
avoid misinterpretation). Failure in either way results in a lack of interoperability. Unfortunately, these two goals
are sometimes at odds, as noted.
Our normal human language is often ambiguous; in real life we handle
these ambiguities without difficulty
(or use them as the basis for jokes),
but in the technical world they can
cause problems. Extremely precise
language, however, is so unnatural to
us that it can be hard to appreciate the
subtleties. Standards often use formal
grammar, mathematical equations,
and finite-state machines in order to
convey precise information concisely,
which certainly helps, but these do not
usually stand on their own—for example, grammar describes syntax but
not semantics, equations have to be
translated into code, and finite-state
machines are notoriously difficult for
humans to understand.
Standards often include diagrams
and examples to aid understandability, but these can actually create problems. Consider the possibility that a
diagram does not match the descriptive text. Which one is correct? For
that matter, any time the same thing is
described in two places there is a danger that the two descriptions may say
subtly different things. For example,
RFC 821 and RFC 822 both describe
the syntax of an email address, but unfortunately they differ in minor ways
(these standards have since been updated to fix this and other problems). A
common solution is always to include
for many years
the Robustness
Principle was
accepted dogma,
failing more when
it was ignored
rather than when
practiced. in recent
years, however,
that principle has
been challenged.
necessary duplicate language “by reference” (that is, including a reference
to another document rather than an
actual description). Of course, taken
to an extreme, this can result in a rat’s
nest of standards documents. For
example, the OSI recommendations
(standards) for message handling
(email) are contained in about 20 different documents filled with cross-references.
Even using examples can be controversial. Examples are never normative
(standards buzzword for
authoritative); that is, if there is a conflict between an example and the body of the
text, the text wins. Also, examples are
seldom complete. They may demonstrate some piece of the protocol but
not all the details. In theory if you removed all the examples from a standard, then the meaning of that standard would not change at all—the sole
raison d’être being to aid comprehension. The problem is that some implementers read the examples (which are
often easier to understand than the
actual text of the standard) and implement from those, thus missing important details of the standard. This has
caused some authors of standards to
eschew the use of examples altogether.
Some (usually vendor-driven) standards use the “reference implementation” approach—that is, a single
implementation that is defined to be
correct; all other implementations are
in turn correct if and only if they work
against the reference implementation.
This method is fraught with peril. For
one thing, no implementation is ever
completely bug-free, so finding and
fixing a bug in the reference implementation essentially changes the
standard.
Similarly, standards usually have
various “undefined” or “reserved” elements—for example, multiple options with overlapping semantics
are specified at the same time. Other
implementations will find how these
undefined elements work and then
rely on that unintended behavior. This
creates problems when the reference
implementation is extended to add
functionality; these undefined and reserved elements are typically used to
provide the new functions. Also, there
may be two independent implementations that each work against the refer-