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 email@example.com 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?
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:
and a good page on wiki.c2:
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*