I haven't fully gone through the other thread, but I think this issue -- at least for Perl -- really needs to be be distinguished between accessors and mutators used within the class package and those used outside the class package.
Within the class package, accessors and mutators are heavily used for typo avoidance -- or rather, compile-time run-time typo checking. That's a straightforward tradeoff of safety for speed and fair enough. (And yes, inside-out objects address some of that, with yet other tradeoffs.)
Outside the class package, the issue of whether accessors and mutators violate encapsulation, etc., is what becomes the religious war. The "problem" for Perl is that most accessors and mutators -- even for internal use -- are declared as public functions for various reasons
I generally feel that your comments about interfaces make sense. But whether you call them accessors or call them interfaces, the issue is the same. By tradition, Perl programmers frequently implement accessors and mutators as part of the published interface regardless of whether it really makes sense to do so from a "good design" standpoint. This is what leads to the sniping about "glorified structs" and so on. To some extent, I agree -- a programmer's convenience to avoid typos shouldn't be the driver of a public interface.
Personally, I think that the distinction between an accessor and an interface is usually pretty minimal. This isn't to say that all internal properties should be exposed, but querying an object's state as expressed by its properties is frequently a necessary part of an interface. If the internal representation changes, the accessor becomes an interface that preserves compatibility.
The stylistic/religious argument question as I see it is more about the mutability of properties once an object has been created -- whether the properties should ever be changed directly independent from the behavior of the object. To use the circle example, does a circle "change radius" or "change size"? One is a statement about a property and one is a behavior. (For this trivial example, they are mathematically equivalent, but not all cases are so trivial -- this is the peril of simplistic analogies.) On balance, I think that defining this interface in terms of the behavior makes for better design. E.g. this function defines a behavior and it can be parameterized in several ways regardless of the internal representation.
$circle->resize( radius => 2 ); $circle->resize( area => 12.56 );
However, no rule should be absolute, and I'm sure there are cases where breaking encapsulation and directly manipulating properties makes for a better/faster/whatever implementation. That said, the principle that I think makes the most sense for mutators is a paraphrase of Bill Clinton's statement on abortion (and apologies for bringing up politics should that offend or distract anyone): Mutators should be safe, legal and rare. (At least as part of the public interface.)
As a related point, this is one reason why I've decided I'm not really in favor of the combined getter/setter style of accessors that are frequently seen in Perl. In addition to the ambiguities in usage that others (e.g. PBP) have noted, I think they make a poor default assumption that the interface for querying state should be the same one as for modifying state. Instead, for the circle, I'd rather see something like this:
# Querying state -- which is the accessor and which are the interfaces +? $circle->radius(); $circle->diameter(); $circle->area(); # Modifying state -- interface potentially defines multiple acceptable + forms $circle->resize( radius => 3 ); $circle->resize( match_area => $another_circle );
This keeps the user interface at the center of the design rather than having it be just a consequence of accessor generators.
Update: Yes, it should have been run-time, not compile-time, on the typo checking. Thank you, Perl Mouse.
-xdg
Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.
In reply to Re: Perl OO and accessors
by xdg
in thread Perl OO and accessors
by dragonchild
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |