views:

367

answers:

6

I don't understand the nature of Java Beans that well. Well, at least how I see them used in some code-bases that pass through our shop.

I found this question:

http://stackoverflow.com/questions/315142/java-beans-what-am-i-missing

The accepted answer there makes it look like programmers tend to abuse Java Bean (which I really don't doubt), but I see it happen so often and so deliberately, I think I'm still missing something.

I see code that looks like:

public class FooBean {
  private int a;
  private int b;
  private int c;

  public int getA() { return a; }
  public int setA(int x) { a = x; }

  // etc...
}

No further structure or control than getters and setters. Is there some sort of super awesome compiler trick going on that involves reflection, getters and setters, and the need for some very awkward (but compiler optimized) static associative arrays?

Or maybe I'm completely missing the point. :\

Cheers!

Edit:

Definitely not promoting the idea of public fields, here.

A: 

'getters' and 'setters' are great if you want to override the access to your data, for example for logging/security or returning a value different from the original class.

Pierre
+2  A: 

People do overuse silly getter/setters, no doubt about that.

However, imagine how much pain you have to go through 2 years down the road when you realize you have to strip withespaces off the string in your setEmail(string email); method and all your code is hard coupled to use public fields instead of a method call.

Remember one of the major rules of object oriented design "Code towards an interface, not an implementation". Accessing public fields of a class is certainly the latter, and will make refactoring code much harder.

nos
The objection isn't necessarily to the idea of getters and setters, but to the fact that we have to write the damned things by hand.
skaffman
@skaffman, modern IDE's provide templates so it is easy to get it autogenerated. Eclipse can generate constructors and get/set'ers for multiple fields.
Thorbjørn Ravn Andersen
OK, fair enough,. but you still end up with shedloads of useless clutter.
skaffman
@skaffman: IDEs could easily be written to hide "useless" getters and setters, like Eclipse can hide 'import' statements. But I haven't noticed an IDE that does this. Either I'm not looking very hard ... or most programmers don't care enough to demand that IDEs implement this.
Stephen C
@nos your answer shows the EXACT problem with setters and getters. You don't ask an object for data, you ask it to operate on it's data. So you might have a name, but you would make it final and set it in the constructor only if at all possible (where you can easily manipulate it before setting the field)... You probably shouldn't have a getter, but they are less egregious... But you may have a getPreferredEmail() which would return one of the email addresses it stores, this isn't a pure getter. Better yet might be a mailTo() method in your object.
Bill K
+1  A: 

without a setter you cannot check for invariants:

public void setFoo(Foo foo) { 
     if (foo == null) {
          throw new InvalidFoo();
     }

     this.foo = foo;
}

with public members you cannot do that. Second point, within a setter you can fire events that other beans can listen to. Last but not least, you can enforce proper type checking (as you pointed out in your question).

dfa
please explain downvote
dfa
It was a fair answer... countered!
skaffman
I downvoted because you did not address the actual question.
Mike Daniels
Agreed, has nothing to do with the question. Does an answer like "Water is wet" deserve an up-vote? It's 100% correct and very useful information, but not really applicable to the question at hand.
Bill K
Also, that's an anti-pattern for invariants, it would be much better to make it final and set it in the constructor, that way you know for sure that not even your own code is setting it. This would be quite useful if you absolutely needed to use the builder pattern, but if that was the case you should be returning "this".
Bill K
anti-pattern? you cannot model all objects as immutable
dfa
@Bill: however you are right, my answer is not good as the accepted one
dfa
+4  A: 

Actually, yes, there is magic going on.

It's a really dumb pattern, but GUI beans (which all components are) were intended to be reflectively analyzed by a GUI builder. The public set/get fields are intended to be "Properties" that the user can muck with while building his GUI.

Edit: In defense of sun, I should say that although the pattern turned out to be pretty obnoxious because of all the people that copied it and started using it throughout their non-bean code, It did allow people to integrate classes with a GUI builder without using any outside meta-data. You didn't need any XML file or properties file for the editor, it was as easy as extending Button and dropping your new object onto the pallet.

This pattern has been used in other places and, as you noticed, it's pretty much the same as having public fields. I think it's one of the worst patters sun created when setting up java, but there were no other obvious solutions (I think the whole concept was kind of tacked on by the first people trying to build the first GUI builders before java's release).

Now there is a much better solution: using annotations to mark private fields, a reflective tool could still analyze them and bind them to the builder controls. This would be a good deal cleaner and not make all your objects so vulnerable to external state changes.

Bill K
+2  A: 

Java Beans are, as you point out, a fairly trivial coding convention.

The useful part is that they were a convention at all. This allowed auxiliary tools to be built which were based on (at the time) novel ideas like specifying exactly what the name of getters and setters were, and an expectation that specific methods would exist without needing to ascribe to an Interface. This allowed enough flexibility to do whatever you wanted, but still allowed you to use the GUI for assembling beans.

At this point, with full introspection being the norm, and other languages having formalized get/set functionality, and many other ways to do what Beans do, I think they're an idea whose time has passed.

Alex Feinman
+1 for a good summary of what the convention is for. But I'd take issue with your assertion that the convention is no longer needed. Spring is an example that makes extensive use of bean style wiring. If you have a large scale web service that is largely composed of Java components, it is much neater to wire them together via an XML file than to write Java code to do the wiring.
Stephen C
And most would now use annotations over bean style wiring because the bean style is, in a word, bad.
Bill K
+1  A: 

You're not missing the point. Getters/Setters are ugly, but are embedded into so many tools that make assumptions about class/method/field names (e.g. spring) that (aside from their obvious value for encapsulation) they've effectively become a near requirement, unless you're working in a very limited and private context.

Steve B.
Doesn't spring now prefer annotations because beans suck? Setters and getters are the opposite of encapsulation by the way--they allow access to internal state that should be hidden completely.
Bill K