which method is better?
Hello,
I remember people used to say dont define your attributes public. Have them private and write getter and setter public methods to access those attributes from outside the class. I've been doing this all the time. But now it's time to know why ;-)
What's the difference between this method and if I have the attributes public and access them directly from outside.
I appreciate your thoughts on this subject
Brian
[468 byte] By [
Brannos] at [2007-9-30 7:31:44]

In a nutshell, making the variables public ties your interface (in the general sense) to the inner workings of your class, or guts (as I call them.) This causes two main problems: 1. You have no control over the instance variables of your class i.e. you cannot protect them. 2. You now have no way to improve or enhance the design without breaking the interface of you class.
For example, let's say you move from a single-threaded to a multi-threaded system. You now need to make you class thread-safe. How do you do it if the variables are public? You have to find every reference to the variables and snychronize from the outside. Even once you've done that, there's no guarantee that a mistake wasn't made in one obscure part of code and you can't stop new code from improperly sychronizing access to that variable.
I can name more situations like this all day long. Generally, you are much better off keeping variables private.
That's a really good habit in Software Engineering. Software Engineering define a good Software design is a design with loose coupling means that the components constructing the software should be as independent as possible. With carefully defined attribute of the method provide a "strictly defined interface" (outside only need to know and only care about what the object declared public).
Dubwai,
but when it comes to synchronization, cant you define them as public synchronized. Wouldnt that be the same as having the getter and setter synchronized?
what do u mean by protecting the variables? Because even if they are private, as long as there are getters and setters you can't really contorl or protect them. so what's the difference?
Thanks Dub
The argument that led to getters and setters is that exposing data-members per se means that the implementation of the attribute is frozen. If you decide to rewrite the way attributes are handled, all client code must be changed.For example, suppose you have a class Person and you implement it like this
class Person {
...
public boolean isChildless;
}
Not obviously bad, but suppose you want to change this class so it keeps track of the number of children the Person has. You are kind of screwed. Unless you are willing to re-write all the code that accesses isChildless, you have to risk that iChildless and nChildren will be inconsistent.
If you had originally coded using getters/setters, there's no problem; You could just write
class Person {
...
public boolean getChildless() {
return nChildren == 0;
}
public void setChildless(boolean nochildren) {
if (nochildren) nChildren = 0;
else throw SomeKindOfRuntimeException();
}
}
There's also the issue that you can define getters and setters in an Interface, something you cannot do with a public data member.
Incidentally, there is one case where public data members are a good idea -- when you are creating a class that is effectively a C struct; just a container for some data that will never, ever be anything else. Ideally, you should make the public data members final, for those structs (the majority in my experience) where the value of the members cannot change after construction.
Speaking for myself, I don't think the getter/setter pattern is a particular good solution to the problem that public data members pose. I'm still working on a brief paper explaining a better solution. Send a private e-mail if you want an advance copy.
I agree with the loose coupling issue, but other than that..?
No, you can't declare variables as synchronized.
> I agree with the loose coupling issue, but other than
> that..?
Other than that, you don't even usually want to expose your fields at all--not even through getters and setters. Just adding get/set to every field is not good practice.
Assuming you do have a valid reason to expose your fields,
* synchronization, as dubwai mentioned
* bounds checking
* caching (maybe something is expensive to compute, not just stored in a variable)
* consistency/valid state (you may not allow certain combinations of values--if you set X to false, X's setter method may also set Y to zero)
* you have no control over when/how fields' values get set. You can't have listeners without methods.
* I think somebody mentioned this, but interfaces. You can't define an interface that requires a class to have a certain field. You can define one that requires it to have a getter/setter, and who cares what the field is behind it, or if there even is a single 1-to-1 relationship with a field.
* You can override get/set methods when you extend the class. Fields are not polymorphic.
jverd at 2007-7-2 0:24:33 >

> even if they are private, as long as there are getters
> and setters you can't really contorl or protect them.
Not so...
public void setFoo(Foo foo) {
if (foo == null) {
throw new IllegalArgumentException("foo must not be null");
}
// only allow us to increase foo, never decrease
if (foo.compareTo(foo_) > 0) {
foo_ = (Foo)foo_.clone(); // we don't want references to our foo leaking outside the class
}
}
public Foo getFoo() {
// lazy initialization
if (foo_ == null) {
foo_ = new Foo();
}
return (Foo)foo.clone(); // don't leak reference to our Foo outside this ojbect
}
ジ
jverd at 2007-7-2 0:24:33 >

Thanks to all of you, I have a good understanding of which method is better now...cheers/Brian
A story of mine...
I wrote an EJB having a method that returned an object of the class XXX. My customer asked if I could return an object implementing the interface XXX (instead of a class) because if the class XXX changed, he would have to recompile and redeploy a lot of components in his application server. (The application server that we use doesn't generate the EJB stub classes on the fly, so each modification of interfaces require a new recompilation and redeployment. Eeek...)
As I used getters & setters I simply derived an interface XXX from the public methods of XXX and renamed the original class XXX to XXXImpl. It was very easy (Eclipse helped a lot) and the client simply didn't have to rewrite a single line. The redeployment was done a single time, and then my customer doesn't have to be worried about changes in the class XXXImpl. If new attributes are needed in the class XXXImpl simply create a new interface XXX2 (listing only the additional getters and setters) and make XXXImpl implement XXX2 as well.
Well, using getters, setters and interfaces is not a recipe for fast code - remember that the current Sun 1.4 JVMs can't "non-virtualize" calls to interface methods - but it is fast and flexible enough for my customer.
> Well, using getters, setters and interfaces is not a
> recipe for fast code - remember that the current Sun
> 1.4 JVMs can't "non-virtualize" calls to interface
> methods - but it is fast and flexible enough for my
> customer.
If you're talking about an Enterprise web app using EJBs, I highly doubt that get/set vs. direct field access will make any noticeable performance differences. :-)
jverd at 2007-7-2 0:24:33 >

Lets introduce what is called a property. A property is really a set of methods,
a getter and a setter, which can be accessed in the same way as a field:
Wouldnt it be nice if we could do like this in java?class Person // version 1.
{
public boolean readonly isChildless; // cant set the variable from outside Person
}
class Person // version 2.
{
private int numberOfChildren;
public boolean isChildless // can access this Property in the same way as you access fields.
{
get
{
return numberOfChildren == 0;
}
}
}
If you have to expose variables then using getters/setters is a good thing, BUT do you really? Having too many getters/setters is often a sign of bad OO design. Se for example,
http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html
A lot of people got totally angry with this article because they had been using getters/setters extensiverly thinking this was all there was to good OO and now someone had the nerve to say it wasn't.
i completely agree with you uj...i can't stand that feature in .net rajnvald is describing :( you never know whena method may be called, its completely confusing.
> A lot of people got totally angry with this article
> because they had been using getters/setters
> extensiverly thinking this was all there was to good
> OO and now someone had the nerve to say it wasn't.
I found this article very annoying at first but it eventually I got my head around it and it completely changed my outlook on GUI design (mostly.)
> A lot of people got totally angry with this article
> because they had been using getters/setters
> extensiverly thinking this was all there was to good
> OO and now someone had the nerve to say it wasn't.
And some people agree with the general message, but feel the author takes it a bit to the extreme.
jverd at 2007-7-2 0:24:36 >

> And some people agree with the general message, but
> feel the author takes it a bit to the extreme.
I find the general idea appealing. Objects shouldn't fool around in public exposing themselves all over the place. They should come together briefly, mate in private and then go their separate ways. -:) Anyway this is a follow-up article,
http://www.javaworld.com/javaworld/jw-01-2004/jw-0102-toolbox.html
He's also publishing a book this summer called something like Learning Design Patterns by Looking at Code.
Mr. Holub is a good writer. Sometimes I think it's beneficial to be outrageous and take an extreme stand. It certainly made people think about what he was saying, even if they disagreed.
I'm not 100% sold on his GUI idea, because it presumes a Swing-like UI from the start. What happens if you're using a Web-based UI? What then? How does your getUI() method return the JSP?
%
> How does your getUI() method return the JSP?
iirc (if i read correctly) he is talking about moving components out and having them draw themslves
class Page {
doPost(){
new SomeTable().drawYourself(context);
// and so on
}
}
> iirc (if i read correctly) he is talking about moving
> components out and having them draw themslves
I'll have to go back and read it more closely, but I'm not sure I understand how that works with JSPs. After all, it's the browser that does the rendering here, so the idea that a component will "draw itself" doesn't seem right to me. They can provide the response stream that will be written back to the client, but the browser will be in charge of rendering. It just feels different than a desktop Swing UI, I guess.
%
> I'll have to go back and read it more closely, but I'm
> not sure I understand how that works with JSPs. After
> all, it's the browser that does the rendering here, so
> the idea that a component will "draw itself" doesn't
> seem right to me. They can provide the response
> stream that will be written back to the client, but
> the browser will be in charge of rendering. It just
> feels different than a desktop Swing UI, I guess.
The component doesn't actually draw itself, it takes the call and then has 'helpers' that draw it. I tried this out and what it means is you use Abstract Factories for drawing the components but the component drives it, if that makes sense.
So how do you hook in the browser as a helper?I think it's a very desktop-centric view of user interfaces.%
> So how do you hook in the browser as a helper?
>
> I think it's a very desktop-centric view of user
> interfaces.
Well first, let me clarify, the 'component' in this case is a wrapper for a model element, for example.
You don't. You have a your AbstractFactory provide a Servlet helper. In the component 'draw me' method, it calls it's helper component, which renders it as HTML. Your drawing helper is tied into some larger helper that manages the big picture. The helper design is basically a fre-for-all. It can be anything you like really and can be completely coupled to the component and it's other parts. That's the way I did it, anyway.
In the end you end up with the component providing all the info that it would with the getters. The difference is that it's a push instead of a pull.
It's hard to image until you try it. I made an effort to do it the Holub way (not sure I completely succeded.) Not that I do everything that way, I'm still getting my head around it. I'm sure if you made the a similar effort you would would succeed.
>
> Well first, let me clarify, the 'component' in this case is a wrapper for a model element, for example.
>
Very good. I've read other attempts at this where the thing returned from a getUI() method was the UI component. I need to re-read the Holub paper more closely.
> You don't. You have a your AbstractFactory provide a
> Servlet helper. In the component 'draw me' method, it
> calls it's helper component, which renders it as HTML.
> Your drawing helper is tied into some larger helper
> that manages the big picture. The helper design is
> basically a fre-for-all. It can be anything you like
> really and can be completely coupled to the component
> and it's other parts. That's the way I did it,
> anyway.
I'll have to think about it. The browser is doing all the drawing here, so I don't see how I code that.
I'm not sure how I'd do this with Struts, for example.
>
> In the end you end up with the component providing all
> the info that it would with the getters. The
> difference is that it's a push instead of a pull.
>
I like the idea. It's the implementation that I don't understand, I guess.
> It's hard to image until you try it. I made an effort to do it the Holub way (not sure I completely
> succeded.) Not that I do everything that way, I'm still getting my head around it.
As am I. I think I need more practice.
> I'm sure if you made the a similar effort you would would succeed.
I'm not so sure, but I'm willing to try. ;)
%
PS - I've often wondered if learning Smalltalk, the purest of the pure O-O languages, would be a good idea. It might influence the way I write Java and C++ in a positive way.
> PS - I've often wondered if learning Smalltalk, the
> purest of the pure O-O languages, would be a good
> idea. It might influence the way I write Java and C++
> in a positive way.
I think Java is really very suited to design patterns. The lack of the gazillions of shrtcuts and tricks available in C++ bascially forces one to use patterns in order to get certain behaviors. I think Java design philosophy has been perverted by heretics such as pre-optimizers and VB slugs. We need to drive out these devil worshipers and restore the true faith!
> I like the idea. It's the implementation that I don't> understand, I guess.After I move my computer this wekend I'll see if I can find an appropriate excerpt of my experiment to show you what I ended up with. Not that that is the 'way'.
I don't disagree that Java is well-suited to patterns.
I'm just saying that I've only learned Java and C++ O-O languages. I think the Holub "no getters/setters" philosophy goes back to the purer Smalltalk view of objects where one sent messages and left the internal data alone. Thinking that way more might have benefit for Java.
Alan Perlis once said: "A language that doesn't affect the way you think about programming is not worth knowing." I've learned neither Smalltalk nor Lisp. Perhaps I should.
Thanks, dubwai - I'll look forward to the results of your experiment. Maybe I'll play with it a bit too, if I have time and energy.
%