<div dir="ltr"><div dir="ltr"><div><div><div>Hi Terry,<br><br></div>I would encourage you to read all the messages on the thread. The points you raised were actually already discussed:<br></div>* Using formal contracts in the code does not imply that you must specify <i>all</i> the contracts; you specify what you consider meaningful.<br></div><div>* Distinction of result/process (the example that was already discussed was related to GUIs and pathlib standard library)<br><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">> b)//If you write contracts in text, they will become stale over time <br>
<br>
Not true for good docstrings.  We very seldom change the essential <br>
meaning of public functions.</blockquote><div><br></div><div>In my team, we have a stale docstring once every two weeks or even more often. If it weren't for doctests and contracts, I could imagine we would have them even more often :) <br><br>I suppose good docstrings require many reviewers and slow refactoring processes. Our public interfaces are changing daily and there is one reviewer per pull request. If github/bitbucket allowed for better highlighting of docstrings in code reviews (<i>e.g., </i>if it highlighted the docstring of every function that changed), the miss rate would be probably lower. I'm always happy to hear other experiences how people dealt with requirements changing at a fast pace and how they dealt with code rot in a team of limited size and time resources.<br><br></div><div>I agree with you that a good docstring is not stale by definition. I have just never experienced a team that had good docstrings in my career.<br> </div></div><br></div><div>Cheers,<br></div><div>Marko<br></div></div><br><div class="gmail_quote"><div dir="ltr">On Sun, 7 Oct 2018 at 22:25, Terry Reedy <<a href="mailto:tjreedy@udel.edu">tjreedy@udel.edu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 9/24/2018 3:46 AM, Marko Ristin-Kaufmann wrote:<br>
<br>
I am responding to your request "Please do point me to what is not <br>
obvious to you".  I think some of your claims are not only not obvious, <br>
but are wrong.  I have read some (probably less than half) of the <br>
responses and avoid saying what I know others have covered adequately.<br>
<br>
A mathematical function is defined or specified by a input domain, <br>
output range, and a mapping from inputs to outputs.  The mapping can be <br>
defined either by an explicit listing of input-output pairs or by a rule <br>
specifying either a) the process, what is done to inputs to produce <br>
outputs or, b) the result, how the output relates to the input.<br>
<br>
 > <br>
<a href="https://www.win.tue.nl/~wstomv/edu/2ip30/references/design-by-contract/index.html" rel="noreferrer" target="_blank">https://www.win.tue.nl/~wstomv/edu/2ip30/references/design-by-contract/index.html</a> <br>
<br>
defines contracts as "precise (legally unambiguous) specifications" (5.2 <br>
Business Contracting/Sub-contracting Metaphor)  It is not obvious to me <br>
that the metaphor of contracts adds anything worthwhile to the idea of <br>
'function'.<br>
<br>
1. Only a small sliver of human interactions are governed by formal <br>
legal contracts read, understood, and agreed to by both (all) parties.<br>
<br>
2. The idealized definition is naive in practice.  Most legal contracts, <br>
unlike the example in the link article, are written in language that <br>
most people cannot read.  Many contracts are imprecise and legally <br>
ambiguous, which is why we have contract dispute courts.  And even then, <br>
the expense means that most people who feel violated in a transaction do <br>
not use courts.<br>
<br>
Post-conditions specify a function by result.  I claim that this is not <br>
always sensible.  I said above that functions may be specified by <br>
process rather than result.  Ironically, the contract metaphor <br>
reinforces my claim.  Many contracts, such as in teaching and medicine, <br>
only specify process and explicitly disclaim any particular result of <br>
concern to the client.<br>
<br>
> b)//If you write contracts in text, they will become stale over time <br>
<br>
Not true for good docstrings.  We very seldom change the essential <br>
meaning of public functions.<br>
<br>
How has "Return the sine of x (measured in radians).", for math.sin, <br>
become stale?  Why would it ever?  What formal executable post condition <br>
would help someone who does not understand 'sine', or 'sine of x'?  The <br>
function is only useful for someone who either understands 'sine' or is <br>
copying a formula written elsewhere without needing to understand it.<br>
<br>
Or consider "Stable sort *IN PLACE*." for list.sort.  A formal <br>
executable post-condition for this *can* be written.  But for someone <br>
who understands the words 'stable', 'sort', and 'in place', this compact <br>
English post condition is much more readable than any formal version <br>
could be.  More over, that addition of 'stable', when we were ready to <br>
do so, did not make "Sort *IN PLACE*" stale in any sense of being wrong.<br>
<br>
I said above that functions definitions and contracts can specify the <br>
process rather than the result.  For functions, the code is the process, <br>
and the code may then be the specification and the contract.  For instance,<br>
<br>
def append_first(seq):<br>
     "Append seq[0] to seq."<br>
<br>
So seq must have a first element accessed as seq[0] and an append method <br>
that accepts the first element as an argument.  One might guess the <br>
minimal body.<br>
<br>
     return seq.append(seq[0])<br>
<br>
The pre-condition here is that the return value can be calculated as <br>
specified.  Whenever this is true, python is already testing <br>
pre-conditions, as efficiently as possible.  We could elaborate the body as<br>
<br>
     try:<br>
         return seq.append(seq[0])<br>
     except Exception as e:<br>
         raise ValueError('raised ' + repr(e)[0])<br>
<br>
and add 'Raise ValueError with explanation on bad input' to the doc string.<br>
<br>
If the domain were restricted to lists, we could write a post-condition, <br>
and use that in a list-based unittest.  However, it likely be less <br>
readable than the docstring, and would execute in O(n) time (for an O(1) <br>
function).  The latter is acceptable for unittests, which will use short <br>
tests, but not for production.  But with duck-typing, no post condition <br>
is possible.  Neither is a generic unittest.  The code *is* the <br>
contract.  This is generally true of duck-typed Python code.<br>
<br>
-- <br>
Terry Jan Reedy<br>
<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote></div>