[Python-ideas] Why is design-by-contracts not widely adopted?
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.
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
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,
"Append seq to seq."
So seq must have a first element accessed as seq and an append method
that accepts the first element as an argument. One might guess the
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
except Exception as e:
raise ValueError('raised ' + repr(e))
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