Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

Re^2: Two simple code style advice questions (tye)

by BrowserUk (Patriarch)
on Jan 18, 2013 at 05:23 UTC ( #1013953=note: print w/replies, xml ) Need Help??

in reply to Re: Two simple code style advice questions (tye)
in thread Two simple code style advice questions

I find it significantly easier and faster to parse the intent.

Could you quantify (in some fashion) what you mean by "significantly easier and faster"?

my $mol = ( $n == 42 ) ? 'forty two' : '';
my $mol = ''; $mol = 'forty two' if 42 == $n;

I find your version quite horrible to parse.

  • Is that one statement or three?

    Oh! It's two!

  • And why is it (are they) all squished up like that?

    It looks like the the code-wrap routine has been given some ridiculously narrow width limit.

  • Why is he comparing a literal against a variable?

    Is the literal's value likely to suddenly change?

    (Yes. I am aware of the justifiction for the backward logic. :)

As for your last example, I find it almost incredulous that you would code that; and almost impossible to parse without reformatting it.

Why not just:

my $mol = defined $n ? ( $n == 42 ? 'fourty two' : '' ) : 'n/a';

I also find the concentration on the minutia of single statements far less important than the overall flow of the code.

That is, when scanning the code, I only need to recognise that $mol has been initialised, and then the next step and the next. I'll only be concerned with what it was initialised to once I understand the overall flow; and if I suspect that might be the source of the problem I'm looking for, or otherwise needs closer inspection.

I don't need to know all the details of each line (or 3 lines!) of code from an instantaneous glance. If I have to read the line twice to understand what it does -- maybe take 2 seconds instead of 1/2 a second -- it is no biggy in the scheme of things. But understanding the overall flow of the subroutine or block is far more important, and that -- for me at least -- means being able to see as much of that subroutine or block as -- clearly defined steps -- as possible. Which is why I infinitely prefer the one line versions to your 3 or 5 line examples.

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^3: Two simple code style advice questions (no reassembly required)
by tye (Sage) on Jan 18, 2013 at 17:25 UTC

    Of course, I didn't say it would be easier for you to parse.

    I can parse the three lines completely in a single glance, not having to pause to even wonder if the details of some complex expression are worth worrying about yet or not. The whole point of the code is already tucked away in my head after that one glance.

    But, no, I don't usually parse the flow while ignoring nearby details, because I find it rather time-consuming to construct the vague but complex (for me) "initializes $mol to something, but I haven't bothered to figure out what" concept. And such vague bits would just leave a mental snag to trip over repeatedly as I discern the purpose while mentally going over the flow. I find the factored-out bits need at least a nice name for me to be able to smoothly gloss over them when considering the flow. More often, I will understand some details of the factored-out bit before dismissing those details from consideration of the current flow (usually by assigning a decent name to that bit -- which is why subroutines are such a good way to factor out bits of complexity; they each get assigned a name).

    The expression is complex enough that I can't tell that it is simply initializing the variable to one of a few different values just by glancing at it. Once I start to parse the expression it takes more effort than a glance. My eyes have to focus on several parts and move back and forth matching up the bits to construct the meaning. By the time I've parsed it enough to tell that it isn't calling some subroutine (that might do complex work), I've already spent more time on the one line then I would have spent on the several lines and yet I still don't understand what the code is doing.

    Both of my multi-line versions parse effortlessly for me. I am not aware of even moving my eyes during the parsing. My mental focus smoothly shifts to each line, in order, instantly understanding the full code of the line and then the next line neatly snaps another detail onto the mental model without the need for any backtracking or restructuring.

    The worst problem of the relative bloat in number of lines is if the logical block of code (almost always a subroutine) gets pushed beyond "one screen full" and thus can't be parsed with just simple and fast eye movements. And that would usually lead to me being less "extravagant" or to factoring out some logical sub-section.

    my $mol = defined $n ? ( $n == 42 ? 'fourty two' : '' ) : 'n/a';

    That is a relative strain to parse in comparison. My experience is that matching up parens is one of the most time-consuming parsing tasks for humans (I've tested it using slide shows and even people who claim to match up parens easily can't do it quickly, IME). The constructs involved are not visually apparent. I'm forced to individually recognize single characters and then mentally re-assemble the logical structure from too many tiny pieces.

    This all reminds me of why newspapers print in rather narrow columns and how many people can read such very quickly without their eyes zigging back and forth (I don't think I'm one of those people, though).

    There are two ways I might try to parse that one complex line. The way that always works is to parse the components of it in order. That is slow because the number of parts to parse is much larger (for me) in the one-line case than in the multi-line cases.

    Using newlines to show each mental pause point, the code ends up in my head like:

    my $mol = defined $n ? ( $n == 42 ? 'fourty two' : '' ) : 'n/a' ;

    And then I have to backtrack several times to line up the '(' and the ')' and to line up the 2nd ':' with the first '?' and then it isn't obvious to me when which of the three values get chosen until I mentally simulate running the code, putting the conditions and values into proper association as I go.

    The second method is to glance over the code, recognizing the "obvious" bits and then filling in the gaps between them. That, for me, starts out as:

    my $mol = <noise> 'fourty two' <noise> 'n/a';

    Then I have to visually and mentally jump between the two "noise" piles and (frustratingly) spend mental effort dealing with single characters. Worse, I then have to tie single characters that aren't next to each other together in a complex structure that isn't represented visually.

    My last example gets parsed so smoothly for me. It is just 4 simple visual pieces that are also 4 simple mental pieces:

    my $mol = ! defined $n ? 'n/a' : 42 == $n ? 'forty two' : '';

    The second piece is the best example of why I prefer my version to yours:

    my $mol = defined $n ? ( $n == 42 ? 'fourty two' : '' ) : 'n/a'; # ^^^^^^^^^^ ^^^^^

    'n/a' is the value that represents "not defined". This is so very much more obscured in your version of the code. It is a single visual and mental chunk in my versions. No re-assembly required.

    Your mileage may vary, obviously.

    Note that I'm talking tiny optimizations here. It might take me 1 or even 2 seconds to parse your complex line. But when reading code, spending that much time on a line is a very long time. When the lines aren't complex, I can scan a whole screen of code in 1 second and understand it.

    And it isn't that I find your most complex line of code unacceptable or even fundamentally difficult to parse. I'd even write the following:

    my $mol = ! defined $n ? 'n/a/' : $n == 42 ? 'fourty two' : '';

    if I had a well-factored subroutine that barely fit on a screenful of lines with that as one of them.

    But if I got the subroutine factored to be smaller, I'd get extravagant with those short expressions and be so happy to re-parse and understand the whole subroutine without even having to degrade out of just needing quick glances.

    - tye        

      Geez! And people call me contrary! But each to their own :)

      Which neatly segways to my theme of the month: Imposing opinions in the name of best practices or automated critique, is fundamentally flawed.

      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1013953]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (1)
As of 2022-05-21 12:10 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (76 votes). Check out past polls.