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.

OO - getters and setters

Hello, a friend referenced me to an article saying that getters and setters are not very good  things to have in an OO program.

http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

What do you think about this?

If you agree, how do you solve it in a language like Java or C#? Do you go with "public Object getThisInfo"? Or do you design not to need getters and setters, as the artile writer recommends?

Comment at will.
COD3R
Wednesday, April 25, 2007
 
 
If you have get/set for each variable you haven't really gained from OO - the caller has to know too much about the internal working of the class and it is difficult to change the class implementation without breaking code.

Having said that - there is a case with simple classes which are just structs with access control. Allowing you to change one variable and have the setter automatically handles change any linked variables.
Martin Send private email
Wednesday, April 25, 2007
 
 
I think it's a crime, OO-wise, to use the fields directly, without the interfacing of methods.

On the other hand, I can understand it somewhat, as in Ruby it's easy to use the fields from the methods that are generated automatically by Ruby itself, but we do use a lot of Hash and Arrays for data as well, while in Java and C#, sometimes one might use such structures a little less frequently, preferring to use "naked objects" (with public fields)?

At least in my Ruby and JavaScript programming, I use a lot of Arrays, Hashes, and fields behind get/set methods as much as possible. (Did you know JavaScript can be slightly OO as well? :-)

For example, in Ruby, this:

class DressedOne
  attr_accessor :shoes_color
end

Is equivalent to:

class DressedTwo
  def shoes_color
    @shoes_color
  end
  def shoes_color= v
    @shoes_color = v
  end
end

And then, the field's data can be set and read as if it was a public field in Java or C#:

one = DressedOne.new
one.shoes_color = 'white'
print one.shoes_color

two = DressedTwo.new
two.shoes_color = 'silverlight'
print one.shoes_color

In JavaScript, though, I would do it like this:

var one = new DressedOne();
one.set_shoes_color('white');
alert(one.shoes_color());

(Notice, I avoid the word "get").

Both, in Ruby and JavaScript it's easy to create Arrays and Hashes to pass data/methods around, though, which in my opinion helps to keep the existing classes as meaningful as possible, while providing plenty of alternatives to Java's and C#'s "temporary" classes.

C# has a neat use of fields, though, similar to Ruby's in some ways. It just needs an equivalent to "attr_accessor" and "attr_reader" (the most used). :-) Maybe Java has envy of it, though.
Joao Pedrosa
Wednesday, April 25, 2007
 
 
This looks like a "religious" discussion, triggered by that "is evil" part of the articles title.

The idea of OO is to encapsulate data-and-behavior.  If you have a lot of 'getter' and 'setter' routines, it looks like you're simply using an object as a data holder.  You might as well access the properties directly -- but at least a getter/setter provides SOME level of access control for the Class in question.

"Moreover, the presence of numerous getter and setter methods is a red flag that the program isn't necessarily well designed from an OO perspective."

"This article explains why you shouldn't use getters and setters (and when you CAN use them)..."

So, he says NUMEROUS getters and setters IS A RED FLAG, not that they're inherently evil.

And the second quote says you CAN use them, so they're not to be avoided at all costs -- your friend was wrong.

While the title of the piece sucks (part of an "... is evil" series, apparently) the body of the article is MUCH more realistic.

As Stroustrup has said, not everything NEEDS to be an object, sometimes a Structure with data elements is all you need.

Bottom line -- do what works, realize you're making trade-offs and be able to say why you made the choice you made.  "Thou Shalt Nots" don't really belong in software engineering.  Except for GOTO, but even that can be helpful in error handling.
AllanL5
Wednesday, April 25, 2007
 
 
In my experience the setters are rather more important than the getters. Getters retrieve information about the state of the object, which might have some use, and don't change the object.

Setters have more tendency to be evil. In the worst case, a badly designed setter interface could make it easy to put your object into an inconsistent state, or make it easy to leave necessary parameters out. Ideally any method that alters a class should step it between self-consistent and meaningful internal states in a single operation.

The OO purists would suggest that you use a class to encapsulate behaviours as well as data. This is all fine when the behaviour is readily capturable - and certainly encapsulating behaviour in a class is far better than scattering it all over the application, or putting it in some enormous 'do-everything' class. However, sometimes the behaviour associated with a set of data is sitting in front of the keyboard, or is in somebody else's application. In these circumstances, you may not be able to do any better than a sensible set of setters.
Duncan Sharpe
Wednesday, April 25, 2007
 
 
What the article is trying to say is it's not the "getters and setters" themselves that are bad, but the design of an object so that a lot of it's internal data is publicly accessible, regardless of whether you get to it through a getter/setter or a public variable.  I think the line from the article that sums it up best is:

“Don't ask for the information you need to do the work; ask the object that has the information to do the work for you”

This is just good OO design. The less connections an object has to the outside work, the easier it is to maintain.

Dan
Dan Boris Send private email
Wednesday, April 25, 2007
 
 
However, even a complete set of getters and setters is better than nothing - it still gives you the flexibility to change and extend the internal representation without changing the interface. This can help you if at some later stage you have to make consistency checks and changes when a setter is run. With all public data, you're forced to change the interface and break the dependencies. Or you may even be forced to live with the public data and an inadequate data representation.
Duncan Sharpe
Wednesday, April 25, 2007
 
 
In my web application I have a separate class for each database table, but I never use getters and setters for any table fields. Instead I pass arrays of values between each of the different application layers. This makes sense to me as the data from the user is presented to the application in the form of a POST array, and where each value is a string. My presentation layer passes the array in to the business layer, the business layer can iterate through the array to do whatever validation or processing is necessary, then it passes the array to the data access layer where it is transformed into a string containing a valid SQL query.

When data is retrieved from the database it is done in small pages, so each page is read in and passed to the business layer in the form of an array. Again the business layer can manipulate this array to do whatever is necessary, then it passes the array to the presentation layer which converts it into an XML document for transformation into HTML via an XSL stylesheet.

The upshot of this method is that I can change the structure of any database table without having to modify any getters and setters anywhere as the only place where table columns are named is within each business layer object. Because data is passed between the presentation and business layers in arrays which can contain any number of fields, I do not have to hard code any field names in my presetation layer. This means that I can actually use a lot of generic and therefore reusable code in my presentation layer as the presentation layer does not contain any hard-coded field names.

Getters and Setters? I don't need no stinking getters and setters!
Tony Marston Send private email
Thursday, April 26, 2007
 
 
So after some more readings I found something called Demeter's law which I didnt know about. The example suggested that multiple "dots" should be avoided.

So for example if we have this two classes that are just about data:

Class T (string c, ClassQ q)
Class Q (string k, string k0)

Now if we are using this in another class that glues properties of those.

Class W {

  String R;
  String O;

    W (T_List) {

        foreach (T t in T_List) {
              R = R + t.getC ();
              O = O + t.getQ.getK();
        }

    }

}

The O = O + t.getQ.getK(); breaks the demeter's law.

How should this be changed to avoid get/set and not break demeter's law?

If we create an Object of class Q locally, we take away the "two dots", but the basic information acessing is still there.

W ( T_List) {

  Q q;

  foreach(T t in T_List) {
    q = t.getQ ();
    R = R + t.getC();
    O = O + q.getK;
  }

}

Thanks.
COD3R
Thursday, April 26, 2007
 
 
I think Duncan has it about right. Getters are fairly harmless, and just mean that the underlying storage of the object happens to reflect the form in which it's users want to access it. The underlying data can usually be refactored if need be.

Setters cause much more of a problem. If you are using a lot of those it's much more of an indication that your class is really just a form of data storage - fine in some cases, as long as you acknowledge it. And remember that if your class is a data storage class it should ONLY be doing data storage, and no significant computation.

The other big problem case is when your getters allow access to objects contained within your object which can then be manipulated. As soon as that happens you've broken data encapsulation in a big way, and thrown away many of the advantages of OO.
DJ Clayworth
Thursday, April 26, 2007
 
 
I always think Java code looks needlessly messy and hard to maintain with all the getter and setter methods.  Much nicer is compiler support for "properties" and automatic getter/setter methods in c#, and even better, Delphi:

http://www.derangedcoder.net/programming/general/comparingObjectOrientedFeatures.html#properties
Herbert Sitz Send private email
Thursday, April 26, 2007
 
 
Not knowing C#, but doesn't that mean you have to disable 'automatic' getters and setters if you don't want other classes to have access to the internal variables? Since more than 4 or 5 getters and setters means your in OO trouble, typically at three lines each, the extra code usually doesn't add anything significant.
DJ Clayworth
Thursday, April 26, 2007
 
 
Based on the example, they don't look automatic to me. It looks like you can code them somewhat more concisely and conveniently, but that you still have to code them more or less the same way.
Greg Send private email
Thursday, April 26, 2007
 
 
"Based on the example, they don't look automatic to me."

Yes, I think the C# ones are mostly just a convenience.  The Delphi ones are actually automatic, or pretty close.  For example, in code below the property 'Height" defines implicit getter and setter using private variable 'FHeight'.  If you don't want any outside access of FHeight you just don't define a property.
------------------
 private
    FHeight: Cardinal;
    FWidth: Cardinal;
 public
    property Area: Cardinal read GetArea;
    property Height: Cardinal read FHeight write FHeight;
-------------------

The property 'Area' has a getter that would require you to define a method 'GetArea' that returns the appropriate value.  I don't think there's any advantage over Java when you have getters or setters that must do something more than just get or set a private variable value.  But since all a lot of getters and setters do is get and set single private variable the 'property' in Delphi's ObjectPascal gets rid of a lot of unnecessary code.
Herbert Sitz Send private email
Thursday, April 26, 2007
 
 
Regardless of how you feel about getters and setters, typing something like vehicle.getType().getNumberOfFlightDecks() is like asking Santa for a NullPointerException for Christmas.  This is one of those times where proper use of linguistic conventions eliminates bugs before they are born.  Technically I guess in Java that probably won't even compile, but in a language like Ruby you'd find out about the whoopsie at runtime, which suggests learning to love that has through construction.
Patrick McKenzie Send private email
Friday, April 27, 2007
 
 
C# 3.0 will have auto-generated getters and setters.  The syntax will look like this:

class MyClass
{
  public int MyProperty { get; set; }
}

This is very similar to a field, but it lets you change the implementation later without changing the interface.
Daniel Plaisted Send private email
Friday, April 27, 2007
 
 
Simply declaring it "public" wasn't enough, they have to add yet more syntactic 'sugar' in that "get; set;" clause?

Oh well.
AllanL5
Friday, April 27, 2007
 
 
Yeah, except that you'll have no access to the underlying storage the compiler has allocated for the property, so any get / set operation must be through the property itself - even within the class. This rules out being able to manipulate the field directly while decorating the property get/set with different behaviour. Not ideal.
.NET Guy
Friday, April 27, 2007
 
 
Even getters can modify an object state... if you implement lazy initialization pattern, for example -and you can't to do that without getters- a call to a getter method will initialize a field, changing the object state.

Another example: you can't avoid getters when implementing immutable classes for example because you have to return defensive copies of internal fields.

A good general advice is that public classes should not expose fields directly.

I've found Joshua Bloch's "Effective Java" book very useful when considering these kind of design issues. I recommend this book to every OO programmer.

Regards, Alessandro
Alessandro Ronchi Send private email
Saturday, April 28, 2007
 
 
Half the posters here aren't reading the article:

<article>
This implementation hiding principle leads to a good acid test of an OO system's quality: Can you make massive changes to a class definition—even throw out the whole thing and replace it with a completely different implementation—without impacting any of the code that uses that class's objects? This sort of modularization is the central premise of object orientation and makes maintenance much easier. Without implementation hiding, there's little point in using other OO features.

Getter and setter methods (also known as accessors) are dangerous for the same reason that public fields are dangerous: They provide external access to implementation details. What if you need to change the accessed field's type? You also have to change the accessor's return type....
</article>
Not_Enough
Saturday, April 28, 2007
 
 
I think the confusion is that there does not have to be a one-to-one match between getters/setters and variables in the class definition.

One value of getters and setters is that you can change the implementation but if you keep the getters and setters the change is invisible to clients of a class.

Although many IDEs will create getters and setters corresponding to fields in the class, this is not mandatory. Here is a contrived example (in my rather rusty Java):

class Storage {
private:
int dollars;
int cents;

public:
void setValue(int V) {
  dollars = (V / 100);
  cents = (V % 100);
}

int getValue {
  return (dollars*100 + cents);
}

};

OK, so getValue() and setValue() look as if a single integer value was being stored, but that's not what's happening. The maintainer of the class could switch to storing the value as a single integer and the change would be transparent to clients of the class.
dot for this one Send private email
Saturday, April 28, 2007
 
 
To me Getters/Setters are no good from an OO perspective simply because they violate encapsulation and from an object architecture are not really required.

However, from the perspective of a 'data mixin' they are ok
ish because they provide a place for data validation.

But then I consider that data mixins are not objects.
AndyW Send private email
Monday, April 30, 2007
 
 
How do getters and setters violate encapsulation? They act as a controlled interface to a private field. How else would you (for example) set the name on a Person object?
John Topley Send private email
Monday, April 30, 2007
 
 
An interesting rebuttal on this article can be found here:

http://www.beust.com/weblog/archives/000022.html
Gerald
Monday, April 30, 2007
 
 
The canonical answer, John, is that you'd do it in the Constructor.  The idea being that when a person comes into being they are assigned a name.

And "getter/setters" 'violate encapsulation' because to call "SetName" you have to know there IS such a thing as a "name" property (but not what it's called) and to call the "SetName" setter to set it.

That's only slightly better (but it IS slightly better) than referring to the .Name field (or whatever it's called) itself.

Personally, I feel like all of this is religious wrangling about the meaning of "OO".

But the Article is about 'Classes' that are ALL 'getters/setters' -- and that this isn't "pure" OO -- which I suppose it isn't.  But even Stroustrup says every so often all you need is a structure.
AllanL5
Monday, April 30, 2007
 
 
@Not ENough

"Half the posters here aren't reading the article:...Getter and setter methods are dangerous for the same reason that public fields are dangerous...What if you need to change the accessed field's type?"

Getters are much less dangerous than public fields for precisely that reason. Getters give you the ability to convert the type which you don't get with public fields - fir example you can change from "float myData" to "double myData"  without any problem provided you wrote "double getMydata()" as an accessor.

Take the classic "complex number" example - if you store real and imaginary parts then you can provide getReal() and getImaginary(); if you switch to storing magnitude and argument (r,theta) you don't have to change them - just rewrite them to calculate their values for r and theta.
DJ Clayworth
Monday, April 30, 2007
 
 
"The canonical answer, John, is that you'd do it in the Constructor.  The idea being that when a person comes into being they are assigned a name."

Of course, but what happens if my Person instance gets married and changes her surname?

"And "getter/setters" 'violate encapsulation' because to call "SetName" you have to know there IS such a thing as a "name" property (but not what it's called) and to call the "SetName" setter to set it."

I take the view that at some point the metal has to meet the track and you have to (gasp!) implement something. Even if you protect the concrete implementation behind an abstract interface, the clients of that interface have to know its method signatures in order to be able to use it. I was taught that encapsulation was only violated if you exposed an object's internals directly to its clients, without any sort of facade. In other words, public fields.

"But the Article is about 'Classes' that are ALL 'getters/setters' -- and that this isn't "pure" OO -- which I suppose it isn't.  But even Stroustrup says every so often all you need is a structure."

Agreed. My personal pet peeve is the J2EE pattern of having Data Transfer Objects. So you'd have a PersonDTO (note the redundant naming) that only consisted of a constructor and getters and setters. Its sole purpose in life is to act like an elevator, shuffling data between the different layers in the architecture. I don't regard such a thing as OO, it's really a struct. And I believe that C# and Ruby have language support for such things.
John Topley Send private email
Monday, April 30, 2007
 
 
@DJ Clayworth:

"Getters give you the ability to convert the type which you don't get with public fields - fir example you can change from "float myData" to "double myData"  without any problem provided you wrote "double getMydata()" as an accessor."

But when people start with "float myData" they usually use "float getMydata()" as the accessor.
DAH
Monday, April 30, 2007
 
 
"when people start with 'float myData' they usually use 'float getMydata()' as the accessor"

That's true. But that's a problem with the WAY they are using getters, not a problem caused BECAUSE they were using them. Assuming that you need myData then you have to return it as something.

The golden rule for this of course is that you design the public interface first based on the information that the other classes need to retrieve. If that happens to correspond to the way the class stores information then fine, it's a getter  (though remember to prevent the external class from being able to modify the stored copy).

The problems occur when you decide how the class will store the info first and then provide getters because it's easy. Now you've locked the external classes into a way of working, and you can't change the internal representation without major surgery.

For example, if you are pretty certain (but not absolutely certain) that myData can be stored as a float, make float the internal representation but make the getter double. Now if you find a rare case that needs double range, you can create a specialist class with the same interface but storing double. Java Point2D works like this.
DJ Clayworth
Tuesday, May 01, 2007
 
 
<article>What if you need to change the accessed field's type? You also have to change the accessor's return type....</article>

Isn't that just plain wrong?  Isn't part of the whole purpose of an accessor method that you can change underlying field types while keeping the type returned by the accessor method the same?
Herbert Sitz Send private email
Tuesday, May 01, 2007
 
 
>> The golden rule for this of course is that you design the public interface first based on the information that the other classes need to retrieve. <<

An even better rule is design the interface based on the things you want the object to do - behavior. Make the data disappear.

I just made a little diagramming tool where all the widgets on the diagram are fully built by the constructor and draw themselves. There are no get or set methods.

An immutable object with no getters is a pretty neat ideal, part of a "tell don't ask" design. It's not always possible (or maybe it is!) but the steps you take to get closer are almost always "good".

Here are some hints in this direction that are a little more fun than Holub: http://www.surfscranton.com/Architecture/LawOfDemeter.htm
Stan James Send private email
Friday, May 04, 2007
 
 
"An even better rule is design the interface based on the things you want the object to do - behavior."

Like initialize itself with values from a configuration file when the caller doesn't know its type, without having any explicit dependency on the caller's library or framework?  Spring likey the setter method.

I think property accessors don't get enough credit for this kind of flexibility.  Using a constructor as the setter is hostile to factories and frameworks, and requiring the object class to implement a specific interface for access or updates can reduce its reusability.  Both alternate implementations introduce unnecessary coupling.

Accessors can also make a class more testable.  When a void operation changes an object's state, that state can be inspected.  The fact that some fool can then use it to make bad judgements isn't a good reason to hide that information.

Obviously the relative promiscuity required of a class plays a role in its design.  Specialized workhorse classes ought to be more tightlipped and impervious to influence, whereas accessors can be practical in the case of the yes-man class trying to satisfy a diverse set of customers.
Matt Brown
Friday, May 04, 2007
 
 
"Of course, but what happens if my Person instance gets married and changes her surname?"

Answer was given earlier:

“Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.”


class person{
// ...
    void sacredunion(const person& other){
        other.surname = surname;
    }
};
Joe Bob Send private email
Friday, May 04, 2007
 
 
oops, just realized I made the "other" person a const out of speed-coding habit... it obviously should not be a const...
Joe Bob
Friday, May 04, 2007
 
 
Is it good for an object to alter the other?

Shouldnt the person changing their own name do that?

Like

class person {

 public boolean MarryTo ( Person p ) {
        this.married = true;
        this.surname = p.surname;
 }
PrisonBreak
Saturday, May 05, 2007
 
 
I suppose it depends on the kind of Person you are. Do you see the glass as half-impregnated or half-being-impregnated-by?
Joe Bob
Saturday, May 05, 2007
 
 
"Spring likey the setter method."

I'm cool with those setters at the configuration level. I started hand-building "application assembler" components in the time between Fowler's famous "inversion of control" paper and Spring. www.martinfowler.com/articles/injection.html

The immutable object on one end of the scale may be as extreme as the promiscuous JavaBean on the other. It's a Good Thing if either of those extremes upset somebody enough to make them stop and think a while. :-) It's a great conversation, and there is no "right" answer.
Stan James Send private email
Monday, May 07, 2007
 
 
The married example is interesting because I think it shows that you do not always know how you are going to "change the name" but the object's client probably does so you should expose the name setter and let the caller do it.

Examples,
Typically, females change their surnames not males, but not always.
Sometimes people get married but don't change their surname at all.

Do you add additional methods for these cases or flags to the MarryTo method?

What about other cases for changing names like adoption?  Which also may or may not include changing the surname.

Do you expect to add methods for every possible scenario for changing the surname?

If I call person.MarryTo(spouse) and I didn't intend to change the surname then I have unexpected side effect.  If I call person.SetSurname(), I'm fairly certain what it does.
Anon
Thursday, May 10, 2007
 
 

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

Other recent topics Other recent topics
 
Powered by FogBugz