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

Steven D'Aprano steve at pearwood.info
Mon Oct 8 08:11:08 EDT 2018


On Mon, Oct 08, 2018 at 09:32:23PM +1100, Chris Angelico wrote:
> On Mon, Oct 8, 2018 at 9:26 PM Steven D'Aprano <steve at pearwood.info> wrote:
> > > In other words, you change the *public interface* of your functions
> > > all the time? How do you not have massive breakage all the time?
> >
> > I can't comment about Marko's actual use-case, but *in general*
> > contracts are aimed at application *internal* interfaces, not so much
> > library *public* interfaces.
> 
> Yet we keep having use-cases shown to us involving one person with one
> module, and another person with another module, and the interaction
> between the two.

Do we? I haven't noticed anything that matches that description, 
although I admit I haven't read every single post in these threads 
religiously.

But "application" != "one module" or "one developer". I fail to see the 
contradiction. An application can be split over dozens of modules, 
written by teams of developers. Whether one or a dozen modules, it still 
has no public interface that third-party code can call. It is *all* 
internal.

Obviously if you are using contracts in public library code, the way 
you will manage them is different from the way you would manage them if 
you are using them for private or internal code.

That's no different from (say) docstrings and doctests: there are 
implied stability promises for those in *some* functions (the public 
ones) but not *other* functions (the private ones).

Of course some devs don't believe in stability promises, and treat all 
APIs as unstable. So what? That has nothing to do with contracts. People 
can "move fast and break everything" in any programming style they like.


> Which way is it? Do the contracts change frequently or not? 

"Mu."

https://en.wikipedia.org/wiki/Mu_(negative)

They change as frequently as you, the developer writing them, chooses to 
change them. Just like your tests, your type annotations, your doc 
strings, and every other part of your code.


> Are they public or not? 

That's up to you.

Contracts were originally designed for application development, where 
the concept of "public" versus "private" is meaningless. The philosophy 
of DbC is always going to be biased towards that mind-set.

Nevertheless, people can choose to use them for library code where there 
is a meaningful distinction. If they do so, then how they choose to 
manage the contracts is up to them.

If you want to make a contract a public part of the interface, then you 
can (but that would rule out disabling that specific contract, at least 
for pre-conditions).

If you only want to use it for internal interfaces, you can do that too. 

If you want to mix and match and make some contracts internal and some 
public, there is no DbC Police to tell you that you can't.


> How are we supposed to understand the point of contracts 

You could start by reading the explanations given on the Eiffel page, 
which I've linked to about a bazillion times. Then you could read about 
another bazillion blog posts and discussions that describe it (some pro, 
some con, some mixed). And you can read the Wikipedia page that shows 
how DbC is supported natively by at least 17 languages (not just Eiffel) 
and via libraries in at least 15 others. Not just new experimental 
languages, but old, established and conservative languages like Java, C 
and Ada.

There are heaps of discussions on DbC on Stackoverflow:

https://stackoverflow.com/search?q=design%20by%20contract

and a good page on wiki.c2:

http://wiki.c2.com/?DesignByContract

TIL: Pre- and postconditions were first supported natively Barbara 
Liskov's CLU in the 1970s.

This is not some "weird bizarre Eiffel thing", as people seem to 
believe. If it hasn't quite gone mainstream, it is surely at least as 
common as functional programming style. It has been around for over 
forty years in one way or another, not four weeks, and is a standard, 
well-established if minority programming style and development process.

Of course it is always valid to debate the pros and cons of DbC versus 
other development paradigms, but questioning the very basis of DbC as 
people here keep doing is as ludicrous and annoying as questioning the 
basis of OOP or FP or TDD would be.

Just as functional programming is a paradigm that says (among other 
things) "no side effects", "no global variables holding state" etc, and 
we can choose to apply that paradigm even in non-FP languages, so DbC is 
in part a paradigm that tells you how to design the internals of your 
application.

We can apply the same design concepts to any code we want, even if we're 
not buying into the whole Contract metaphor:

- pre-conditions can be considered argument validation;

- post-conditions can be considered a kind of test;

- class invariants can be considered a kind of defensive assertion.



> if the use-cases being shown all involve bad code
> and/or bad coding practices?

How do you draw that conclusion?


> Contracts, apparently, allow people to violate versioning expectations
> and feel good about it.
> 
> (Am I really exaggerating all that much here?)

"Exaggerating" is not the word I would choose to use. "Talking utter 
bollocks" is probably more accurate *grin*



-- 
Steve


More information about the Python-ideas mailing list