1. 5
  1.  

  2. 1

    The object-oriented approach, based on the theory of abstract data types, provides a particularly appropriate framework for discussing and enforcing reliability.

    The first half of the sentence is false: objects are fundamentally different from abstract data types.

    The second half of the sentence requires further qualification, since it is in general not true. For example, both objects and abstract data types have little to offer to implementors of cryptographic algorithms.

    It is important to include the preconditions and postconditions as part of the routine declarations.

    Clearly, preconditions and postconditions ought to be a part of the routine’s documentation. But it is not clear why they should be a part of the routine itself. For example, Hoare’s and Dijkstra’s formalisms use predicates on the program state to guide the verification and construction of programs, respectively, but these predicates are not a part of the program itself.

    Invariants, the next major use of assertions, are unconceivable outside of the object-oriented approach.

    Mmm… Okay. (Granted, runtime-checked assertions are not used, but invariants certainly are.)

    In some cases, one might want to use quantified expressions (…) by using (…) calls to functions that rely on loops to emulate the quantifiers.

    Try quantifying over infinite domains in this way.

    The use of functions [read: procedures] — that is to say, computations — is not without its dangers. (…) software functions [read: procedures] can produce side effects (change the state of the computation).

    Indeed. Moreover, computation itself is a kind of effect, by virtue of the fact it takes time and uses space. If you take the view that complexity requirements are a part of the functional specification, then the very act of checking assertions can make an otherwise correct procedure incorrect.

    any function used in assertions must be of unimpeachable quality

    To be unimpeachably assessed how?

    What is to prevent a redeclaration from producing an effect that is incompatible with the semantics of the original version? Nothing, of course. No design technique is immune to misuse.

    Some design techniques are more prone to misuse than others. For example, while abstract data types can be incorrectly implemented, the invariants of a correctly implemented abstract data type cannot be violated by third parties. This shows that classes are not abstract data types.

    But at least it is possible to help serious designers use the technique correctly: here the contract theory provides the proper perspective.

    Contracts merely mitigate the damage caused by the ability to arbitrarily redefine features. A simpler alternative is to disallow such redefinitions.

    What redeclaration and dynamic binding mean is the ability to subcontract a task

    The same effect can be achieved with less semantic complication by manipulating procedures as a first-class values. My apologies for the misnomer in the linked article’s title.

    Invariants are always passed on to descendants.

    Mmm… Okay.

    The contract theory provides a good starting point for a more rational solution. If a routine is seen not just as some “piece of code” but as the implementation of a certain specification — the contract — it is possible to define a notion of failure.

    Alternatively, you should only promise what you can actually deliver.