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


in reply to Re: RFC - Parameter Objects
in thread RFC - Parameter Objects

hossman wrote:

Why make the mutators "set_foo" ... why not just overload "foo" (ie: foo with args does a set, and returns true if-and-only-if the args are valid, without args returns whatever the parameter value(s) should be.

Sorry to come into this late, but I didn't feel the question was answered. There are a couple related reasons not to overload mutators or accessors.

Most of the time, coders are aware whether they intend to call a mutator in "set" or "get" mode. This awareness happens at coding time.

Having separate mutators for "set" and "get" allows code to be explicit about its intentions. Mutators may be prototyped such that accidentally supplying or omitting a parameter is a compile-time error rather than a runtime misbehavior. If prototypes aren't desirable, separate mutators still makes mismatches between design and code more visible.

To illustrate that last point, compare misused overloaded mutators with misused explicit ones.

$thing->foo(); $foo = $thing->foo($bar);

vs.

$thing->get_foo(); $foo = $thing->set_foo($bar);

The latter form of each example is legal code, and only the surrounding context will determine whether they are errors.

An obvious solution is to check the number of parameters given against the mutator's runtime context. The resulting code might look like this.

sub foo { my $self = shift; if (@_) { if (defined wantarray) { croak "can't expect a return value when setting foo"; } # store foo = shift; } else { unless (defined wantarray) { croak "must expect a return value when fetching foo"; } # return foo member here } }

That has its own drawbacks.

"set" mutators cannot be chained. While foo() might return $self in "set" mode, the wantarray() check would make it an error to actually use it.

"set" mutators cannot be allowed to return their members' new values. Even if they did, the wantarray() checks would prohibit code like print $thing->foo($new_value);

It's still a runtime error. Ideally every line of a program should be instrumented before it goes into production. Pragmatically speaking, compile time errors are better at preventing bogus code from being released.

Even if these problems are not an issue for a particular application, every mutator has gained an enormous amount of avoidable runtime overhead.

-- Rocco Caputo - troc@pobox.com - poe.perl.org