Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re^6: What is code readability?

by BrowserUk (Patriarch)
on Jan 14, 2007 at 12:45 UTC ( [id://594631]=note: print w/replies, xml ) Need Help??


in reply to Re^5: What is code readability?
in thread What is code readability?

Hmm. I really do have a strong aversion to this vertical coding style. I've attempted to explain the reasons for this on many occasions here and elsewhere, but I'm not sure I've ever done so successfully. I may try again at the end of this post, or in another post.

I'm also skeptical about the need for/benefits of named arguments. For example, there are very few functions in perlfunc that take more than 4 arguments. And for those that do, those beyond 4 are final LISTs that extend indefinitely in an obvious and unnameable way.

Of those that (can) take four, non-list arguments, the ones I use regularly: splice, substr, index, rindex, vec, open/sysopen, read/sysread/syswrite; I do remember the ordering without any specific effort to do so.

Of the others in perlfunc that take four or more args, most of which I have rarely if ever had occasion to use--mostly because they don't work or make little sense on my platform--I would have to look them up. But then, I'd have to look them up anyway just to know what they do, and what they require to do it--let alone what order they expect those things in.

Of the APIs that use named argument interfaces that I use regularly, the IO::Socket::* constructor is probably the one I've used most. And if I ever need to call that in anything other than the simplest $sock = IO::Socket::INET->new('127.0.0.1:25'); form, I always have to look it up. In large part because I can never remember the correct capitalisation of the argument names!

The upshot is that I think that

  • A well defined API rarely needs more that 4 or 5 arguments.

    If you find yourself writing APIs that require more than 4 or 5 arguments then that is usually indicative of more fundamental problems in your architecture.

  • Where more than 3 arguments are required, there is generally an obvious, 'natural ordering' that makes the need for naming the arguments redundant.

    This, as in so many ways, Perl's API is exemplary in the way it DWIMs.

    This is one (of several) reasons why I get irked by people recommending the substitution of modules that are bare wrappers around Perl's built-in APIs. Perl has one of the richest and complete, yet simplest set of built-ins of any language. Despite all of it's well-known quirks, foopars, anomalies and out-right errors, as a whole, it hangs together and works together to provide immense power without the need to resort to loads of often incompatible add-ons, tack-ons and overarching frameworks to get the vast majority of things done.

    There are many modules on CPAN that set out to 'correct' some perceived flaw in Perl's built-ins that wrap a simple, cohesive API in a behemoth of a (usually OO) API that creates as many problems as it fixes. And in doing so, forces the maintenance programmer of code using those modules to have to learn all the twists, roundabout, flaws and limitations of that API--in addition to knowing those of Perl itself. This is false economy in 90% (made up statistic warning!) of cases.

  • In many situations, naming arguments simply shifts the problem.

    You end up looking up the API documentation in order to remember what arguments are required/optional; how they are spelt; what naming conventions are used; etc. Once you've looked it up, the ordering is the easiest thing to document and read.

  • And actually, looking up the documentation for APIs is a 'Good Thing'.

    Assuming that is a reasonably simple process--which it should be--then scanning the documentation even for APIs that you're familiar with will often remind you of quirks, caveats, short cuts or alternatives that may not have immediately sprung to mind had you not.

    And even for 'simple' APIs, there are often reasons other than the ordering, for looking at the documentation.

There are occasions when it is necessary to have an API with more than 4 or 5 arguments and for which named arguments makes sense, but on those occasions there are several things that (IMO) should be true.

  • Argument names should be short.
  • They should be passed as pairs, not as you have shown as a hashref:

    Eg:

    sub some_function { my (%args) = @_; # no need to worry about the order here either } ## optionally sub someMethod { my( $self, $mandatoryFirstArg, %args ) = @_; # no need to worry about the order here either }
  • Names should be case-insensitive.

    Not easy to do with Perl's hashes, but still very desirable for a bunch of reasons. It's easier to arrange with the camelCasesNamingConvention than it is with the underscaler_separated_naming_convention.

    The use of Mixed_Case_And_Underscore_Separated naming should be outlawed by the UN and enforced by OHCHR under the heading of "Crimes against Humanity" :)

  • Often, hash-based named argument interfaces can (and would be better) replaced by the use of a 'string' interface.

    The 'simple' form of the IO::Socket::* constructor is a good example of this.


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?
Username:
Password:

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

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

    No recent polls found