http://qs321.pair.com?node_id=309969


in reply to Why get() and set() accessor methods are evil

I had a short flame war with an Anony Monk about this not long ago (starts here). I'm now starting to come around to this point of view. One of my arguments was that Class::DBI is pretty much nothing but a fancy system for automatic get/set creators.

In this article, I had orginally taken the author's point of view as a puritanical stance against any method that matches / ( get | set ) /x. After reading the "Why getter and setter methods are evil" article (linked to above), where the author explains his views more fully, I realized that it's not that accessors and mutators are problems in themselves, but ones that return primitives (strings, integers, etc.) are. Returning complex objects is something you do all the time, and it doesn't matter if the method happens to have the word 'get' or 'set' in it. On occasion, it's necessary to return primitives, but you can do it with objects more often than not.

In a recent project I was given that was going to use Class::DBI, I realized that many of the fields we use could take objects, using the inflate/deflate params to has_a. Have a date field? It should take a DateTime object (or one of Perl's other date/time objects). Storing a URI? It should take a URI object.

In this project, one of our tables has 22 fields. Of that number, 13 take objects (5 of which are relations to other Class::DBI objects), and 1 is the primary key (which is a primitive integer out of necessity).

Of the remaining 8, three are boolean fields--can't do a lot with that, and making them objects wouldn't add anything. For one of the fields, we're not sure how its going to be implemented, so it's being left alone for now. Two others are strings from user input. I suppose they could become objects, but I don't see a benifit to doing so. The last two are unsigned integers and deal with a number of hours. They could potentially become DateTime fields.

So in all, there are three fields where making them an object would be pointless, and two others where (IMHO) it would be silly to make them objects.

I also realized that using objects, you can use Perl's object system to limit (to an extent) what goes into a MySQL ENUM or SET column (this technique is probably worthy of a meditation on its own). For instance, say you have a column declared:

foo ENUM( "bar", "baz") NOT NULL

Your Class::DBI subclass could use this:

my $foo_bar = 1; # Could store the string representation, too my $foo_baz = 2; sub FOO_BAR { bless \$foo_bar, __PACKAGE__ . '::FOO' } sub FOO_BAZ { bless \$foo_baz, __PACKAGE__ . '::FOO' } __PACKAGE__->has_a( foo => (__PACKAGE__ . '::FOO'), inflate => sub { my $f = shift; bless \$f, __PACKAGE__ . '::FOO' } +, deflate => sub { my $f = shift; $$f; }, );

If you wanted to, you could then delcare a package the same name as this table's class with a '::FOO' at the end and add methods there. Then you put a note in your documentation so people will know to use the subroutines to get the data to go in that column.

----
I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer

: () { :|:& };:

Note: All code is untested, unless otherwise stated

Replies are listed 'Best First'.
Re: Re: Why get() and set() accessor methods are evil
by Ovid (Cardinal) on Nov 25, 2003 at 20:46 UTC

    hardburn wrote: Two others are strings from user input. I suppose they could become objects, but I don't see a benifit to doing so.

    While I don't think you meant to, you actually touched on a fundamental point in favor of OO programming: create an object when you have invariants that must be respected.

    If the user can enter any arbitrary string, then there's not much point in using an object. However, if the string must be validated in some way (such as with a URI), then creating an object is perfect. At the very least, I suspect that your strings might have a length limit. If that is the only invariant that you need to worry about, perhaps it's not worth the overhead of creating an object (particularly since you'll likely be validating length via your Class::DBI objects). If you have any more invariants, then using an objects can be a great way to ensure that the data is what you intended it to be.

    Cheers,
    Ovid

    New address of my CGI Course.

Re: Re: Why get() and set() accessor methods are evil
by Anonymous Monk on Nov 25, 2003 at 18:13 UTC
    I realized that it's not that accessors and mutators are problems in themselves, but ones that return primitives (strings, integers, etc.) are. Returning complex objects is something you do all the time, and it doesn't matter if the method happens to have the word 'get' or 'set' in it

    Just a point of clarification: Get/Set methods are a short way of labelling methods that access an objects attributes, that is, methods that are only concerned with reading or writing object state directly. It has nothing to do with whether the value of that slot is a primitive or an object, but whether it represents object-state. Objects should rarely provide methods to the outside world that are only concerened with accessing state.