The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Getters and Setters (reprise)

Now, I'm coming at this from a couple of languages where everything is a free for all and you can get/set anything you want.

Why is it a best practice that the most obvious use of a private variable is proscribed?

pos.x = 4;  // this is a no-no

pos.setX(4);  // this is proper?

Why not simply wave your hands and say, "only use the variable directly if you are sure that is what you want."

This argument seems so very typical of Java.  Make the normal use more difficult to support the rare use.

I think the problem lies with the people that think a function named setX() should do anything other than set the variable x to the value passed.  If you really need another value, you should be naming your functions accordingly:  moveX(int x)  // you get the idea.

Maybe it's just that I work with programmers who can be trusted.
Lance Hampton Send private email
Monday, April 14, 2008
 
 
Using getters and setters instead of direct access gives you the freedom to later change the implementation without having to change all usages. Perhaps you want to cache a value. Perhaps you want to use lazy initialisation. Perhaps you want to use a derived value, or log the field accesses.

One of the strongest reasons for using a setter is you can add validation. Ensure x is not null, or not negative, or not an empty string, and so on.
Steve McLeod Send private email
Tuesday, April 15, 2008
 
 
"Why is it a best practice that the most obvious use of a private variable is proscribed?"

It is _not_ a best practice. It's someone's opinion in a recent thread. It's true that for input validation and other additional logic a function will be useful, but it's also true that if the variable is private and you have no additional logic then any decent refactoring tool will let you add this function later if you need it.

Don't sweat the small stuff.
Daniel_DL Send private email
Tuesday, April 15, 2008
 
 
Actually setting members probably isn't useful.

A better design philosophy is to ask the object to set its state, by sending a suitable message. Preferably which includes a verb. The result is that the caller's code notates what is intended, not what actually happens.

Instead of;

  myFont.setStyle(ITALIC|BOLD)
  myFont.size = 10;

or

  myFont.setSize(10);

you should be asking things like;

  myFont.selectMediumSizeUpright();

or

  myFont.select(
      FontDescription("TimesRoman",10,ITALIC|BOLD)  );

If your object doesn't have suitable verbs, it's probably really just a bag-o-data rather than a proper object. It's perfectly reasonable to have them in a system, but in general they can just have public members anyway.

{Examples would be objects which represent, say, rectangles with an X,Y and a W,H. Or coordinates which have an XYZ}

In general, few true domain objects have a state which can be entirely expressed by single intrinsic types and therefore updated by changing the value of that type. Allowing access to the internal members -- either with getters/setters or with publishing them -- allows the possibility of an object being set to an inconsistent state.

The latter example above can return a status to say whether the font exists or if an approximation will be used.

If you do this by using multiple requests, you can allow the state to be inconsistent; presumably what happens is that when you try and render some text with it it returns an error complaining that the font doesn't exist.

{Or, more likely given the way IT works, it will transparently fail in some way; your user is now looking at a blank area or a line of square blocks or something.}

If you allow the state to be inconsistent at any point in time, there is the risk that it will fail to be moved to a consistent state by the user. Objects should move from consistent state to consistent state as atomically as possible to reduce the risk to their end users.
Katie Lucas
Tuesday, April 15, 2008
 
 
I don't know what we're discussing anymore. Does the OP imply that

"pos.x = 4;"

should compile even if x is a private member of pos's Class and you're calling it from outside? This would be totally insane.
Daniel_DL Send private email
Tuesday, April 15, 2008
 
 
Yeah, but I think the argument was something like 'why not have public fields as well as accessors?' and then you can choose to set the value directly if you think you know what you're doing.

That reflects a fundamental lack of understanding of encapsulation, if you ask me, but then not all people agree that OO is even a good thing, so it's not heresy or anything :-)

Basically, the argument here is that using language features to hide or prevent access to things is equivalent to not trusting the programmer. I doubt most OO people would see it that way.

Personally, I think Java would just do as well to adopt properties from .NET. You get value assignment semantics with the benefits of encapsulation via an accessor. Sorted.
Neil Hewitt Send private email
Tuesday, April 15, 2008
 
 
I like the way Delphi does it with properties.

you can bind the property x to the private field fx... then change it to read from fx, and write with setX... and later change it to use getX and setX...

you will use class1.x in all cases, so no change in code...
Totally Agreeing
Tuesday, April 15, 2008
 
 
"Why not simply wave your hands and say, "only use the variable directly if you are sure that is what you want.""

Because that violates a couple design philosophies inherent to the language (or to OOP in general).  There's nothing holy about this; it is simply the philosophy against which the language was created.

The tenets are as a class, I should be able to control all access to my internal structure.  My structure should be hidden, I should only be exposing an interface by which others can request I do something.

However, at least in Java, classes often end up being the equivalent of C 'struct' objects: a collection of data fields with little or no logic.  This forms the crux of these discussions, because in such objects, having to generate boilerplate getXXX() setXXX() methods can be thought of as code bloat.

It also touches the whole JavaBeans-are-misused discussion.  The JavaBeans spec defines properties as values that are accessed via a specific method naming convention ( getMyProp()  setMyProp() => defines a property 'myProp' on my class).  These properties do not have to actually be stored internally to the class, they may be entirely calculated at runtime.


Myself, I'd like to see differentiation between the actual data values exposed by an object vs how the object opts to  manage the storage of them.

A hybrid of the JavaBean and internal members if you will. 

A great example is mentioned in an earlier post; define something as an externalized property, the compiler can generate getters/setters backed by an internal data member.  If you wish to control how the externalized property is stored or where the value comes from, or to validate, have syntax that lets the class implementor override the get/set operations with custom logic.

This lets you define the properties of your object as part of its interface, but lets your object, say, have a property that is stored a database instead of tracked internally, but you can still use it in code by:

myObj.dbBackedProperty = "foo";

This isn't "directly accessing the class members", so it doesn't violate encapsulation.

This is one aspect of the .NET languages that I like, compared to Java.  So tired of piles of boilerplate get/set methods in my code.
Dan Fleet Send private email
Tuesday, April 15, 2008
 
 
Or you can do it like Bioperl (described in "Beautiful Code"), where you can set anything to a *function*, which is evaluated (called back) inside the object using the objects contents when needed:
Set_font(lamdba size: Times if size< 12; else: Arial)

But people who object to setting attributes might see that as a little ... undisciplined.
PeterR
Tuesday, April 15, 2008
 
 
"Because that violates a couple design philosophies inherent to the language"

Makes you wonder why all of these languages support public fields, doesn't it? If it was so clearly and obviously wrong then perhaps no "real" OO language would support it?
Arethuza
Tuesday, April 15, 2008
 
 
The OP was talking about a _private_ variable.
Daniel_DL Send private email
Tuesday, April 15, 2008
 
 
I should have used this.x instead of pos.x

Although, I'm personally not against pos.x either.  You have private, public, etc... use them.
Lance Hampton Send private email
Tuesday, April 15, 2008
 
 
Why are we still discussing this nonsense?
uggh
Tuesday, April 15, 2008
 
 
"Makes you wonder why all of these languages support public fields, doesn't it? If it was so clearly and obviously wrong then perhaps no "real" OO language would support it?"

What about:

public class Math {
  public static final double PI = 3.14...
}
John Topley Send private email
Tuesday, April 15, 2008
 
 
You're right. Why the hell are we communicating?!
:-)

I read somewhere (and subsequently thought it sounded like good advice) that as a tradeoff of encapsulation vs. bloat/boilerplateishness it can be a good idea to make variable which are only used as a value public, and anything which can change the state should be encapsulated in a method call.

However, it does depend on those fields, and whether they can be in an "invalid" state as earlier mentioned. If you have a number which shouldn't be less than zero, then you want a mechanism to stop it being set to less than zero.

And it isn't a "black and white Java says you must do this" kinda thing. Most people will meet a public field in their very first program in the System.out call to print "Hello world".


Mind you, any other language/methodology is totally eclipsed by my involvement with Java, so by definition I can't really have much of an insight.
Graham Allan
Tuesday, April 15, 2008
 
 
The issue is whether it's worth the pain of having to declare a getter/setter for every stinkin' private class variable on the off chance that one will change.

Personally, my answer would be that if your class is so big that you'll potentially save a lot of rework by doing this, then your class is too darn big.

Even if you find that you can't remember all the places where a variable is set, it's not so hard to rename the variable, build, and then look at all the now-broken places.  And if you can't remember *when* those places get called, then maybe it's worth putting in a private getter/setter for that one variable so you can put breakpoints on it.

These cases are so rare, though, that it's not worth all the extra work to put getters and setters around *everything*.

So says I.
Kyralessa Send private email
Tuesday, April 15, 2008
 
 
To me getters and setters are most of the time a code smell. The argument goes that they allow you to change the underlying implementation but in my experience this rarely happens and you're usually left with a bunch of get()/set() methods that completely break encapsulation. And if you really need to change the underlying implementation and need to maintain a state or invariant, then there is a good chance that your interface is badly designed and your functions should be renamed. E.g. Resize() is better than SetSize(); Lock()/Unlock() is better than SetLocked(); etc. If you need validation, use user-defined data types.

This related article appeared on reddit a while back.
http://www.kirit.com/C%2B%2B%20killed%20the%20get%20%26%20set%20accessors
triple-dot
Wednesday, April 16, 2008
 
 
"Makes you wonder why all of these languages support public fields, doesn't it? If it was so clearly and obviously wrong then perhaps no "real" OO language would support it?"

Smalltalk, probably the archetypical "real" OO language, doesn't have public fields.
Chris Tavares Send private email
Friday, April 18, 2008
 
 
Getters and setters undermine one of the basic principles of object oriented programming: a responsibility should be assigned to an object in the system that has the information to do it. (Information expert in the GRASP http://en.wikipedia.org/wiki/GRASP_(Object_Oriented_Design))

This is why you put an 'isValid()' method in the PostalCode object and not somewhere else, because only the PostalCode knows what string to validate. If you generate getters and setters for this, suddenly every object in your entire system, ranging from your web layer to the dao layer, will have the knowledge to validate the postal code. You shouldn't do a postalCode.getCode().matches("whatever regexp you need"), but nobody is stopping you.

Using setters for validation is not a good reason either. If you have a startdate and enddate property in your object and everywhere in your system you use

object.setStartDate(...);
object.setEndDate(...);

you are in big trouble if validation needs to be added:

End date must be after the start date. You can only implement this if you are calling setStartDate before setEndDate. Can you guarentee that this is done in a big system built by several different developers?

Even if you've managed to do the above (and it is possible if you have enough time), the next requirement is impossible to do without a big rebuild of your system:

End date should be max. 7 days after start date.

Let's say you have an object that has a startdate of Jan. 1st and an enddate of Jan 6nd. The user wants to edit this object and moves the startdate to Feb 1st and the enddate to Feb 6nd. Setting the startdate first will result in failure (startdate is after enddate), setting the enddate before startdate will result in failure too (enddate is more than 7 days after startdate). The only place left to do this validation will be in your client tier with some hacked javascript...

If you really want to create dumb datacontainers and place the functionality in other parts of the system, try programming in C, it was made to do this. Don't do this in an OO environment.
Jeroen Weelink Send private email
Wednesday, April 23, 2008
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz