http://www.perlmonks.org?node_id=463589

srdst13 has asked for the wisdom of the Perl Monks concerning the following question:

There are a plethora of modules for auto-generating accessor/mutator methods including Class::MethodMaker, Class::Struct, Class::Accessor, and several others. I've been through the documentation of the first three and just wanted to hear what people thought of each. Are there strong reasons (or any reasons, for that matter) for using one over the next? Are there others that one "must" consider?

Thanks,
Sean
  • Comment on Modules for autogenerating accessor/mutator methods

Replies are listed 'Best First'.
Re: Modules for autogenerating accessor/mutator methods
by other90percent (Sexton) on Jun 05, 2005 at 00:16 UTC

    Accessor generation is very handy when you've got a 'big' object model sketched out - the nouns of your application - and you'd like to flesh out that model quickly in Perl, so you can get on to how those objects interact. It's also good coding practice to reduce redundant code, and accessor/mutator generation helps quite a bit there.

    I've used Class::Accessor several times, and it's pretty easy-going. It's very good for cases where you have many classes to implement, and they're all fairly similar (in the since that they are all composites of each other or simple scalar datatypes). It's easy to have validating mutators. Class::Accessor is also nice about not getting in your way; if you want, you can use it to generate only some of your methods, and hand-code the "interesting" ones yourself.

    Class::Accessor can also be used on-the-fly (at runtime) to add new methods, though most people won't need such a fancy trick. Just call $obj->mk_accessor() and you can add bells and whistles as needed. But most object models don't need to go around redefining their schemas.

    Class::MethodMaker, Class::MakeMethods, and many other approaches want to be compile-time only, which might be "safer", or at least "saner". In other words, you define your classes in like this (varies a bit):

    use Class::MyFavoriteMethodGenerator qw( YOUR-CLASS-DEF-HERE );

    where YOUR-CLASS-DEF-HERE is usually a hash of attribute names and options (read-only, etc).

    Class::MakeMethods is much more ambitious about generating more complex methods for you, while trying to keep your class definition code as simple as possible. Try it, and see if you like it.

Re: Modules for autogenerating accessor/mutator methods
by Ovid (Cardinal) on Jun 04, 2005 at 21:36 UTC

    There's also Class::Meta. For most applications it's overkill. However, if you need introspection (think "Reflection" if you're a Java guy), then Class::Meta is a great choice.

    Cheers,
    Ovid

    New address of my CGI Course.

Re: Modules for autogenerating accessor/mutator methods
by simonm (Vicar) on Jun 04, 2005 at 23:12 UTC
    I think this comes down to the kinds of accessor methods you need created.

    If you just need a few basic get/set methods, than any of these choices would be fine and I'd pick the simplest or the most popular.

    However, if you are generating a lot of different kinds of methods, you may need to base the decision on the types supported by each system.

    My own Class::MakeMethods supports hundreds of different method types, so if you're in the market for inside-out accessors, or accessors for array-based objects, or accessors which return closures that perform their action, or something else a bit out of the ordinary, it's worth wading through the volumnious documentation.

Re: Modules for autogenerating accessor/mutator methods
by wazoox (Prior) on Jun 04, 2005 at 21:30 UTC
    I'll even add to your question: is there any reason not to write accessors/mutators ourself?
        Hey, that was my answer! However, these modules exist and are definitely being used. Class::DBI is a prime example. I really don't get much out of writing simple accessors/mutators. If they get more complicated, I would of course like to have the Module move over and facilitate my creating a custom method, which most seem to offer as an option. I think the question still stands as to which, if any, is "better" than the next (or what less-than-obvious advantages exist in one versus the next).

        Sean
        Really I'm not sure. An accessor/mutator is often very simple, so where is laziness? writing the quick'n'dirty one that "just works" or use a complex module that provides complex options and try to learn how it works --and may bite?

      When a lot ( > 2 ) of your subroutines have the exact same code, why type it more than once? :)

      Other than that, some things generate lots and lots of accessors. Writing some code to automatically generate them all means less typing and a single point of maintenance when you decide you need to change them all.

      --
      brian d foy <brian@stonehenge.com>

      I'll even add to your question: is there any reason not to write accessors/mutators ourself?

      Because then we would also have to write tests for them.

      Michael

Re: Modules for autogenerating accessor/mutator methods
by wolv (Pilgrim) on Jun 05, 2005 at 13:10 UTC
    Attribute::Property is very elegant and simple. I like it mainly because it adds so little typing, instead using Perl's attributes to make any sub a property (accessor).
    package Automobile; sub new : New; sub colour : Property; sub owner : Property { /^(?:Jack|Jill|Bob)$/ } package main; my $car = Automobile->new(colour => "red"); print $car->colour; # red $car->colour = "blue"; print $car->colour; # blue my $other_car = Automobile->new(owner => "Jack"); # works my $another_car = Automobile->new(owner => "Dad"); # fails
Re: Modules for autogenerating accessor/mutator methods
by TheDamian (Vicar) on Jun 05, 2005 at 22:44 UTC
    Are there others that one "must" consider?
    Well, there's certainly no must about it, but I'd encourage you to look at my new Class::Std module, as well as Abigail's Lexical::Attributes.

    Damian

Re: Modules for autogenerating accessor/mutator methods
by johnnywang (Priest) on Jun 05, 2005 at 17:28 UTC
    There were a couple of blogs with titles like "getters/setters considered harmful for python/php". The authors were proposing to access the member variables directly, unless one wants to add some logic like validation. That, of couse, breaks encapsulation. Any comments?

      The blogger agrees that you should make your object's data available to the outside world in a way lets you change the underlying implemtation when you need to.

      In Java, it seems like the "best practice" is to copy and paste a bunch of identical get/set methods.

      The blogger seems to be against copying and pasting when native language features can give you the same benefit. With Python (apparently) you can use the built-in features to make public attributes that can be transparently upgraded from simple attributes to get/set methods, without changing the API:

      contact.email = "x@x.com"

      Behind the scenes this can be implemented by a simple attribute variable or a get/set method. The user of the object doesn't care.

      This feature isn't built in to Perl 5. If you break encapsulation and access the underlying hash keys directly:

      $contact->{'email'} = "x@x.com";

      Then you can't protect the access without a tied hash. On the other hand, if you wrap the accessor in a method:

      $contact->email("x@x.com");

      Then you have to copy and paste multiple identical get/set methods.

      The better solution is to let a module generate the methods for you. For instance, Attribute::Property (which looks excellent, BTW - thanks for pointing it out, wolv!), automatically makes methods that are assignable like hash elements:

      # module code sub email : Property; # ... # user code $contact->email = "x@x.com";

      When you need to upgrade 'email' to do some validation, you can change the accessor into a full sub:

      # module code sub email { # do some validation or processing here } # ... # user code - API stays the same. $contact->email = "x@x.com";

      Michael

        Mind you, Attribute::Property generates lvalue subroutines, so a simple 'sub email { }' won't replace the interface in a compatible way. Furthermore, A::P supports adding validation and processing: sub email : Property { process; validate } The return value of the block will indicate whether the value given validates.
Re: Modules for autogenerating accessor/mutator methods
by ambrus (Abbot) on Jun 05, 2005 at 16:11 UTC

    If you need objects, use Ruby. It has efficent accessor/mutator generating methods built in, called attr, attr_reader, attr_writer, attr_accessor in the Module class.