tags:

views:

984

answers:

5

I'm wondering if I'm missing something about Java Beans. I like my objects to do as much initialization in the constructor as possible and have a minimum number of mutators. Beans seem to go directly against this and generally feel clunky. What capabilities am I missing out on by not building my objects as Beans?

+1  A: 

Beans are configured that way so automated tools can create and modify the Beans. They aren't meant to necessarily be great design patterns.

Examples of these tools:

Hibernate
JMX

jjnguy
Sure. Are any of the automated tools (besides serialization) worth using? Examples? Thanks!
Dave Ray
Honestly....I have no idea.
jjnguy
One good example would be Hibernate it needs getters and setters to do access the properties being persisted.
bmatthews68
I think struts and spring and web frameworks like that use the Beans to automate some of the website building processes. I wouldn't use beans unless you had to.
jjnguy
JMX is another example.
ykaganovich
And GUI editors like NetBeans Matisse.
Michael Myers
Hibernate does not require getters and setters. It can work directly with fields. It can can also bypass access restrictions (that is, use private fields and methods) as long as the security manager allows it. Some optimizations are disabled when working with final (including private) API though.
erickson
+7  A: 

I like my objects to do as much initialization in the constructor as possible and have a minimum number of mutators.

Favouring immutable objects is a wise choice. However the benefit of beans is that frameworks/tools/libraries can determine at runtime the properties of a class, without requiring you to implement a particular interface.

For example, assume you have a collection of Person beans, and each bean has properties such as name, age, height, etc.

You can sort this collection of beans by name (for example) using the following code:

Collection<Person> myCollection = // initialise and populate the collection
Comparator nameCompare = new BeanComparator("name");
Collections.sort(myCollection, nameCompare);

The BeanComparator class knows how to extract the "name" property from each object, because the Java Beans convention is followed, i.e. you're spared the "overhead" of implementing an interface such as:

interface Nameable {
    public String getName();
    public void setName(String name);
}

Another example from Spring MVC is a bean that stores request URL parameters. This can be defined in a web controller (known as an 'Action' in Struts) like this:

public ModelAndView searchUsers(UserSearchCriteria criteria) {
    // implementation omitted
}

Because UserSearchCriteria is expected to be a JavaBean, if the request URL contains a parameter such as maxItems=6, the Spring framework 'knows' that it should call a method with the signature

void setMaxItems(int maxItems);

In essence, JavaBeans is just a simple convention which allows the properties of a class to be discovered dynamically at runtime (usually by a tool or framework), when it's inconvenient/impossible to know a priori the properties that may be provided.

Don
BeanComparator is nasty. Reflection is for design-time and frameworks, not for the heart of a sort loop.
erickson
+10  A: 

It sounds like you are on the right track. It's not you who's missing the point of Java Beans, it is other programmers that are misusing them.

The Java Beans specification was designed to be used with visual tools. The idea was that an application designer would be able to configure an instance of an object interactively, then serialize (or generate code for) the configured bean, so that it could be reconstructed at runtime; the intent was that it would not be mutated at runtime.

Unfortunately, a lot of developers don't understand that accessors violate encapsulation. They use structs instead of objects. They don't see anything wrong with other classes, even other packages, having dependencies on a class's data members.

Of course, you will in general have the need to configure instances of your objects. It's just that this should be done through some sort of configuration feature. This might be a dependency injection container, a "BeanBox" style visual tool, or simply reading JSON, XML, or properties files that you wrote by hand. The key is that at runtime these objects are effectively immutable; clients just invoke their operations, they don't access their properties.

erickson
Holub follows a definition of encapsulation I call "data hiding".I prefer "data protection". The game is all about knowing when and how your data is changed. As long as the data itself is private, you're in control of changes. At that point, what counts is whether you want it immutable or not.
Scott Stanchfield
Minimizing the coupling between types greatly eases code readability and maintenance. Authorities like Holub and my own anecdotal experience have taught me that external dependencies on object properties are symptomatic of unnecessary complexity. There's usually an easier, cleaner alternative.
erickson
+1  A: 

When you hear the word "bean" expect to be looking at a "container" of some sort. The idea of a JavaBean of any sort is to provide a uniform interface convention for components that can be added and manipulated at run time. Plain JavaBeans are just the simplest example of this: it presents all the interface possibilities and is Serializable, which means you can create instances of the bean, modify them, save them, and reload them.

Long and long ago, I write a Java editor that contained a simple "data base" representing the text strings, and had a "plug in architecture" that used beans. You could add behavior to the editor by dragging a bean out of a bean storage bin and dropping it on the editor; once you did, the behavior (say, Cntl-T to transpose characters at cursor) was automagically available in the editor. The beans had a known interface --- they knew how to ask the container for its data structure, and a doSomething() method --- and the container knew to dynamically load a class file, instantiate the object, and set its access to the data base.

By the way, it's not really necessarily true that accessors violate encapsulation; it is however true that just because you have a member, you don't need to provide get and set methods for it. The JavaBean spec is a little unclear on this; the point is to provide getters and setters for those things that need to be in the objects "contract".

After introspection and reflection were added to the language and really understood, the need for those conventions was somewhat reduced; in early Java, you needed to have a convention to find the methods.

Charlie Martin
+2  A: 

I share the idea that minimize the mutability is a good thing. As already pointed out, the advantage of JavaBeans is that they are easy to handle by the frameworks.

To get the best of "both worlds", I think that a good option is to use the Builder pattern, slightly modifying the Builder to comply with the JavaBeans standard. So, if you need a framework functionality that requires that your class comply with the JavaBeans standard, you can use the Builder instead the actual class.

german1981