<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Hi Kyle,<br><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">6) The name of the method<br>
    7) How the method is called throughout the codebase <br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">10) relying on convention inside, and outside, the application<br></blockquote><br></div><div>Sorry, by formulating 2) as "docstring" I excluded names of the methods as well as variables. Please assume that 2) actually entails those as well. They are human text and hence not automatically verifiable, hence qualify as 2).<br><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
    8) observing input and output values during debugging<br>
    9) observing input and output values in production<br>
    </blockquote></div><div><br>Sorry, again I implicitly subsumed 8-9 under 4), reading the implementation code (including the trial-and-error). My assumption was that it is incomparably more costly to apply trial-and-error than read the contracts given that contracts can be formulated. Of course, not all contracts can be formulated all the time.<br><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
    11) Don't communicate - Sometimes
    <complexity>/<num_customers> is too high; code is not
    repaired, only replaced.<br></blockquote><br></div><div>I don't see this as an option for any publicly available, high-quality module on pypi or in any organization. As I already noted in my message to Hugh, the argument in favor of<i> undocumented and/or untested code</i> are not the arguments. I assume we want a <i>maintainable</i> and <i>usable</i> modules. I've never talked about undocumented throw-away exploratory code. Most of the Python features become futile in that case (type annotations and static type checking with mypy, to name only the few).<br><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Does it work on Windows? <br></blockquote><div>This is probably impossible to write as a contract, but needs to be tested (though maybe there is a way to check it and encapsulate the check in a separate function and put it into the contract).<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
      What is_absolute()?  is <a class="gmail-m_-4462269581093404228moz-txt-link-rfc2396E">"file:///"</a> absolute?<br></blockquote><div>Since the type is pathlib.Path (as written in the type annotation), it's pathlib.Path.is_absolute() method. Please see <a href="https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.is_absolute">https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.is_absolute</a><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">At a high level, I can see the allure of DbC:  Programming can be a
    craft, and a person can derive deep personal satisfaction from
    perfecting the code they work on. DbC provides you with more
    decoration, more elaboration, more ornamentation, more control. 
    This is not bad, but I see all your arguments as personal ascetic
    sense.  DbC is only appealing under certain accounting rules. 
    Please consider the possibility that "the best code" is: low $$$,
    buggy, full of tangles, and mostly gets the job done.   :)</blockquote><div>Actually, this goes totally contrary to most of my experience. Bad code is unmaintainable and ends up being much more costly down the line. It's also what we were taught in software engineering lectures in the university (some 10-15 years ago) and I always assumed that the studies presented there were correct.  <br><br></div><div>Saying that writing down contracts is costly is a straw-man. It is costly if you need to examine the function and write them down. If you <i>are writing </i>the function and just keep adding the contracts as-you-go, it's basically very little overhead cost. You make an assumption of the input, and instead of just coding on, you scroll up, write it down formally, and go back where you stopped and continue the implementation. Or you think for a minute what contracts your function needs to expect/satisfy before you start writing it (or during the design). I don't see how this can be less efficient than trial-and-error and making possibly wrong assumptions based on the output that you see without any documentation by running the code of the module.<br><br></div><div>Cheers,<br></div><div>Marko<br></div></div></div></div></div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, 25 Sep 2018 at 23:59, Kyle Lahnakoski <<a href="mailto:klahnakoski@mozilla.com">klahnakoski@mozilla.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div text="#000000" bgcolor="#FFFFFF">
    <p><br>
    </p>
    <p>I use DbC occasionally to clarify my thoughts during a
      refactoring, and then only in the places that continue to make
      mistakes. In general, I am not in a domain that benefits from DbC.
      <br>
    </p>
    <p>Contracts are code: More code means more bugs. Declarative
      contracts are succinct, but difficult to debug when wrong; I
      believe this because the debugger support for contracts is poor;
      There is no way to step through the logic and see the intermediate
      reasoning in complex contracts.  A contract is an incomplete
      duplication of what the code already does: at some level of
      complexity I prefer to use a duplicate independent implementation
      and compare inputs/outputs.<br>
    </p>
    Writing contracts cost time and money; and that cost should be
    weighed against the number and flexibility of the customers that use
    the code.  A one-time script, a webapp for you team, an Android app
    for your startup, fraud software, and Facebook make different
    accounting decisions.  I contend most code projects can not justify
    DbC.<br>
    <br>
    <br>
    <div class="m_-4462269581093404228moz-cite-prefix">On 2018-09-24 03:46, Marko
      Ristin-Kaufmann wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr">
        <div dir="ltr">
          <div dir="ltr">
            <div dir="ltr">
              <div dir="ltr">
                <div dir="ltr">
                  <div dir="ltr">
                    <div dir="ltr">
                      <div dir="ltr">
                        <div dir="ltr">
                          <div dir="ltr">
                            <div dir="ltr">
                              <div dir="ltr">
                                <div dir="ltr">
                                  <div dir="ltr">
                                    <div dir="ltr">
                                      <div dir="ltr">
                                        <div dir="ltr">
                                          <div dir="ltr">
                                            <div dir="ltr">
                                              <div dir="ltr">
                                                <div dir="ltr">When you
                                                  are documenting a
                                                  method you have the
                                                  following options:<br>
                                                  <div>1) Write
                                                    preconditions and
                                                    postconditions
                                                    formally and include
                                                    them automatically
                                                    in the documentation
                                                    (<i>e.g., </i>by
                                                    using icontract
                                                    library). <br>
                                                  </div>
                                                  <div>2) Write
                                                    precondtions and
                                                    postconditions in
                                                    docstring of the
                                                    method as human
                                                    text.<br>
                                                  </div>
                                                  <div>3) Write doctests
                                                    in the docstring of
                                                    the method.<br>
                                                  </div>
                                                  <div>4) Expect the
                                                    user to read the
                                                    actual
                                                    implementation.<br>
                                                  </div>
                                                  <div>5) Expect the
                                                    user to read the
                                                    testing code.<br>
                                                  </div>
                                                  <div dir="ltr"><br>
                                                  </div>
                                                </div>
                                              </div>
                                            </div>
                                          </div>
                                        </div>
                                      </div>
                                    </div>
                                  </div>
                                </div>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
    There are other ways to communicate how a method works.<br>
    <br>
    6) The name of the method<br>
    7) How the method is called throughout the codebase <br>
    8) observing input and output values during debugging<br>
    9) observing input and output values in production<br>
    10) relying on convention inside, and outside, the application<br>
    11) Don't communicate - Sometimes
    <complexity>/<num_customers> is too high; code is not
    repaired, only replaced.<br>
    <br>
    <br>
    <blockquote type="cite">
      <div dir="ltr">
        <div dir="ltr">
          <div dir="ltr">
            <div dir="ltr">
              <div dir="ltr">
                <div dir="ltr">
                  <div dir="ltr">
                    <div dir="ltr">
                      <div dir="ltr">
                        <div dir="ltr">
                          <div dir="ltr">
                            <div dir="ltr">
                              <div dir="ltr">
                                <div dir="ltr">
                                  <div dir="ltr">
                                    <div dir="ltr">
                                      <div dir="ltr">
                                        <div dir="ltr">
                                          <div dir="ltr">
                                            <div dir="ltr">
                                              <div dir="ltr">
                                                <div dir="ltr">This is
                                                  again something that
                                                  eludes me and I would
                                                  be really thankful if
                                                  you could clarify.
                                                  Please consider for an
                                                  example, pypackagery (<a href="https://pypackagery.readthedocs.io/en/latest/packagery.html" target="_blank">https://pypackagery.readthedocs.io/en/latest/packagery.html</a>)
                                                  and the documentation
                                                  of its function
                                                  resolve_initial_paths:<br>
                                                  <div dir="ltr">
                                                    <div>
                                                      <dl class="m_-4462269581093404228gmail-function">
                                                        <dt id="m_-4462269581093404228gmail-packagery.resolve_initial_paths">
                                                          <code class="m_-4462269581093404228gmail-descclassname">packagery.</code><code class="m_-4462269581093404228gmail-descname">resolve_initial_paths</code><span class="m_-4462269581093404228gmail-sig-paren">(</span><em>initial_paths</em><span class="m_-4462269581093404228gmail-sig-paren">)</span></dt>
                                                        <dd>
                                                          <p>Resolve the
                                                          initial paths
                                                          of the
                                                          dependency
                                                          graph by
                                                          recursively
                                                          adding <code class="m_-4462269581093404228gmail-docutils m_-4462269581093404228gmail-literal m_-4462269581093404228gmail-notranslate"><span class="m_-4462269581093404228gmail-pre">*.py</span></code>
                                                          files beneath
                                                          given
                                                          directories.</p>
                                                          <table class="m_-4462269581093404228gmail-docutils
gmail-field-list" frame="void" rules="none">
                                                          <colgroup><col class="m_-4462269581093404228gmail-field-name">
                                                          <col class="m_-4462269581093404228gmail-field-body">
                                                          </colgroup><tbody valign="top">
                                                          <tr class="m_-4462269581093404228gmail-field-odd m_-4462269581093404228gmail-field">
                                                          <th class="m_-4462269581093404228gmail-field-name">Parameters:</th>
                                                          <td class="m_-4462269581093404228gmail-field-body">
                                                          <p class="m_-4462269581093404228gmail-first"><strong>initial_paths</strong>
                                                          (<code class="m_-4462269581093404228gmail-xref m_-4462269581093404228gmail-py m_-4462269581093404228gmail-py-class m_-4462269581093404228gmail-docutils m_-4462269581093404228gmail-literal
gmail-notranslate"><span class="m_-4462269581093404228gmail-pre">List</span></code>[<code class="m_-4462269581093404228gmail-xref m_-4462269581093404228gmail-py m_-4462269581093404228gmail-py-class m_-4462269581093404228gmail-docutils m_-4462269581093404228gmail-literal
gmail-notranslate"><span class="m_-4462269581093404228gmail-pre">Path</span></code>]) –
                                                          initial paths
                                                          as absolute
                                                          paths</p>
                                                          </td>
                                                          </tr>
                                                          <tr class="m_-4462269581093404228gmail-field-even m_-4462269581093404228gmail-field">
                                                          <th class="m_-4462269581093404228gmail-field-name">Return
                                                          type:</th>
                                                          <td class="m_-4462269581093404228gmail-field-body">
                                                          <p class="m_-4462269581093404228gmail-first"><code class="m_-4462269581093404228gmail-xref m_-4462269581093404228gmail-py m_-4462269581093404228gmail-py-class m_-4462269581093404228gmail-docutils m_-4462269581093404228gmail-literal m_-4462269581093404228gmail-notranslate"><span class="m_-4462269581093404228gmail-pre">List</span></code>[<code class="m_-4462269581093404228gmail-xref m_-4462269581093404228gmail-py m_-4462269581093404228gmail-py-class m_-4462269581093404228gmail-docutils m_-4462269581093404228gmail-literal
gmail-notranslate"><span class="m_-4462269581093404228gmail-pre">Path</span></code>]</p>
                                                          </td>
                                                          </tr>
                                                          <tr class="m_-4462269581093404228gmail-field-odd m_-4462269581093404228gmail-field">
                                                          <th class="m_-4462269581093404228gmail-field-name">Returns:</th>
                                                          <td class="m_-4462269581093404228gmail-field-body">
                                                          <p class="m_-4462269581093404228gmail-first">list
                                                          of initial
                                                          files (<em>i.e.</em>
                                                          no
                                                          directories)</p>
                                                          </td>
                                                          </tr>
                                                          <tr class="m_-4462269581093404228gmail-field-even m_-4462269581093404228gmail-field">
                                                          <th class="m_-4462269581093404228gmail-field-name">Requires:</th>
                                                          <td class="m_-4462269581093404228gmail-field-body">
                                                          <ul class="m_-4462269581093404228gmail-first m_-4462269581093404228gmail-simple">
                                                          <li><code class="m_-4462269581093404228gmail-code m_-4462269581093404228gmail-docutils m_-4462269581093404228gmail-literal
gmail-notranslate"><span class="m_-4462269581093404228gmail-pre">all(pth.is_absolute()</span>
                                                          <span class="m_-4462269581093404228gmail-pre">for</span>
                                                          <span class="m_-4462269581093404228gmail-pre">pth</span>
                                                          <span class="m_-4462269581093404228gmail-pre">in</span>
                                                          <span class="m_-4462269581093404228gmail-pre">initial_paths)</span></code></li>
                                                          </ul>
                                                          </td>
                                                          </tr>
                                                          <tr class="m_-4462269581093404228gmail-field-odd m_-4462269581093404228gmail-field">
                                                          <th class="m_-4462269581093404228gmail-field-name">Ensures:</th>
                                                          <td class="m_-4462269581093404228gmail-field-body">
                                                          <ul class="m_-4462269581093404228gmail-first m_-4462269581093404228gmail-last m_-4462269581093404228gmail-simple">
                                                          <li><code class="m_-4462269581093404228gmail-code m_-4462269581093404228gmail-docutils m_-4462269581093404228gmail-literal
gmail-notranslate"><span class="m_-4462269581093404228gmail-pre">len(result)</span> <span class="m_-4462269581093404228gmail-pre">>=</span>
                                                          <span class="m_-4462269581093404228gmail-pre">len(initial_paths)</span>
                                                          <span class="m_-4462269581093404228gmail-pre">if</span>
                                                          <span class="m_-4462269581093404228gmail-pre">initial_paths</span>
                                                          <span class="m_-4462269581093404228gmail-pre">else</span>
                                                          <span class="m_-4462269581093404228gmail-pre">result</span>
                                                          <span class="m_-4462269581093404228gmail-pre">==</span>
                                                          <span class="m_-4462269581093404228gmail-pre">[]</span></code></li>
                                                          <li><code class="m_-4462269581093404228gmail-code m_-4462269581093404228gmail-docutils m_-4462269581093404228gmail-literal
gmail-notranslate"><span class="m_-4462269581093404228gmail-pre">all(pth.is_absolute()</span>
                                                          <span class="m_-4462269581093404228gmail-pre">for</span>
                                                          <span class="m_-4462269581093404228gmail-pre">pth</span>
                                                          <span class="m_-4462269581093404228gmail-pre">in</span>
                                                          <span class="m_-4462269581093404228gmail-pre">result)</span></code></li>
                                                          <li><code class="m_-4462269581093404228gmail-code m_-4462269581093404228gmail-docutils m_-4462269581093404228gmail-literal
gmail-notranslate"><span class="m_-4462269581093404228gmail-pre">all(pth.is_file()</span> <span class="m_-4462269581093404228gmail-pre">for</span> <span class="m_-4462269581093404228gmail-pre">pth</span> <span class="m_-4462269581093404228gmail-pre">in</span> <span class="m_-4462269581093404228gmail-pre">result)</span></code></li>
                                                          </ul>
                                                          </td>
                                                          </tr>
                                                          </tbody>
                                                          </table>
                                                        </dd>
                                                      </dl>
                                                      <br>
                                                    </div>
                                                    <div>How is this
                                                      difficult to
                                                      read,[...]?<br>
                                                    </div>
                                                  </div>
                                                </div>
                                              </div>
                                            </div>
                                          </div>
                                        </div>
                                      </div>
                                    </div>
                                  </div>
                                </div>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
    This contract does not help me:  <br>
    <blockquote>Does it work on Windows? <br>
      What is_absolute()?  is <a class="m_-4462269581093404228moz-txt-link-rfc2396E">"file:///"</a> absolute?<br>
      How does this code fail?  <br>
      What does a permission access problem look like?  <br>
      Can initial_paths can be None? <br>
      Can initial_paths be files? directories?  <br>
      What are the side effects?<br>
      <br>
    </blockquote>
    resolve_initial_path() is a piece code is better understood by
    looking at the callers (#7), or not exposing it publicly (#11).  You
    can also use a different set of abstractions, to make the code
    easier to read:  <br>
       <br>
    UNION(file for p in initial_paths for file in p.leaves() if
    file.extension=="py") <br>
    <br>
    At a high level, I can see the allure of DbC:  Programming can be a
    craft, and a person can derive deep personal satisfaction from
    perfecting the code they work on. DbC provides you with more
    decoration, more elaboration, more ornamentation, more control. 
    This is not bad, but I see all your arguments as personal ascetic
    sense.  DbC is only appealing under certain accounting rules. 
    Please consider the possibility that "the best code" is: low $$$,
    buggy, full of tangles, and mostly gets the job done.   :)<br>
  </div>

_______________________________________________<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>