[Python-ideas] Why is design-by-contracts not widely adopted?

Terry Reedy tjreedy at udel.edu
Sun Oct 7 16:24:58 EDT 2018


On 9/24/2018 3:46 AM, Marko Ristin-Kaufmann wrote:

I am responding to your request "Please do point me to what is not 
obvious to you".  I think some of your claims are not only not obvious, 
but are wrong.  I have read some (probably less than half) of the 
responses and avoid saying what I know others have covered adequately.

A mathematical function is defined or specified by a input domain, 
output range, and a mapping from inputs to outputs.  The mapping can be 
defined either by an explicit listing of input-output pairs or by a rule 
specifying either a) the process, what is done to inputs to produce 
outputs or, b) the result, how the output relates to the input.

 > 
https://www.win.tue.nl/~wstomv/edu/2ip30/references/design-by-contract/index.html 

defines contracts as "precise (legally unambiguous) specifications" (5.2 
Business Contracting/Sub-contracting Metaphor)  It is not obvious to me 
that the metaphor of contracts adds anything worthwhile to the idea of 
'function'.

1. Only a small sliver of human interactions are governed by formal 
legal contracts read, understood, and agreed to by both (all) parties.

2. The idealized definition is naive in practice.  Most legal contracts, 
unlike the example in the link article, are written in language that 
most people cannot read.  Many contracts are imprecise and legally 
ambiguous, which is why we have contract dispute courts.  And even then, 
the expense means that most people who feel violated in a transaction do 
not use courts.

Post-conditions specify a function by result.  I claim that this is not 
always sensible.  I said above that functions may be specified by 
process rather than result.  Ironically, the contract metaphor 
reinforces my claim.  Many contracts, such as in teaching and medicine, 
only specify process and explicitly disclaim any particular result of 
concern to the client.

> b)//If you write contracts in text, they will become stale over time 

Not true for good docstrings.  We very seldom change the essential 
meaning of public functions.

How has "Return the sine of x (measured in radians).", for math.sin, 
become stale?  Why would it ever?  What formal executable post condition 
would help someone who does not understand 'sine', or 'sine of x'?  The 
function is only useful for someone who either understands 'sine' or is 
copying a formula written elsewhere without needing to understand it.

Or consider "Stable sort *IN PLACE*." for list.sort.  A formal 
executable post-condition for this *can* be written.  But for someone 
who understands the words 'stable', 'sort', and 'in place', this compact 
English post condition is much more readable than any formal version 
could be.  More over, that addition of 'stable', when we were ready to 
do so, did not make "Sort *IN PLACE*" stale in any sense of being wrong.

I said above that functions definitions and contracts can specify the 
process rather than the result.  For functions, the code is the process, 
and the code may then be the specification and the contract.  For instance,

def append_first(seq):
     "Append seq[0] to seq."

So seq must have a first element accessed as seq[0] and an append method 
that accepts the first element as an argument.  One might guess the 
minimal body.

     return seq.append(seq[0])

The pre-condition here is that the return value can be calculated as 
specified.  Whenever this is true, python is already testing 
pre-conditions, as efficiently as possible.  We could elaborate the body as

     try:
         return seq.append(seq[0])
     except Exception as e:
         raise ValueError('raised ' + repr(e)[0])

and add 'Raise ValueError with explanation on bad input' to the doc string.

If the domain were restricted to lists, we could write a post-condition, 
and use that in a list-based unittest.  However, it likely be less 
readable than the docstring, and would execute in O(n) time (for an O(1) 
function).  The latter is acceptable for unittests, which will use short 
tests, but not for production.  But with duck-typing, no post condition 
is possible.  Neither is a generic unittest.  The code *is* the 
contract.  This is generally true of duck-typed Python code.

-- 
Terry Jan Reedy



More information about the Python-ideas mailing list