Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
Ah. Interesting. Tell me then, which is more readable:

if an assertion fails, return false.
if an assertion fails, return false.
if an assertion fails, return false.
return true

or

return the combined success of assertion one and assertion two and assertion three

Wait, lets try that again:

if an assertion fails, return false.
if an assertion fails, return false.
if an assertion fails, return false.
if an assertion fails, return false.
if an assertion fails, return false.
if an assertion fails, return false.
return true

vs:

return the combined success of assertion one and assertion two and assertion three and assertion four and assertion five and assertion six

Now I have little doubt this will prove to be debatable. In my opinion however, for humans, the first is easier to read, and more importantly, more consistant (WHAT! You say consistant? why is this consistant evl PhiRatE person! well, explainations shall be forthcoming).

The concept I utilised is one known as a "Guard clause". It is, by my own admission, entirely overkill in the two and maybe in the three condition simple function that we're playing with now, however it becomes very important in more complex functions, and thus the principle of being consistant with your code suggests that (given no appreciable efficiency or readability loss) you should use it in simpler functions as well.

The normal "best case" example for guard clauses is like this:

function a ($fruit, $vegetable) { if (!$fruit) { return; } # Guard clause if ($vegetable) { print "Fruit and Vege"; } else { print "Just the fruit ma'am"; } }

The idea being that arguments to the function and trivial tests are done immediately upon entry. The reasoning behind this is simple, it is easier to read nothing than it is to read anything, no matter how readable anything is. Thus, if you are tracking a bug through a series of functions, the earlier you encounter something that says "that condition is taken care of in this manner" the sooner you can stop reading that function and get back to finding the typo in line 700 of ObscureFoo.pm.

As such, I maintain that, except in simple cases (such as the one we are really supposed to be talking about :) guard clauses are a superior method of laying out a set of "deny" rules as it were (or accept rules if your function suits it), rather than creating a stacked boolean expression. It also has the benefit of extending elegantly to multi-line operations and individual operations depending on exactly what failed (Too many items! Item not recognised!) without completely refactoring the expression (into guard clauses anyway). (If you wish an exercise to test this, take the function we were working on, and get it to throw an exception when there are too many items. In mine you can do it with one change, in yours, you must effectively write mine, then make the change.)

So, while I agree that in the case specified, your example is marginally easier to read than mine, I maintain that my structure provides, overall, more consistency with the rest of the code likely to be written, and supports later modification with less issue.

I agree that the primary purpose of source code is to be read by a programmer, but I also recall that the biggest cause of failure in source code is incorrect modification. It would seem to me then, that a very light cost in readability for the advantage of seamless and elegant modification is a win, as is a general consistency with other, similar but more complex operations elsewhere in the code.

Of course, such things seem to be to some extent subjective. Interestingly I'm usually annoyed by this assertion since I believe very few things in programming are really as subjective as they are made out to be, however I have one particular aspect which "warps" my opinion of certian practices. I have a bloody awful memory :)

Thus, any practice which means I need to read less code (in ops, not in lines or characters) and remember fewer things (contents of variables, meanings of obscurely named functions, constants) tends to weigh higher with me than with some other programmers I know.

Guard clauses fall squarely into this category, with the amount of code read per debugging hunt being considerably reduced in the average case by the presence of negative assertions right at the start of each function.

People with a better memory may see less benefit from this technique :)


In reply to Re: Re^4: Pattern Matching Query by PhiRatE
in thread Pattern Matching Query by Elgon

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2024-03-28 17:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found