Guido sees the light: PEP 8 updated

Steven D'Aprano steve at pearwood.info
Sun Apr 17 21:57:01 EDT 2016


On Sun, 17 Apr 2016 09:01 pm, Marko Rauhamaa wrote:

> In fact, if you find yourself introducing coding "paragraphs" with
> comments:
> 
> def f(...):
> # I'll start by doing this
> ...
> # segueing into the middle portion
> ...
> # and finish it off as follows
> ...
> 
> you had better break those paragraphs off into separate functions. Just
> turn your comments into function names.

I'm reminded of the book "Refactoring - Ruby Edition" by Jay Fields, Shane
Harvie and Martin Fowler (which I strongly recommend, for what it's worth).
It is full of sections like:

Change Value to Reference
Change Reference to Value

Decompose Conditional
Recompose Conditional

and most relevant to this discussion:

Extract Method
Inline Method

(For "Method", substitute "Function".)

The intro to Extract Method says:

"You have a code fragment that can be grouped together."

and then the author explains that he looks for methods which are too long,
or code that needs a comment to explain what it does, and turns that
fragment of code into its own method.

But then the same author goes on to introduce Inline Method:

"A method's body is just as clear as its name."

and explains "sometimes you do come across a method in which the body is as
clear as the name. ... When this happens, you should then get rid of the
method. Indirection can be helpful, but needless indirection is
irritating."

Indeed.

Once your code is the most straight-forward and simple implementation of the
needed algorithm, it is hard to reduce complexity any further. All you can
do is move the complexity around. You can hide the complexity inside the
function, where it exposes itself only to those who need to dig into the
body of the function to understand what it does.

Or you can extract the code into functions of their own, which decreases the
internal complexity of the function, but increases the complexity of the
application or module.

Extract Method hides complexity of the function by moving it into the
module:

def Do_The_Thing():
    ...

def internal_subpart_start(): ...

def internal_subpart_middle(): ...

def internal_subpart_end(): ...


Inline Method reduces module complexity by moving it into the function:

def Do_The_Thing():
    ...  # internal subpart start
    ...  # internal subpart middle
    ...  # internal subpart end


But the total complexity remains the same.


One technique which is common in Pascal, but less so in Python, is to get
the best of both worlds by using nested functions. In Python syntax:


def Do_The_Thing():
    def internal_subpart_start(): ...
    def internal_subpart_middle(): ...
    def internal_subpart_end(): ...
    ...


This hides complexity of the function by moving it into the nested
functions, where they can be ignored, but without increasing the complexity
of the module. (Of course, the *total* complexity of module, function and
nested functions is the same.)




-- 
Steven




More information about the Python-list mailing list