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

I am writing an package (object) and was wondering if any monks have an opinon about the best way to access the attributes of the object.

should each attribute have its own accessor method or is it ok (or better) to have one accessor for all the attributes.

That is should my code look like:

my $name = $object->get_name;
 or
my $name = $object->get('name');
Or something else completely.

Thanks for the input.
(I used <pre> on purpose.)
I did look around. Why get() and set() accessor methods are evil had interesting thoughts, but I think it might be helpful to look at it again.

-- gam3
A picture is worth a thousand words, but takes 200K.

Replies are listed 'Best First'.
Re: Accessor methods again.
by gargle (Chaplain) on Oct 04, 2005 at 14:51 UTC

    Hi,

    As always, it depends. If you use different accessor methodes for each attribute you can easility mimic public,private, and protected access. See Re: OO - best way to have protected methods for more. If you don't need, don't use (kiss ;))

    Different setter methods have an advantage: you can put code in it to check the parameters. As the setting for the attribute in question only occurs in one place your code becomes simpler to update.

    A single getter/setter shared by all attributes can do the same but becomes complex the moment you have many attributes, plus, you loose the public, private, protected simplicity.

    --
    if ( 1 ) { $postman->ring() for (1..2); }
Re: Accessor methods again.
by Perl Mouse (Chaplain) on Oct 04, 2005 at 14:53 UTC
    It's hard to say what is "better" without saying what you consider "better".

    I prefer the ->get_name over ->get('name'). The former is easier to type - just one underscore vs 4 punctuation characters. It also let's perl do the boring work of name validation - if I mistype the method as get_anme, perl will complain it can't find such a method. But I have to write by own validation to catch get('anme').

    In lines of code, a general get method may be less (given enough attributes). OTOH, having one accessor per attribute makes for short, simple attributes, less room for error. And with a proper editor, having more lines of code doesn't mean it takes longer to write.

    But those are my preferences. You should do whatever makes you feel most comfortable.

    Perl --((8:>*
Re: Accessor methods again.
by ghenry (Vicar) on Oct 04, 2005 at 15:13 UTC

    You could adopt the Perl Best Practices recommendation for the naming conventions of methods:

    routine -> imperative_verb [_ adjective]? _ noun _ preposition
    | imperative_verb [_ adjective]? _ noun _ particle
    | imperative_verb [_ adjective]? _ noun

    This rule results in method names such as:
    get_record
    get_record_for
    eat_cookie
    eat_previous_cookie
    build_execution_profile_using

    This is lifted straight from the text, but if this is not allowed, I'll withdraw this post and recommend that you buy the book.

    Thanks, Gavin.

    Walking the road to enlightenment... I found a penguin and a camel on the way.....
    Fancy a yourname@perl.me.uk? Just ask!!!
Re: Accessor methods again.
by duff (Parson) on Oct 04, 2005 at 15:03 UTC
Re: Accessor methods again.
by Moron (Curate) on Oct 04, 2005 at 15:12 UTC
    I would recommend the third option (something else completely). It isn't object-oriented to pull the values out of an object like that and prevents it being data driven. It also means that immediately you are not using a method to do whatever you are trying to do, which rather defeats the purpose of having it as an object in the first place. If you say more exactly what you are trying to achieve, maybe we can advise more exactly how to do it in an OO way.

    -M

    Free your mind

      Pretend you have an object that represents something like an "Order" in the sense of a shopping cart order. The order object has all these attributes and methods, and after you have populated the order with a customer, a list of items, and finalized the order using your fancy methods, you want to print out the order information to the customer so they can have a look over it and send an e-mail message if something is wrong. Not an uncommon problem.

      It seems you are suggesting that instead of having accessor methods I can use to query specific data from the object and pass said data to something like a template system, you would have a method on the $order object called something like $order->print() or $order->fetch_printable() or something like that. In which case, we either have embedded HTML or template logic (where the templates are located, how to populate them) inside the class.

      Now pretend this information is embedded into an outer page. Fine, you can use a script to pull the printable and place it inside the other page. What if you want to use some specific information from the order to place in the TITLE of the page? For instance, the order number? Oh wait, we can't have accessors so we will have to have the order object generate the entire page.

      So then you get into this situation where each of your objects have to know how to render themselves completely (in the context of an entire web page, or pdf file, or gui window, etc.). But in order to render themselves, they need some information from other objects, which in turn requires accessors.

      So exactly what are you suggesting?
        There are several oo mechanisms that can overcome this, including inheritance and friendship. However, if, with a full understanding of oo techniques, a 'clean' OO implementation still doesn't fit the requirement then I would recommend not using OO rather than being forced from the outset to abuse it.

        -M

        Free your mind

      Howdy!

      I think what you meant to say was "it runs counter to encapsulation...".

      If you need to extract values from an object, you need a method. If you always use a method to fetch data from an object, you have no way of knowing (and no need to know) whether you are fetching an attribute or a computed value. Encapsulation means, among other things, that you have no need to know the distinction. The object makes certain data available to you via a well defined API, to wit, the methods frequently labeled "accessors".

      yours,
      Michael
        This is a very good point. I think it makes it clear that an object attributes should really each have a method. And the only time you would want to have something like a get/set method would be if the object is something like a bookshelf where you will be adding and removing arbitrary objects.

        Thanks for helping me think about this.

        -- gam3
        A picture is worth a thousand words, but takes 200K.