zondag 11 september 2016

What's wrong with Java Beans?

TLDR: This is my rant against the concept of Java Beans.
Im my previous post I mentioned that beans are a great way to compose a solution out of smaller parts. I also mentioned writing generators for the boilerplate of a bean. Such generators are now standard in modern IDEs.  Sadly one important thing Java does not have is real properties. Syntactic sugar for properties is present in  languages like: C#,  F#, Scala, Kotlin and Ceylon.

Programming is a way of communicating your ideas:
  1. To yourself
  2. To your later self
  3. To your coworkers
  4. To the unknown people that have to maintain your crap(often politely called legacy).
  5. To outside programmers, aka customers, if you are writing a library.
In daily life we use  words, sentences paragraphs etc to express our ideas. For a frequently used idea we use  single word as  succint way of communication, a shared understanding.

Java Beans are a little bit more verbose. They use sentences to express  simple ideas:
  • For just a simple object holding a Person's details you have to add fields, getters with comments and setters with comments. 
  • Supporting one field requires at least 15 lines of code.
  • These lines need tests too! 
  • This code needs to be maintained by you, your future self, coworkers, and the guy after you.  Customers have to read about the getters and the setters from the Javadocs.
  • These lines clutter your codebase.
When Microsoft copied  improved upon Java by inventing C# they did at least one thing right. They introduced syntactic sugar for properties. Nowadays a simple property in C# is just one line, almost like a public field.  Example:

public string Name{get; set;}="John Doe";

That is:
  • 14 lines less to be read. No clutter!
  • One line to be maintained by you.
  • One line to be maintained by your future self.
  • One line to be maintained by coworkers.
  • One line to be maintained by the guy after you.
  • Much less documentation to be written.
  • Less tests to write.
  • More time to break other stuff.
Languages such as F#, Scala, Kotlin and Ceylon even improved this further. A simple class definition in these languages is a one liner:

class Person(string name, string address);

Often forgotten methods

Write default constructor, the getters, setters, the related tests and the Javadoc and your beautiful bean  is ready for use? Wrong!. When your bean is used in  collections the collection framework uses equals(...) and hashCode() for sorting bean instances. If you do nothing the equals() and hashCode()  of the super class  Object  will be used. This is usually not what you want.

For debugging purposes having a custom toString() function is a nice to have,
If you add these you already  have some code to maintain and write tests for.

Unlike C#, Java does not allow operator overloading so there are no operators to overload.

 F#,  probably other languages too, even goes a bit further by also including sensible implementations for comperator functions. These functions are more important if you use Streams. To the .NET programmer: Streams are Java's way to LINQ without syntactic sugar in the language.

Ease the pain with code generation

IDEs like Eclipse come with  code generation functionality. You can:
  • generate getters and setters form fields.
  • generate a  hashCode() and equals(...) function.
  • generate a toString() function.
 In a language like F# these functions are generated by the compiler automatically. developers do not see these functions so nothing to maintain or break.

Sadly there is no support for maintainance. Maintainance when adding, changing or deleting fields to a bean, are left to the crafmanship of the developer. This will not change in coming Java version 9.  We have to live with it for near future.

 I wonder, how do you count your beans and check whether they are in good shape?

What's Next

  • A final word or a word on final.
  • Decorators to constrain types.
  • Streams.
  • Automatic Getter/Setter and more testing for Beans.