On Sun, 9 Oct 2022 at 15:39, Axy via Python-list <python-list@python.org> wrote:

"shortest block first"

Have never heard this advice before. Kind-of rankled with me, as it did for others.

Enquiring minds want to know... Played Duck, duck, go on this: zero hits amongst a pile of similar phrases - turns-out there's an algorithm with a similar name, but not related, and an electronics approach (way too 'low' a level for translation to us though).

Tried prefixing with "program" but no such advice to programmers or program[me] designers.

Tried prefixing with "python", but equal lack of joy.

Would OP please quote source?


On 10/10/2022 05.56, Peter J. Holzer wrote:
On 2022-10-09 12:18:09 -0400, Avi Gross wrote:
Smallest code blocks first may be a more modern invention.

None of the recent-grads or new-hires I've asked this morning (it's already Monday over-here!) have used or heard the term.


Some would argue for a rule related to efficiency of execution. When you
have multiple blocks as in an if-else or case statement with multiple
choices, that you order the most common cases first. Those shorten
execution more often than the rarer cases especially the ones that should
never happen.

Those of us who started programming on 8 bit homecomputers of course
have efficiency always at the back of their heads, but I find this

... for mainframes just as much as micro-computers!

Regarding execution-efficiencies, I'm sure @Avi knows better than I: It seems likely that Python, as an interpreted language, will create 'blocks' of its virtual-machine code in the same order as they appear in the Python-source. However, aren't there optimising compilers which do something intelligent with the equivalent clauses/suites in other languages?

Regardless, is a Jump-instruction which transfers else-control to a block five machine-instructions 'down', any less efficient than a jump which spans 50-instructions?


So not a rule but realistically not always a bad idea to write code in a
way that draws the attention of readers along the main path of execution
and perhaps not showing all the checking for odd cases first.

much more important. Putting the main path first makes it easier to
understand what the code is supposed to do normally. All those pesky
exceptions are in the "small print" below.

Absolutely! Has the term "readability" been used 'here'?

Human nature (or is it that of computer programmers in-particular) is to be optimistic: it will work [this time*]. Accordingly, a colleague talks of always coding 'the happy line' first (meaning line of logic, cf source-code).

Contrarily, for while-True (infinite) loops, and particularly recursive algorithms, the [wise] counsel is to code the end-condition first. (always know your closest exit! "The nearest exit may be behind you"...)


Indeed, dare I say, this optimistic-approach is pythonic. Taking an over-simple, two-value division example, the approach is:

try:
    a = b / c
except ZeroDivisionError:
    ... clean-up the mess ...

which contrasts the EAFP philosophy of Python versus the LBYL expectation of (many) other languages:

assert c != 0
a = b / c

That said, as "Data Science" use of Python expands, it is bringing more and more needs for an LBYL attitude, eg "data cleaning".

(EAFP, LBYL? https://docs.python.org/3.9/glossary.html)


There is of course the opposite view that you should just get all of the
confounding factors out of the way first, so that the default is also
the common case. I also do that sometimes, but then I don't hide this in
in an else: clause but do something like this:

for item in whatever:
     if not_this_one(item):
         continue
     if neither_this_one(item):
         continue
     if cant_continue(item):
         break
     if oopsie():
         raise SomeError()

     do_something_with(item)
     and_some_more(item)
     we_are_done(item)

which shows visually what the main purpose of the loop (or function or
other block) is.

Nicely stated!

NB I've seen sufficient of @Peter's posts to know that this was never (even implied to be) intended as a snippet for all occasions!


It also illustrates why such is less readable: because we have to scan four if-statements before we can 'see' the purpose of the loop. My 'itch' would be to extract this code 'out' to a function - that way the name will convey the somewhat-obscured purpose of the loop.


Alternately, reduce the 'distractions':-

try:
    for item in whatever:
        inspect_the_data( item )
        do_something_with(item)
        and_some_more(item)
        we_are_done(item)
except SomeError:
    ...
except CustomBreakException:
    ... ?pass?                          # same effect as break

by 'hiding' in:

def inspect_the_data( item ):
    if not_this_one(item):
        continue
    if neither_this_one(item):
        continue
    if cant_continue(item):
        raise CustomBreakException      # was break
    if oopsie():
        raise SomeError()


It is now easier to understand 'the happy line', ie the thinking of the original-coder, and the 'small print' has been relegated to such and can be cheerfully disregarded.

Whereas, if 'exceptional circumstances' is the reason one is inspecting the code in the first-place, then it also helps to have separated-out the ifs-buts-and-maybes, and into a structure which can be as closely (and exhaustively) tested, as may be required.


In some ways, (IMHO) there are reasons to feel disquiet over this style of coding. Learning "Modular Programming", and slightly-later "Structured Programming", when they were still new (?fresh, ?exciting), we were inculcated with the 'one way in, one way out' philosophy-of-correctness. This applied to "blocks" of code (per "module"), as well as formal units, eg functions.

Accordingly, am slightly unnerved by seeing Exceptions being used to 'jump out' of interior/nested blocks, rather than using the return-mechanism (taking their turn like all the good little boys and girls). That said, it makes for tidier code - so I'll stop muttering into my (grey) beard ...


The alternative, assuming the 'errors and omissions' function is a possible tactic(!), would be to return a boolean, eg

def is_clean_data( item )->bool:
    is_verified = False
    if ...
    ...
    return is_verified

- thus the do-stuff calls will become a 'successful' if-then 'suite'.


There is more code to write/read - and the toy-example lends itself to such a tactic. In other situations, perhaps some refactoring or pre-processing, even a decorator, might remove (or reduce) the need for so much checking within the loop/block.


When to use one or the other approach?

We could hide behind some 'mystery', and say "I just know from experience", but that smacks of a secret coin-toss (human 'gut feelings' not being particularly indicative of success). So, here's a stab at it which harks back to the learn/use 'COBOL or FORTRAN' [argument] days:

If the purpose/considerations of the for-loop (block), are:-
- data-related: check-first
        (and thus consider extract and/or invert to promote readability)
- logic/algorithmic implementation, take 'the happy line' first
        (and deal with the exceptions ("small print") later)


Worthy of consideration, is that Python is (still) fast-developing. The switch-case construct of v3.10, and protocols and beefed-up descriptors (?interfaces?) could have quite an impact on such thinking, and in the relatively near-future...


* back in the ?bad old days when testing was something that was (only) done AFTER coding was complete, ie ego-driven development. The traditional response to the question: "are you coming to lunch/dinner/supper/break/the party/bed/...?" was "in a moment - [surely?] there's only one more bug"!


I've been 'dipping into' Martin Fowler's "Refactoring", 2e, Pearson, 2019; but don't have it with me to point to useful references. What I do have to-hand, because it has just arrived, is Mariano Anaya's "Clean Code in Python", (also 2e), Packt, 2020* - although I didn't see its previous edition, and have read nothing beyond the Contents(!) to-date; it talks of "Design by Contract", "Defensive Programming", "Separation of Concerns" indicating it may have thinking to offer.

* the reviewer was Tarek Ziadé, author of "Expert Python", which is worth reading - as are his other works (in English and in French)
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to