in reply to Class attribute get/set approach flaws?

My take on this is that in general, as a rule of thumb, methods that don't do anything but get or set a variable are a sign of bad design. It would be different if there were some concrete reason for having methods get and set the variables. For instance, the setter methods of some classes might do validation, and that would provide a worthwhile excuse for their existance; if you think you might add validation in the future, you might go ahead and do the interface this way to ease that transition. Another example is Class::DBI, whose methods do rather more than merely get or set a plain old variable (and which, incidentally, implements both the Class::Value() and Class::get(value) interfaces; both are useful, the former for reasons pointed out by others in this thread, and the latter because sometimes it's terribly convenient to run a foreach loop through several values). Nevertheless, these are special cases, cases where the methods either currently do or someday might do something more than just get or set the value.

Object-oriented design is a very useful approach, especially for certain types of problems, but (unless you're taking a class in it and need to make certain grades) don't get too caught up in textbook notions of "clean" OO design, wherein the professor will mark you down if any of your object's variables are public. If the methods are never going to do anything but get or set the object's values, they're probably superfluous and add needless complexity, which is usually a bad thing; in that case, it's probably better to let the calling code get or set the variables via normal assignment. This is especially true in Perl, because normal assignment has some flexibility that you might not think about and might not think to implement in your methods, e.g., it reacts appropriately to contexts, can work with array or hash slicing, and so on. It may also perform better than methods.

  • Comment on Re: Class attribute get/set approach flaws?

Replies are listed 'Best First'.
Re^2: Class attribute get/set approach flaws?
by sauoq (Abbot) on Nov 29, 2005 at 01:58 UTC
    If the methods are never going to do anything but get or set the object's values, they're probably superfluous and add needless complexity, which is usually a bad thing; in that case, it's probably better to let the calling code get or set the variables via normal assignment.

    This is not likely to be a popular stance around here.

    I don't entirely disagree... This is useful for some very simple classes which are just glorified hashes anyway and, preferably, are used only in one application.

    But, you should recognize that there is a huge problem with this approach. It locks you into an implementation. Say you want to change your hash-based objects into "inside-out objects" down the road, for instance. You've got to change all the code that uses your class. If your class has gotten any real use, that's probably not going to be an easy task.

    So, unless you're pretty damn sure you're never going to change the implementation of your class, you don't want to do this.

    And, really, who's ever that sure?

    -sauoq
    "My two cents aren't worth a dime.";
    
      This is not likely to be a popular stance

      Popular opinion isn't everything it's cracked up to be. Popular opinion around here also favours CGI.pm, but I have very solid reasons for disliking it.

      Say you want to change your hash-based objects into "inside-out objects" down the road, for instance

      If I were going to make a change that substantial, I'd probably write a new class entirely and just declare the old one deprecated in favor of the new one. I'm all for code re-use up to a point, but trying to make a fundamental structural change like that to any non-trivial module is going to mean a trainload of headaches and subtler bugs than I really want to deal with if I can help it. Besides, while I do appreciate the usefulness of lexical closures (and, in fact, my one lone module on the CPAN accepts code references as a callback mechanism), using them for encapsulation in object-oriented code is a technique I reserve for the Obfuscated Code section (e.g., see this or this).

      However, I also neglected to finish explaining my original thought, i.e., that accessor methods can be a sign of poor design. This is not universally the case, but often it is better to accept named arguments when instantiating the object in the first place. Obviously you will sometimes have a value that needs to be changed later on by outside code for one reason or another, but if all of your variables have such accessors, the object basically *is*, semantically, a glorified hash. I am *particularly* leary of the "let's use AUTOLOAD to automatically generate get/set accessors for all of our variables" approach. If you are even tempted to do that, it's time to re-evaluate the entire design of the class, IMO.