development

getters/setters

January 6, 2005 12:35:20.075

Blaine Buxton discusses whether or not to use getters/setters (as opposed to direct variable access). His post is based off this article, which opposes using them.

Blaine comes down as a pragmatist, stating that the most important thing is consistency - either use them or don't, but don't mix and match styles. I have a slightly different perspective, but it's colored by my experience developing BottomFeeder. One of the things I added early was the ability to have the app update itself on the fly. Smalltalk has always been capable of this, so I thought it would be a nice way of tooting that horn. Using direct variable access is problematic if you are going to update an app on the fly. Why?

Well, posit a method foo that directly accesses a variable bar - the older version (i.e, the one being replaced) was written before that variable had been added to the class in question. So I access the variable... and as soon as I try to send a message to it I'm likely to get an exception. When I add a new variable to a class, it gets initialized to nil, so I have one of two choices:

  • I can wrap all direct accesses with a nil check
  • I can simply add a getter method that does lazy initialization

The former is a more annoying version of the latter, and scatters the same initialization logic all over the class - which violates the once and only once principle. Now, this kind of thing never comes up in Java, because you can't add attributes to a class at runtime there - you would need to restart. For that reason, Java developers simply aren't going to come across this messy little use case for getters. That's why I tend to use getter methods - it makes runtime updating of code far, far simpler.

Comments

[isomer] January 6, 2005 13:10:22.000

Given the refactoring browser, I consider this a non-issue.

I start with no accessors (ie all instvars are private). If I get a DNU accessing a variable from another class, then I write the accessor and change all the direct references in one step.

Additionally, in my opinion accepting a policy like "always use accessors" paints with too wide a brush; It is tantamount to "mindlessly violate encapsulation at all times." In Smalltalk, instance variables are private for a reason. Violating that privacy should be a conscious decision.

[John M McIntosh] January 6, 2005 15:44:09.000

Ah, but if you later have a simple instance variable which then turns into a complex thing requiring some sort of calculation to resolve then having an accessor allows you to bury that code (much like the lazy initialization) in the accessor method. In practice I've found having accessors just allows for more flexibility.

Smalltalk and Java are like different

[Isaac Gouy] January 6, 2005 16:28:37.000

Smalltalk instVars are like Java protected fields - they only break encapsulation with respect to subclasses, they never break encapsulation like Java public fields. In Smalltalk practice, accessors are used to encapsulate access to instVars (from subclasses, and other methods). See Encapsulation and Inheritance in Object-Oriented Programming Languages.

In Java practice, inadequate reflection support pushed Java programmers into the JavaBean getter/setter conventions, which end-up being a guarantee that Object A has instance variables x,y,z. Java getter/setter methods are used to break encapsulation and allow access from unrelated classes.

getter/setter can be evil in Java, and accessors can be good in Smalltalk.

Re: getters/setters NOT!

[Terry] January 6, 2005 16:34:04.000

John

That argument works when you are developing and no one else has to read your code. Too many times I have run into situations where the developer used accessors everywhere and I found I had to read every accessor because I could not tell if a method was an accessor or it did something more. In this situation the code does not do an adequate job of conveying what it is attempting to do. IMHO if you intend to access state you should use a direct reference, that best conveys what you are attempting to do. If later on you find you need to do more, then you use the RB to refactor your references to use methods.

Jim's reason to use accessors, because it facilitates dynamic updates, is the only good reason I have seen so far to use accessors instead of direct references.

Having said that, I find that when I am writing a method early in development, when I am not sure what form things will take, I write my methods as if everything uses an accessor. Later on I go back and change the use of self accessors to use direct references.

Behavior vs State

[Isaac Gouy] January 6, 2005 17:01:39.000

Terry: "I found I had to read every accessor because I could not tell if a method was an accessor or it did something more."

Why did you care?

getters/setters

[ Rich Demers] January 6, 2005 17:15:57.000

Comment by Rich Demers

Here are several more reasons to use accessors:

  1. Because they are part of an object's API -- the methods by which other objects are expected to use to interact with it.
  2. When a complex object is being created, it is common practice to create it with a simple #new and then use a series of setters to initialize it.
  3. For test cases, setters are often needed to set the object under test to an initial state. The test is performed, and getters are then needed to determine if the changes to the object's state are correct. Unless these seters and getters are part of its API, though, they should be considered private.

Non-issue

[Travis Griggs] January 6, 2005 17:16:33.000

I agree with isomer completely. I'm not sure he made it completly clear why the RefactoringBrowser makes it such a non-issue. Instance variable menu options "abstract" and "protect" do all the work automatically for you. Got an instance variable that you suddenly want everyone to use accessors/getters for? Just hit 'abstract'. Tired of looking at self this and self that: for what is essentially something private? Just hit 'protect'. Want to "tune" the transformation in either direction so you can have it 90% one way or the other? Just enable "show changes" and adjust the proposed changes when doing the transformation. One menu click and you can have it 100% one way or the other, at any point. This is a non-issue. Of course.... if you're stuck using VA or even Squeak, then maybe it still matters, a little. :)

getters/setters

[ James Robertson] January 6, 2005 17:40:54.000

Comment by James Robertson

Travis,
The point I was making is that you have to consider the implementation language when making this call - it's not independent of that...

getters/setters

[ Dennis Smith] January 6, 2005 17:51:05.000

Comment by Dennis Smith

I have another reason to use accessors -- some of the time. When using VW connected to Gemstone, its much faster to flush/fault objects which have "nil" in the instvars. So rather than store the "normal/default" value, we leave it as "nil", and the read-accessor does readIt readIt isNil ifTrue: ^123. ^readIt

However, I would beware of doing MORE than that in the accessor or yes, you do run into cases where you THINK its just an accessor, but it really does 100's of other things.

So I use direct access where I don't care, but read-accessors where I need to use default values without actually storing the value. It really becomes class-dependent, so I either use them or don't use them based on class and how its used relative to Gemstone.

My $0.02

[Tom K] January 6, 2005 18:37:30.000

I've got a few thoughts on the direct vs. accessors question.

First, it's nice to say that one should use direct access until forced not to by circumstances, but this sort of non-policy just doesn't cut it in a larger team where one is trying to foster consistent practices. When one is dealing with neophyte or mediocre programmers, it's much safer to limit the decisions they have to make. Believe me, it's tough enough just to get them to use code formatting tools!

The only cogent argument I've ever heard to not use accessors is for purposes of encapsulation. Much weaker arguments include performance (not a problem with a reasonable VM), and readability. Personally, I think direct access _impedes_ readability - I have to look at the temporary variables defined in a method in order to verify where a variable is being defined.

On the other hand, by using accessors, one gains some advantages. It becomes trivial to see where a variable is actually being altered just by an appropriate use of sendersOf. Direct access actually requires one to examine the context to determine where things are being changed. By using accessors, one can easily specialize behaviour in subclasses.

Finally, there are still some of us who spend our days using VisualAge Smalltalk. In that environment, one has to use accessors in order to make a lot of the environmental behaviour work correctly. Consistent use of accessors is going to save hours of tracking down why some UI is not behaving as expected!

Behavior vs State

[Terry] January 6, 2005 19:45:53.000

Issac

It is a maintenence issue. If you are debugging someone elses code and the original developer is not available you cannot assume that the methods do what they say they do. I have been bitten a few times by that. As a matter of convention the method name for an accessor should be clear that it is only an accessor and it does not do anything else, otherwise when you are fixing or modifying code you will also have to read all the accessors. That is why I also disagree with those who like to use accessors because its behavior can be changed in a subclass, i.e. the method name no longer reflects what it does. I realize that it may be easier to do it this way but the time saved can easily be spent later when someone else trys to fix unfamiliar code and believes that the method does what the name indicates.

Of course it is also bad for encapsulation. I have seen novice smalltalkers write something like "anObject attributeX attributeW attributeT doSomething". It becomes too easy to continue to write procedural code and treat objects like records.

With respect to finding out how an instance variable is being used I find that the "instance variable reference" commands to be very effective. I think it is also easier to find out when a variable is no longer be used if there are no accessors to begin with. If there are accessors it becomes more difficult to determine if a client object is using it or if it sending a message to a different class.

It's always the people

[Isaac Gouy] January 6, 2005 20:34:30.000

Terry,

"I could not tell if a method was an accessor or it did something more"
Something like ReadStream>>next ?

"you cannot assume that the methods do what they say they do"
On that basis why would you assume that the instVars hold what they say they do?

 Share Tweet This
-->