On Wed, 26 Sep 2018 at 13:40, Marko Ristin-Kaufmann firstname.lastname@example.org wrote:
Please mind that I said: any library would benefit from it, as in the users of any library on pipy would benefit from better, formal and more precise documentation. That doesn't imply that all the contracts need to be specified or that you have to specify the contract for every function, or that you omit the documentation altogether. Some contracts are simply too hard to get explicitly. Some are not meaningful even if you could write them down. Some you'd like to add, but run only at test time since too slow in production. Some run in production, but are not included in the documentation (e.g., to prevent the system to enter a bad state though it is not meaningful for the user to actually read that contract).
Since contracts are formally written, they can be verified. Human text can not. Specifying all the contracts is in most cases not meaningful. In my day-to-day programming, I specify contracts on the fly and they help me express formally to the next girl/guy who will use my code what to expect or what not. That does not mean that s/he can just skip the documentation or that contracts describe fully what the function does. They merely help -- help him/her what arguments and results are expected. That does not mean that I fully specified all the predicates on the arguments and the result. It's merely a help à la
- "Ah, this argument needs to be bigger than that argument!"
- "Ah, the resulting dictionary is shorter than the input list!"
- "Ah, the result does not include the input list"
- "Ah, this function accepts only files (no directories) and relative paths!"
- "Ah, I put the bounding box outside of the image -- something went wrong!"
- "Ah, this method allows me to put the bounding box outside of the image and will fill all the outside pixels with black!" etc.
Whoops, I think the rules changed under me again :-(
Are we talking here about coding explicit executable contracts in the source code of the library, or using (formally described in terms of (pseudo-)code) contract-style descriptions in the documentation, or simply using the ideas of contract-based thinking in designing and writing code?
For example, if I have an object detector operating on a region-of-interest and returning bounding boxes of the objects, the postconditions will not be: "all the bounding boxes are cars", that would impossible. But the postcondition might check that all the bounding boxes are within the region-of-interest or slightly outside, but not completely outside etc.
I understand that you have to pick an appropriate level of strictness when writing contracts. That's not ever been in question (at least in my mind).
Let's be careful not to make a straw-man here, i.e. to push DbC ad absurdum and then discard it that way.
I'm not trying to push DbC to that point. What I *am* trying to do is make it clear that your arguments (and in particular the fact that you keep insisting that "everything" can benefit) are absurd. If you'd tone back on the extreme claims (as Chris has also asked) then you'd be more likely to get people interested. This is why (as you originally asked) DbC is not more popular - its proponents don't seem to be able to accept that it might not be the solution to every problem. Python users are typically fairly practical, and think in terms of "if it helps in this situation, I'll use it". Expecting them to embrace an argument that demands they accept it applies to *everything* is likely to meet with resistance.
You didn't address my question "does this apply to the stdlib"? If it doesn't, your argument has a huge hole - how did you decide that the solution you're describing as "beneficial to all libraries" doesn't improve the stdlib? If it does, then why not demonstrate your case? Give concrete examples - look at some module in the stdlib (for example, pathlib) and show exactly what contracts you'd add to the code, what the result would look like to the library user (who normally doesn't read the source code) and to the core dev (who does). Remember that pathlib (like all of the stdlib) doesn't use type annotations, and that is a *deliberate* choice, mandated by Guido when he first introduced type annotations. So you're not allowed to add contracts like "arg1 is a string", nor are you allowed to say that the lack of type annotations makes the exercise useless.
I think I've probably said all I can usefully say here. If you do write up a DbC-enhanced pathlib, I'll be interested in seeing it and may well have more to say as a result. If not, I think I'm just going to file your arguments as "not proven".