in reply to Re: Class attribute get/set approach flaws?
in thread Class attribute get/set approach flaws?

Not necessarily true. It can actually make code easier to work with.

my %validation_for = ( foo => qr/^\d+$/, # foo must be an integer bar => \&validate, }: sub attr { my ( $self, $attr ) = splice @_, 0, 2; croak "No such attribute $attr" unless exists $validation_for{$attr} +; return $self->{$attr} unless @_; # set the value my $validation = $validation_for{$attr}; my $new_val = shift; if ('Regexp' eq ref $validation) { croak "$new_val doesn't match $validation" if $new_val !~ $validation; } else { $self->$validation($new_val); # we'll assume it throws an error } $self->{$attr} = $new_val; return $self; }

With that quick hack, adding a new attribute is as simple as adding a new key/value pair to the validation lookup.

You can then use a single method for getter/setters for everything and still have validation. Whether or not that's appropriate for your needs depends on your requirements. Also, "extra" behavior can easily be added to the validation subroutine, though at that point you'd probably want to rename the hash.

Cheers,
Ovid

New address of my CGI Course.

Replies are listed 'Best First'.
Re^3: Class attribute get/set approach flaws?
by sauoq (Abbot) on Nov 28, 2005 at 23:48 UTC
    With that quick hack, adding a new attribute is as simple as adding a new key/value pair to the validation lookup.

    Well, that glosses over the fact that adding the key/value pair might not be easy depending on the validation and/or behavior you need for a given attribute... You might need to write a new validation function, for instance. And, you might want to change the names of things a bit if, for instance, you want functions that don't just perform validation but, say, set other values. (Change the radius and update the area, to use an example that's been used frequently today.)

    But, okay. Yeah. Sure. You can do things like that. I've even done it, though not quite like that.

    It might even buy you something in the common cases... I'm not sure how much though and I've come to think that just writing a separate method is easy enough and usually neater. So, that's what I usually do these days. (I do prefer accessors that both set and get though.)

    -sauoq
    "My two cents aren't worth a dime.";
    

      How do you avoid problems with passing in zero length lists when you're setting a value? How do you distinguish the setting form of $obj->foo( new_value() ) from $obj->foo() if new_value() might return an empty list?

        Why, the obvious way... I avoid the necessity, of course!

        My accessors take a single optional scalar. Period. If I have to pass a reference, I do. If I need to clone it, I do. It's easy. Straight forward. Simple. (And I'm really embracing simplicity as much as possible these days.) Mostly, my accessors look something like:

        sub foo { $self = shift; @_ <= 1 or croak 'Too many arguments (' . @_ . ')'; if (@_) { # do whatever I need to. } return $self->{foo}; # Or whatever. }

        I think the biggest plague among Perl programmers is a drive to be altogether too tricky when there isn't a real good reason to be. I know enough about Perl's quirkier features to believe it's better to avoid most of them much of the time.

        I've taken the Ruby-on-Rails slogan, "Convention Over Configuration" and modified it for my personal use:

        Convention Over Confusion

        † Well, okay... not "period" exactly... There are exceptions to every rule... but relatively few to this one.

        -sauoq
        "My two cents aren't worth a dime.";