Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

In reading through M. Conway's Best Practices, I must say that there are a few areas where I'm disappointed to discover that he's not enlightened enough for my one true way ™. For the most part, though, I'm quite delighted to find eloquently stated reasons backing up many things I do. I was particularly happy to find him recommending programmers not use tied variables or lvalue subs. They've always struck me as hacks. And what do those hacks buy us? Well, nothing, really. OK, some tied hashes are useful, but I think said usefulness is overblown.

I know how to tie variables, but I don't like to. In fact, I can't recall a single time I've tied a variable in production code. If one really needs to alter the semantics of built-in datatypes, switch to a damned object, will ya? Tied variables are slow, they're mysterious if you don't realize they're tied (this has caused me a lot of pain) and it's easy to implement them incorrectly. One of their biggest problems is that you can't just look at a single line of code with them and know that something is amiss.

And this brings me to lvalue subs (not just lvalues, as He Who Must Not Be Named pointed out below). These little beasties, in case you're not familiar with them, are what's known as a "big bucket of suck". They let you do this:

sub name :lvalue { shift->name } # and later $object->name = [qw/ random unvalidated value which breaks encapsulation /];

This brings up an interesting question. Why would I, the conscientous Perl programmer, want to throw away my hard-won encapsulation by switching to lvalues? Yeah, I was lazy and saved a line of code in my name method, but that's a bad lazy. I can no longer validate my data. Of course, some lvalue fans argue that I can use tie to get my validation back. Great! Now I've lost much of the conciseness I've hoped to gain and I've probably moved the data validation code away from the method in which the maintenance programmer expects to see it but at least I've switched to a slow, confusing and fragile interface! And hey, if you disagree with that, go argue with the Damianator who already took a Gatling gun to tie. (Wouldn't that have made an interesting movie? "I'll be back, mate." However, I'm not sure switching from an Austrian to an Australian accent would inspire the right amount of dread).

And while we're at it, I can't say I'm a huge fan of overloading accessors to also be mutators. I've done it, but I don't like it. It turns out that the Damianator recommends against this, too. It's easy to write buggy code:

sub name { my $self = shift; return $self->{name} unless @_; $self->{name} = shift; return $self; }

Answer quickly! Does the following set the name or not?


The short answer: maybe. You see, it's impossible to tell by visual inspection if that array has any elements. You can trace through the code and guess, but now you've lost data validation (throwing away information is rarely a good idea) and have a silent failure. Compare that with this:

sub set_name { my $self = shift; croak "set_name() requires a name, silly!" unless @_; $self->{name} = shift; # insert other validation here }

Of course, once you start overloading the method name, what happens if you have a method which returns a value you can't set? Such as the database row id?

$object->name($name); $object->age($age); $object->id($id); # huh?

Does that silently fail? Did that accidentally change the ID you weren't supposed to change? Did you remember to throw an exception with a reasonable error message? Did the programmer using your code curse you out for not making it obvious what you can and cannot do with the methods? With proper getters and setters, you would not have these issues:

$object->set_name($name); $object->set_age($age); $object->set_id($id); # huh?

And the error:

Can't locate object method "set_id" via package ...

Now, we get a verbose failure and a reasonable error message without writing any code to do this. That's good Laziness.

tie, lvalue subs, and overloaded getter/setters: do leave home without 'em.

What features of Perl do you deliberately avoid and why?

Update: (sigh) fixed a couple of typos hv, herveus and AReed pointed out in /msgs. Thanks!


New address of my CGI Course.

Side note: lvalues got me to thinking about method call syntax. Geoff asks why some coding standards might require parentheses for method calls. One respondent speculated this might be a sop for those coming from other languages. Some languages (*cough* Java *cough*) alternatively require/forbid parentheses depending upon whether you're calling a method or accessing a property. Frankly, I don't like it when languages such as Java which force me to put the parentheses on a method call. In an OO point of view, why should I care that the value 42 was a property or computed on the fly? What if I hard-coded it at first and didn't encapsulate it in a method and later decided to calculate it? Yes, creating a property without encapsulation is a sign of bad design, but can anyone tell me why on earth it would be a good idea to allow that in a language? I'm stumped.

In reply to Things I Don't Use in Perl by Ovid

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

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

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

    How do I use this? | Other CB clients
    Other Users?
    Others having an uproarious good time at the Monastery: (5)
    As of 2020-10-20 12:30 GMT
    Find Nodes?
      Voting Booth?
      My favourite web site is:

      Results (210 votes). Check out past polls.