tags:

views:

149

answers:

6

Usually JavaPractices.com is a good site with good idea's, but this one troubles me: JavaBeans are bad.

The article cites several reasons, mainly that the term JavaBean means "A Java Bean is a reusable software component that can be manipulated visually in a builder tool." not Data storage, violates certain patters, and is more complex.

Now I can agree with the last one, but in my eyes JavaBeans in a list makes a lot more sense than nested Maps. The article claims that database mapping frameworks should call constructors, not set* methods, and the object should be immutable. In my mind however, calling set* methods when trying to build an object is easier to read than new MappedObject("column1", "column2", "yet another column", "this is stupid");

I also use the JavaBean style class for other things besides database mapping, eg for an IRC bot, having an object per user that gets updated with various things. I don't want to create a new object every time new information is given, I want to add it to an existing one.

So my question: Is using JavaBeans for data storage a bad practice and should be avoided, or is it perfectly safe?

A: 

Its perfectly safe, and far more preferable than endlessly nested java.util.Map. You gain type safety, easier to understand code, and avoid your code ending up on The Daily WTF. Note that the implementation should be segregated - don't mix too much logic (beyond simple validation) into your data storage classes. You should read about POJOs

Yann Ramin
+3  A: 

"The JavaBeans pattern has serious disadvantages." - Joshua Bloch, Effective Java
I love those guys. Taking arbitrary quotes out of context is already reason for me not to trust such article.

BTW, referred book (Effective Java) has extensive discussion about both those models, their advantages, disadvantages and alternatives. You might want to check it out. But there's nothing inherently wrong with java beans, just sometimes their are not the best choice.

edit
Effective Java in google books, see item 2:
http://books.google.com/books?id=ka2VUBqHiWkC&lpg=PP1&pg=PA11#v=onepage&q&f=false

Nikita Rybak
I agree that the arguments in the article are very weak, based on quotes taken out of context and the article does not propose an alternative that's clearly better. In other words, @Lord.Quackstar: don't believe anything you read in a random article on Internet at face value.
Jesper
+1  A: 

The article's intentions are well-meant, but in practice avoiding beans and setters is hard to uphold. For example, having frameworks use constructors is not possible in many cases since names are usually the identifying feature, and method/constructor parameter names are not maintained in the .class file. (Although there is at least one library to work around this.)

Setters are the next best thing - not as "pure" OO, but a huge convenience over constructors and work well in practice.

Whem tests start failing because of "bad" java beans, then I'll reconsider it cause for concern. But I've not seen that so far. The only time I'd say they are probably inappropriate is having shared beans in multithreaded code, since synchronizing the shared mutable state is tricky. Steer clear of that and beans are just fine.

mdma
What would you consider a "bad java bean"?
TheLQ
The "bad" was my humoring the article title - I don't think they are intrinsicly bad - but like all patterns they can be abused to become an anti-pattern. Maybe in some cases beans can produce unnecessary decoupling between behaviour and data, or where the habitual single line getter/setter would be better done as a richer computation. And if only properties were a first class concept then we could build upon the pattern without the need for strings (property names) and reflection...
mdma
+6  A: 

It seems that you are misreading the text.

Now I can agree with the last one, but in my eye's JavaBeans in a list makes alot more sense than nested Maps

The text never mentions nested maps as an alternative ( yiack )

...should call constructors, not set* methods, and the object should be immutable

This is a good practice, specially useful when dealing with threads.

But we can't say that using setters is baaad either, specially when a single thread is using the object. That's perfectly safe.

I don't want to create a new object every time new information is given, I want to add it to an existing one.

That's fine, as long as you control the object there is no problem with this, some other may find easier to just create a new object.

Is using JavaBeans for data storage a bad practice and should be avoided, or is it perfectly safe?

No, is not a bad practice. Is not perfectly safe either. Depends on the situation.

The problem with mutable objects ( not with JavaBeans per se ) is using different threads to access them.

You have to synchronize the access to avoid one thread modify the object while other is accessing it.

Immutable objects doesn't have this problem, because, .. well they can't change, and thus, you don't have to synchronize anything.

To make sure an object is immutable you have to declare your attributes as final.

class MyBean  {
    private final int i;
}

If you want to assign a reasonable value to MyBean.i you have to specify it in the constructor:

 public MyBean( int i ) {
     this.i = i;
 }

Since the variable is final, you can't use a setter. You can just provide a getter.

This is perfectly thread-safe and the best is, you don't have to synchronize the access, because if two threads try to get the value of i they both will always see the value that was assigned on instantiation, you don't have to synchronize anything.

Is not bad practice or good practice. Must of us have to work with a single thread, even in multithread environments like servlets.

If in the future you have to deal with multi thread applications, you may consider using an immutable JavaBean ;)

BTW, the alternative to create immutable beans, and still provide a bunch of setters is using Builders like:

 Employee e = new EmployeeBuilder()
                  .setName("Oscar")
                  .setLastName("Reyes")
                  .setAge(0x1F)
                  .setEmployeeId("123forme")
                  .build(); 

Which looks pretty similar to the regular setXyz used in regular beans with the benefit of using immutable data.

If you need to change one value, you can use a class method:

 Employee e = Employee.withName( e, "Mr. Oscar");

Which takes the existing object, and copy all the values, and set's a new one....

 public static EmployeeWithName( Employee e , String newName ){
      return new Employee( newName, e.lastName, e.age, e.employeeId );
  }

But again, in a single thread model is perfectly safe to use getters/setters.

PS I strongly encourage you to buy this book: Effective Java. You'll never regret about it, and you'll have information to judge better articles like one cited.

OscarRyz
+1 for good content. I talked about nested maps because I use beans for other things besides database rows, IE evolving user objects. However since both are evolving, I'm not sure the immutable route, although it does have benefits, is best here since if I wanted to change the object, I still have syncing issues + trying to replace the existing object.
TheLQ
@Lord.Quackstar Yes, but most of the times single thread is good enough, and Java beans are not a bad pattern or anything. They are just an alternative.
OscarRyz
+1  A: 

The main reason for avoiding setters is immutability. Code for immutability up front and you avoid any threading issues around those objects.

If you end up with a constructor that reads

new Person("param 1","param 2","param 3","param 4","param 5","param 6","param 7","param 8")

then your object is too complicated. You will need Parameter objects (See the Martin Fowler Refactoring book).

Code defensively at the start and the people who come along and maintain your code will either thank you (good) or curse you (because they can't be lazy and just mutate objects).

When you need to change the object, add a copy constructor (i.e. clone method). Modern JVMs deal with this easily and quickly enough and there is little speed penalty. You also make things easy for Hotspot and the GC.

Fortyrunner
A: 

My objection to using JavaBeans as data storage classes is that they allow for objects with inconsistent state. In the typical use case for such beans, you have the following steps:

  • instantiate the class;
  • set the first property;
  • set the second property;
  • ...
  • set the final property;
  • use the object instance.

Now your class is ready to use. So what's the problem here? Between instantiating the class and setting the final property you have an object which is in an internally-inconsistent or unusable state, but there's nothing preventing you from accidentally using it. I prefer a system where the class is automatically in a consistent, usable state upon instantiation. For this reason I prefer to either pass in all the initial state in the constructor or, if said initial state is too complicated, pass in the initial state in the form of a hash map or set or the like. The use case scenario is now:

  • (Optional: set up a parameters object);
  • instantiate the class;
  • use the object instance.

At no point in this work flow is it possible for me to accidentally start using an object with inconsistent state. If I use a parameters object, it is not directly used for anything at all and its contents will be vetted upon instantiation of my main class. The main class itself, upon returning from instantiation, will give me an object instance that is of immediate use.

This kind of setup is best for simpler objects, of course. For more complicated objects with things like optional properties, etc. you'll want to go a step farther and use something like the Builder pattern that others have pointed you toward. Builders are nice when you have more complicated scenarios, IMO, but for simpler, more straightforward parametrization just using constructor arguments or a parameters object of some sort is more than enough.

JUST MY correct OPINION