Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
makes my code less sexy

That is such a common motivation for the use of "worst practices". I don't want sexy code. I want clear code. Ugly is often a good thing. Perl is full of ugly sigils, which is something I liked from the beginning. I find they can greatly aid clarity and speed visual parsing of code.

But the worst thing that the desire for sexy code does is motivate the use of huge piles of problematic hidden complexity just to get slightly "cleaner" syntax. That leads to source filters and similar madness. I've read Devel::Declare documentation that goes to great lengths to talk about how stupid of an idea a Perl source filter is. And then the developers implement something almost identical to a source filter (and having the same level and type of problems). And their motivation for such a stupid thing? They didn't want you to have to type one single "extra" character (a semicolon).

I urge you to get over the desire to be aroused by reading source code.

I wouldn't want %_. Unpack your arguments into lexical variables at the top of the sub. Typing $_{whatever} over and over doesn't detect when you typo the key name. Please oh please don't require people to search the entire code of your routine in order to figure out what parameters can be passed to it!

Not too long ago we spent some time standardizing argument passing for our team's Perl best practices. We standardized on passing named arguments in this manner:

whatever( { user_id => $user, campaign => $cmp } );

You'll note the inclusion of ugly brace characters, { and }. Part of the reason for that is because those tell the person reading the Perl code that the stuff inside is key/value pairs forming a real hash. For example, that makes it clear that order cannot matter. It also tells Perl that these are real name/value pairs.

We also do that because it helps avoid the temptation of extending interfaces in ambiguous ways. For example, we separate the key/value pairs for DB records from key/value pairs for optional method arguments from the tiny number of simple, required method arguments (if any):

$account->add_client( $db, # DBI handle { name => $client, status => 'new' }, # Data { require_unique => 1 }, # Options );

We explored a bunch of possible interfaces for providing a helper for unpacking such arguments. But no interface was other than trivially shorter than the below. And they were all significantly less flexible and less obvious (and each had different, worse problems).

sub add_client { my( $db, $rec, $opt, @bad ) = @_; $opt ||= {}; my $uniq = delete $opt->{require_unique} || 0; my $fatal = delete $opt->{fail_fatal} // ! $uniq; my $contract = delete $opt->{contract}; my $context = _context( delete $opt->{referrer} ); argue( \$opt, \@bad, { db => $db, rec => $rec } );

argue() just complains about unknown options, too many arguments, or (the simpler cases of) missing required arguments, filling in the sub/method name and the calling line of code for you.

Those few ugly, somewhat repetitive lines have the advantage of being ordinary, real Perl code. So they support things you might want like comments. The default values can be any Perl code (including based on other arguments). You can distinguish between || and // (and other tests). You can preprocess arguments. And all of these things are completely clear to anybody who can read Perl code. Yet most of the time we have just 1 line per option.

Yep, you can certainly consider it boilerplate. But it is clear, informative, flexible boilerplate. Ugly and so very useful.

- tye        


In reply to Re: Why doesn't Perl provide %_ as the hash equivalent of @_ in subs? (ugly++) by tye
in thread Why doesn't Perl provide %_ as the hash equivalent of @_ in subs? by smls

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 browsing the Monastery: (4)
As of 2024-04-25 18:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found