Skip to content
December 5, 2008 / Abe Pralle

Access methods potentially harmful

As one of the last born into the “C generation”, I learned programming in the twilight of the procedural years. Like many others, I initially fit the newly-emerging object-oriented concepts into my C worldview, thinking of objects as “structures with access methods”: if you have a Clock object with {hours,minutes} values, then you write a pair of access methods for each value: getHours(), setHours(), getMinutes(), and setMinutes(), allowing for access control and implementation independence. Sounds good, right?

The problem is that this is still procedural programming thinking. When you write those access methods, you’re locking yourself into a thought process where an outside force is going to manipulate the hours and minutes of this clock piecemeal. Not good! If this is an object-oriented clock, then the clock itself should be responsible for maintaining itself.

In short, having good ol’ get/set access methods interferes with abstraction. We want to be able to think of a clock in terms of what it can do for us as an atomic object and not be burdened with the details of how it works.

Old-school OO literature suggests starting a class definition with some instance variables and then of course some get/set (accessor/mutator) methods for each variable.  And yes, for several years I taught OOP in this way.  Then I read Nino & Hosch’s “An Introduction to Programming and Object-Oriented Design” and that totally changed my thinking.  I’ve since adopted Barnes & Kolling’s “Objects First with Java”, but the first book introduced a particularly useful way of designing classes that I still use today.

Nino & Hosch’s strategy is to figure out what query methods and what command methods you want your class to have.  At first that sounds just like get/set, but the difference is that query methods return information about an object without changing its state and command methods may or may not return a value but they do cause an object to change state.  It’s not about whether you’re setting or retrieving a value, it’s about whether you’re affecting state or observing it.

On top of that system I’ve adopted the notion of properties from Alice, an introductory teaching language.  It calls its instance variables “properties”, and to me that name change is really important.  “Instance variables” seem like the variables that an object contains, while “properties” sound more like variables that comprise an object and its state.  In other words, “instance variables” encourages thinking of objects as collections of variables where “properties” encourages thinking of objects as abstract units.

So my class design in my intro-level Java courses now goes like this:

Let’s make a clock. What are its properties? What are its command methods – what can we tell it to do?  What are its query methods – what questions can it answer for us?

I’d then write this on the board:

Clock

PROPERTIES
– hours, minutes

COMMAND METHODS
– setTime, tick

QUERY METHODS
– toString

We can set the time on a clock, advance it with tick(), and get the current time with toString().  Oh my gosh we can’t set the individual hours and minutes or retrieve the separate hours and minutes – but wait a minute, we don’t need to!

For some reason it used to be hard for me to come up with OO examples for class, but now it’s really easy.  I just take any kind of simple mechanical device and make a software model of it.  Clock, flashlight, raffle machine, calculator, stapler, pack of gum, soda machine, stoplight, oven, iPod, etc., etc.  Things you could observe about an object become query methods, actions an object could perform become command methods, and it’s all kept track of internally by the object’s properties.

Real software isn’t modeled as a collection of simple physical objects, of course, but the design mentality transfers just fine and it’s that mentality that’s important.

Advertisements

6 Comments

Leave a Comment
  1. Jacob Stevens / Dec 6 2008 9:34 am

    Great post. Your point reminds me of the user interface design thought process I was introduced to at IBM. To paraphrase:

    The developers of our software have put a lot of time into the functional API of their software. We hire good programmers so their code is clean, elegant, and easy to maintain. Therefore, the programmers are going to assume that the best user interface is one that directly exposes the software’s API through a graphical interface.

    This is generally not the best philosophy for usability. The API was designed to be programmer-friendly, not user-friendly.

    Your job is to figure out what users *actually want to do* with the software. What actions do they want to take, and what sort of information do they need to see? Once you have determined this, you can work backwords and map these tasks to the actual API.

    Once you’ve mapped what users *want* to do with what the software *can* do, the job of laying out the interface (which is what most people think our job is) is relatively trivial.

  2. abepralle / Dec 6 2008 1:31 pm

    Definitely! BTW I love that last sentence.

  3. Mathew Eis / Jan 13 2009 8:43 pm

    Hey there, I’m one of your students from this semester’s CS200 class.

    I’m quite literally on the tailing edge of the “C” generation, having learned C about 9 years ago as my first programming language, so I fully understand where you’re coming from.

    I have never understood the point of having a ‘get’ and ‘set’ method for a class instance variable – if the class design is good, and get/set are needed, then why shouldn’t it simply be a public variable? Having get/set does very little for abstraction and portability, while (albeit only slightly) reducing efficiency.

    What you’ve written here finally brings light to this problem; that get/set shouldn’t be taking place in a well design class; instead focusing should be on what you are calling ‘properties’ and ‘command methods’

    I’m looking forward to the rest of the semester – especially after reading this post!

  4. Abe Pralle / Jan 14 2009 1:18 am

    Well thanks! I have to say though that actually there is a good reason to have pairs of get/set access methods in some cases: to allow properties to be private which prevents you from accessing them directly which in turn gives you implementation independence – which is good because it allows you to stop thinking about what an object is *made of* and instead just think about what it can do.

    Example: let’s say you make a Temperature class that stores the temperature in Fahrenheit and also allows interaction in units of Celsius and Kelvin. Say you also write 5,000 lines of code that make use of the temperature class. Now let’s say you decided you needed to change Temperature so that it actually stores in Celsius instead of Fahrenheit. If the variable was public then you probably used it a lot in your 5K lines, but if it was private, with a pair of get/set methods, then you only have to adjust conversion formulas on a couple of lines and you’re good to go.

    Or maybe instead of storing in C instead of F you decide to store data in a network database instead of in a local file. Same thing: if you’ve been accessing all the I/O control variables directly then your original implementation may be significantly entangled with your other code.

    So what I’m primarily against is the mentality that access methods should automatically be made for whatever instance variables you happen to have. I’m still all for keeping properties private (officially, at least), I just think the interacting methods should support the purpose of the object as a whole instead of being determined piecemeal by the individual properties.

    Do I really use private variables all the time in my personal Java programming? No, hardly ever, ’cause it’s a huge pain in the ass. BUT I do adhere to the “atomic, abstract objects” philosophy and try to ensure that any variables I directly access are in little danger of changing later on. Private members are good for beginners and intermediate-level programmers though – they’re like training wheels that you can take off later once you’ve got the hang of it!

  5. Timothy Goya / Jan 14 2009 10:00 am

    I’ve gotten into the habit of writing C# and Python style properties in C++ because I’m always annoyed when I have to use functions when “direct” variable access seems much more natural. I’m not worried about the “if I change from F to C” type cases cause it won’t break API and would break ABI regardless. It’s a huge pain to write the helper wrapper classes repeatedly, though. I haven’t figured out a way to write generic portable C++ properties.

  6. murphymc / Feb 6 2009 1:51 am

    Really, the only time I ever heard the whole every-instance-variable-has-a-getter-and-setter methodology espoused was by people who never really “got” it. Every *good* imperative/OO book talked about it exactly like you do above. (The fact that as many people — or more — didn’t get it as did is another issue.)

    I’ll also point out that Visual Basic had this all worked out years ago. At least since VB4 (1995, IIRC), public data members were called properties, and underneath… these were automatically implemented by what were essentially transparent accessors/mutators. You could also use explicit properties (transparent accessors/mutators). For that matter, you could take what had been a “public variable” and change it to using an explicit accessor/mutator pair without breaking the ABI. All this was done with a minimum of syntax. Some other languages can do this last trick (or the equivalent, e.g. Python), but keep in mind that VB was compiled and had binary components.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: