http://qs1969.pair.com?node_id=532075


in reply to Class::Accessor and Damian's PBP

If you have so many accessible properties that you need to generate accessors for them, you may need to re-think your design. Accessors are a code smell.

But assuming you have good reason to have so many accessors, I'm sorry to say I don't have a satisfactory answer to your question. I would go with Class::Accessor::Lvalue because I think that something that behaves like a variable (being settable and gettable) should have an interface like a variable. It is also very clear about when you're setting and when you're getting. If you then use Class::Accessor for the read-only accessors, everything is taken care of.


Caution: Contents may have been coded under pressure.

Replies are listed 'Best First'.
Re^2: Class::Accessor and Damian's PBP
by grantm (Parson) on Feb 23, 2006 at 00:49 UTC
    If you have so many accessible properties that you need to generate accessors for them, you may need to re-think your design. Accessors are a code smell.

    I'm not sure that I entirely agree with that assertion.

    Most OO classes will have a number of properties, but unfortunately Perl's object model does not provide a standard way to define those properties. The simple and common approach is to store properties as keys in a hash but this leads to hard-to-find bugs resulting from typos in hash keys. Generating accessors is an effective way to eliminate that class of error.

    I do agree that lots of accessors in the public API of a class is often a problem with the design.

    The examples on the page you linked to seem to be written in a language that, unlike Perl, supports both properties and private methods.

      The simple and common approach is to store properties as keys in a hash but this leads to hard-to-find bugs resulting from typos in hash keys. Generating accessors is an effective way to eliminate that class of error.
      Have you already tried to use fields;?
      Not that I dislike accessors, but I think this is not the exact reason why they're good.


      acid06
      perl -e "print pack('h*', 16369646), scalar reverse $="
      The reason accessors are a code smell is that OO programming is supposed to be about objects performing tasks that they know how to do, not programmers fiddling with the objects' internal states. The internal states should primarily change as a result of interacting with their universe. If that's not the case, then maybe OO is the wrong approach.

      That is not to say that there should be no public accessors in good OO code. Code smell is not an absolute condemnation, it's just a marker that should make you think twice.


      Caution: Contents may have been coded under pressure.
Re^2: Class::Accessor and Damian's PBP
by nothingmuch (Priest) on Feb 22, 2006 at 20:59 UTC
    Whenever your setter needs to be normalized to a different value lvalue accessors don't cut it.
    -nuffin
    zz zZ Z Z #!perl
      Whenever your setter needs to be normalized to a different value lvalue accessors don't cut it.
      Well...that certainly used to be the case. Indeed, the fact that you have to employ the complexities of tied proxy variables to retain control when using lvalue accessors, is precisely why I cautioned against lvalue accessors in "Perl Best Practices".

      But last week I released the latest version of the Contextual::Return module, with which you can now hide all the complexity of tied proxies behind two simple LVALUE, and RVALUE blocks. For example:

      use Contextual::Return; # Name method offers unconstrained access... sub name : lvalue { my ($self) = @_; $name_of{ident $self}; } # Rank method constrains access: can assign only valid ranks # (value being assigned is passed as $_ to LVALUE block)... sub rank : lvalue { my ($self) = @_; LVALUE { croak "Invalid rank ($_) assigned" if !$is_valid_rank{$_}; $rank_of{ident $self} = $_; } RVALUE { $rank_of{ident $self}; } } # Serial method offers read-only access... sub serial { my ($self) = @_; return $snum_of{ident $self}; }

      With this functionality now available, I'm seriously reconsidering my long-held objections to lvalue accessors.

      Damian

        Wow, that's pretty nice... Great work =)

        -nuffin
        zz zZ Z Z #!perl
      Neither do generated accessors. So you have to write something. For either kind of accessor, tie is one way to do it.

      Caution: Contents may have been coded under pressure.
        uh, override the set method?

        -nuffin
        zz zZ Z Z #!perl
Re^2: Class::Accessor and Damian's PBP
by cbrandtbuffalo (Deacon) on Feb 23, 2006 at 12:47 UTC
    If you have so many accessible properties that you need to generate accessors for them, you may need to re-think your design.

    I'm working on a configuration module, so accessors and data are the primary purpose of the module. You can see some background in Configuration Best Practices for Web Apps.

    Even if you don't have many, though, I would argue the good kind of Laziness should drive you to use tools to avoid cut and paste. Even with just a few accessors, the code often ends up being largely cut and pasted, so using a module to automate the process is still a nice idea.

      After playing around in several directions, I realized that it's trivially easy to generate default accessors, which may be why there are so many modules for it (although it makes me wonder why there are any).
      for my $property (qw(several members defined public)) { no strict 'refs'; *{"get_$property"} = sub { (shift)->{$property} }; *{"set_$property"} = sub { (shift)->{$property} = $_[0] }; }

      Caution: Contents may have been coded under pressure.
        You got it. I took at look and that's almost exactly what Class::Accessor does.
Re^2: Class::Accessor and Damian's PBP
by diotalevi (Canon) on Feb 22, 2006 at 20:33 UTC

    Lvalue properties are fine if you're using Visual Basic or another language where they're better supported. They're a bad idea in perl.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      Could you elaborate more on this subject (or point me to other nodes regarding this discussion)?
      Are there any specific issues regarding Lvalue accessors so that everyone seems to dislike them?


      acid06
      perl -e "print pack('h*', 16369646), scalar reverse $="