OOP and the Get/Set issue

Posted: Fri, 2 December 2005 | permalink | No comments

Steinar, your comments on the limited utility of Get/Set methods both struck a chord and touched a nerve with me.

On the one hand, I completely agree that people need to spend more time writing methods that do something useful to an object rather than just exposing public methods. For example, how often have you seen something like this (in faintly python-inspired syntax):

 obj.count += 1
 [...]
 obj.count -= 1
 [...]
 if obj.count == 0:
 	obj.destroy

Instead of the far more descriptive (and well-encapsulated):

 obj.register_user()
 [...]
 obj.unregister_user()
 [...]
 obj.destroy_if_unused()

(or any one of a thousand other similar idioms). This is a contrived example, of course, and a real example would involve doing at least a dozen operations on an object's public attributes from another class (which results in class-associated logic being located in other classes in the system) instead of putting it in a method and calling that (thus keeping all of the logic with the data it's manipulating -- which is the point of OOP).

Anyone who writes code like the first example above and calls it OOP is kidding themselves. Of course, you could make the code even more ridiculous with getter/setters:

 obj.setCount(obj.getCount()+1)
 [...]
 obj.setCount(obj.getCount()-1)
 [...]
 if obj.GetCount() == 0:
 	obj.destroy

Incidentally, if you ever see anyone turn the first example into the last example and say they're "improving encapsulation", please do the programming world a favour and kill them. kthx.

On the other hand, Steinar, you say "I'm not denying that getters and setters for a few variables might make sense", which clouds the issue immensely. The idea of routing attribute access through a method is immensely useful. It even has it's own name -- the Uniform Access Principle. A few examples are in order (you might already have thought of these, Steinar, but who knows who reads my dribblings!):

In my real-life case, there were few enough places to change all of the calls to a method, and since it's all written in Python I could have played __getattr__ games to get back to a method if I'd had to, but it would have been messy.

But imagine a system written in a language that doesn't (somehow) support the Uniform Access Principle, and which was widely deployed (possibly even used by programs outside of our direct control) so the users of the class couldn't be adapted easily. Nightmare.

Now, the real solution to the problem is to only use languages which support the UAP (Python can be hacked to do it; Ruby is, IMHO, almost a case-study in How To Do It; and there are other good languages out there). But, in ass-backwards languages that can't transparently map attribute accesses to method calls, I'd rather deal with getX()/setX() everywhere than have to try and perform the necessary gymnastics to later support dynamic value generation from what-was-previously-an-attribute.

If, on the other hand, your post was primarily targeted at said ass-backwards languages, or programmers who cargo-cult manual getter/setters everywhere, let me join you in your derision. <grin>


Post a comment

All comments are held for moderation; markdown formatting accepted.

This is a honeypot form. Do not use this form unless you want to get your IP address blacklisted. Use the second form below for comments.
Name: (required)
E-mail: (required, not published)
Website: (optional)
Name: (required)
E-mail: (required, not published)
Website: (optional)