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

Marko Ristin-Kaufmann marko.ristin at gmail.com
Tue Sep 25 14:11:27 EDT 2018


Hi Hugh,

> As soon as you need to document your code, and
> > this is what most modules have to do in teams of more than one person
> > (especially so if you are developing a library for a wider audience), you
> > need to write down the contracts. Please see above where I tried to
> > explained  that 2-5) are inferior approaches to documenting contracts
> > compared to 1).
>
> You left off option 6), plain text. Comments. Docstrings.
>

 That was actually the option 2):

> 2) Write precondtions and postconditions in docstring of the method as
> human text.


The problem with text is that it is not verifiable and hence starts to
"rot". Noticing that text is wrong involves much more developer time &
attention than automatically verifying the formal contracts.

In Python we can write something like:

def foo(x):
    x.bar(y)

What's the type of x? What's the type of y? What is the contract of bar?
Don't know, don't care. x, or y, can be an instance, a class, a module, a
proxy for a remote web service. The only "contract" is that object x will
respond to message bar that takes one argument. Object x, do whatever
you want with it.

I still don't see how this is connected to contracts or how contracts play
a role there? If foo can accept any x and return any result then there is *no
*contract. But hardly any function is like that. Most exercise a certain
behavior on a subset of possible input values. The outputs also  satisfy
certain contracts, *i.e.* they also live in a certain subset of possible
outputs. (Please mind that I don't mean strictly numerical ranges here --
it can be any subset of structured data.) As I already mentioned, the
contracts have nothing to do with typing. You can use them for runtime type
checks -- but that's a reduction of the concept to a very particular use
case. Usually contracts read like this (from the numpy example linked in
another message,
https://www.numpy.org/devdocs/reference/generated/numpy.ndarray.transpose.html#numpy.ndarray.transpose
):

ndarray.transpose(**axes*)

Returns a view of the array with axes transposed.

*For a 1-D array, this has no effect. (To change between column and row
vectors, first cast the 1-D array into a matrix object.) For a 2-D array,
this is the usual matrix transpose. For an n-D array, if axes are given,
their order indicates how the axes are permuted (see Examples). If axes are
not provided and a.shape = (i[0], i[1], ... i[n-2], i[n-1]), then
a.transpose().shape = (i[n-1], i[n-2], ... i[1], i[0]).*
(emphasis mine)

Mind the three postconditions (case 1D array, case 2D array, case N-D
array).

As for 4) reading the code, why not? "Use the source, Luke" is now a
> programming cliche because it works. It's particularly appropriate for
> Python packages which are usually distributed in source form and, as
> you yourself noted, easy to read.


Because it is hard and costs a lot of time. The point of encapsulating a
function is that I as a user don't have to know its details of
implementation and its wider dependencies in the implementation. Looking at
the code is the tool of last resort to figure out the contracts. Imagine if
you had to look at the implementation of numpy.transpose() to figure out
what happens when transposing a N-D array.

Cheers,
Marko

On Tue, 25 Sep 2018 at 13:13, Hugh Fisher <hugo.fisher at gmail.com> wrote:

> > Date: Mon, 24 Sep 2018 09:46:16 +0200
> > From: Marko Ristin-Kaufmann <marko.ristin at gmail.com>
> > To: Python-Ideas <python-ideas at python.org>
> > Subject: Re: [Python-ideas] Why is design-by-contracts not widely
> >         adopted?
> > Message-ID:
> >         <CAGu4bVB4=Bou+DhoDzayx=
> i7eQ2Gr8KDDOFONeaB-Qvt8LZo2A at mail.gmail.com>
> > Content-Type: text/plain; charset="utf-8"
>
> [munch]
>
> > Their users would hugely benefit from a more mature
> > and standardized contracts library with informative violation messages.
>
> Will respond in another message, because it's a big topic.
>
> > I really don't see how DbC has to do with duck typing (unless you reduce
> it
> > to mere isinstance conditions, which would simply be a straw-man
> argument)
> > -- could you please clarify?
>
> I argue that Design by Contract doesn't make sense for Python and other
> dynamically typed, duck typed languages because it's contrary to how the
> language, and the programmer, expects to work.
>
> In Python we can write something like:
>
> def foo(x):
>     x.bar(y)
>
> What's the type of x? What's the type of y? What is the contract of bar?
> Don't know, don't care. x, or y, can be an instance, a class, a module, a
> proxy for a remote web service. The only "contract" is that object x will
> respond to message bar that takes one argument. Object x, do whatever
> you want with it.
>
> And that's a feature, not a bug, not bad design. It follows Postel's Law
> for Internet protocols of being liberal in what you accept. It follows the
> Agile principle of valuing working software over comprehensive doco.
> It allows software components to be glued together quickly and easily.
>
> It's a style of programming that has been successful for many years,
> not just in Python but also in Lisp and Smalltalk and Perl and JavaScript.
> It works.
>
> Not for everything. If I were writing the avionics control routines for a
> helicopter gas turbine, I'd use formal notation and static type checking
> and preconditions and whatnot. But I wouldn't be using Python either.
>
> > As soon as you need to document your code, and
> > this is what most modules have to do in teams of more than one person
> > (especially so if you are developing a library for a wider audience), you
> > need to write down the contracts. Please see above where I tried to
> > explained  that 2-5) are inferior approaches to documenting contracts
> > compared to 1).
>
> You left off option 6), plain text. Comments. Docstrings. README files.
> Web pages. Books. In my experience, this is what most people consider
> documentation. A good book, a good blog post, can explain more about
> how a library works and what the implementation requirements and
> restrictions are than formal contract notation. In particular, contracts in
> Eiffel don't explain *why* they're there.
>
> As for 4) reading the code, why not? "Use the source, Luke" is now a
> programming cliche because it works. It's particularly appropriate for
> Python packages which are usually distributed in source form and, as
> you yourself noted, easy to read.
>
> --
>
>         cheers,
>         Hugh Fisher
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180925/bece7f97/attachment.html>


More information about the Python-ideas mailing list