I hate Java Beans.
Okay, so I really don't have Java Beans. But I do hate the abuse of this design model, just as I hate the abuse of any otherwise reasonable design models.
What? Don't know what I'm talking about? Okay, here goes, for those who aren't indoctrinated into the
cult ways of Java programming--an art which, I'm honest to report, I'm not quite comfortable with.
See, in languages such as Visual Basic or Visual C++, you have this Microsoft-ian thing called a COM object, which is a way where objects can present a multitude of programmatic interfaces, and you can --at run time--discover what interfaces your object provides. So, for example, you can create a basic COM object which provides two interfaces: IInterfaceA and IInterfaceB, and call the object's QueryInterface() method to obtain a reference to the other interface. COM objects also support resource counting, so you can have multiple references to a single object, and when the last reference is released, the object is automatically deleted.
On top of this rather simple (and banial) concept, which predates the dynamic_cast<> operator on C++, Microsoft introduced the concept of the IDispatch interface. This allows a programmatic way not only to query which one of several set interfaces a COM object provides, but also to perform a form of "introspection" on C++ objects, so programmatically you can enumerate (via the IDispatch interface) the list of methods provided by an interface, and invoke them.
For Java programmers, I'm sure you'll think "who cares"--after all, what Microsoft does in thousands of lines of C++ code, Java programmers get for free in the java.lang.reflect package.
But not to be stopped in Microsoft's desire to
pile tons of crap on top of other crap until something useful comes out innovate, they used COM objects with an IDispatch interface to create GUI components which can be invoked and run at design time, as well as at run time.
Why is this significant, you say? (And that's assuming you have the foggiest idea what the hell I'm talking about...)
Well, it means that some junior GUI engineer who doesn't know how to write a line of code can sit down in front of a GUI builder, and drag and drop components of an interface and hook them together. Each component provides a set of standard interfaces (such as IDispatch to discover what various object settings--such as color or font of a button--are available), and that set of standard interfaces allow a GUI builder to create an instance of, oh, say, a button, and hook it into an instance of, oh, say, a dialog box.
Volia! Instant interface; just drag and drop and hit the "save" button! What used to take in the late 1980's several weeks to do in the Macintosh Toolbox now takes an afternoon in Microsoft Windows. (And I should know; I wrote enough Macintosh Toolbox code in my day.)
Java gives you introspection pretty much for free, but the idea of building visual interface components and drag them together and get a working interface is a pretty cool idea. Especially because the first release of Java's AWT was even worse than the Macintosh toolbox to use. So Java introduced the concept of a Java Bean.
Now just because you can find a method doesn't mean you know what that method is, programmatically speaking. That is, just because you know that your class has a bunch of methods called "updateThing", "computeItem", "validateObject" means you have a clue what that method is supposed to do. So the Java Bean specification defines some standard method names so that a program inspecting your bean can know what's going on.
In other words, a Java Bean is just a class whose methods follow a certain naming convention. For example, according to the specification, if I have a property called "font" which takes the name of a font, then my Bean should provide two methods: 'String getFont()' and 'void setFont(String)'--the first is used to get the current font, the second used to set the font. A program which then loads your bean can then know your bean has this property called "Font" which takes a string--and even prompt you if you want to change the font.
So far, happiness. And if done right, you can then pop up a visual editor, drag and drop your beans together, and have a new application. And better yet, another user can come along, grab your beans, and build something new you never thought of.
So why do I hate beans?
The tradeoff of any sort of visual editing system is that you wind up adding additional complexity to the code. This is fine if your objects are well defined: I don't mind a little additional complexity if I'm creating (for example) a spreadsheet visual component and want someone else to be able to plug it into their program without pestering me too much.
But if you are not using this bean object within it's original context, well, it's just additional complexity
that doesn't get you anything except extra reams of code that is almost impossible to maintain.To give you a simple example, suppose I have an object 'adder' which adds two numbers. Intuitively, that method should be invoked by writing:
sum = adder.add(a,b);
However, if we were to rewrite this as a bean using the getter/setter method naming conventions, this is what we could potentially wind up with:
adder.setFirst(a);
adder.setSecond(b);
adder.sum();
sum = adder.getResult();
We've replaced one line of code, which is relatively easy to understand, with four lines of code which is a royal pain in the ass to follow.
Now if we are constructing our adder object to be used within a GUI builder or visual application builder IDE, then we may wish to build our adder this way: that way, we could (for example) drag a line from the "Read Input Field" field to our "First" input, a second line from the "Read Instrument Input" field to our "Second" input, and drag a line from our "Result" output to our "Display Meter" object.
But if we are not touching this thing in a Java Bean visual editor? All we've done is made a simple operation of adding two numbers four times more complex. Further, we've created a
stateful bean object, and introduced the possibility of extra unnecessary complexity and chances for making the code impossible to maintain. So, for example:
adder.setFirst(a);
thing.process();
callThisRoutine();
System.out.println("Some log stuff");
callThatRoutine();
adder.setSecond(b);
thing.reprocess();
adder.sum();
System.out.println("Some more log stuff");
callAnotherRoutine(a);
doSomethingElse();
return adder.getResult();
You see what has happened? We've managed to
completely bury the fact that this routine returns 'a+b' in endless meaningless and useless complexity.And because the meaning is now buried, we've created code that someone who was new to the team would not want to touch with a ten foot pole; after all, they have no way of knowing what is meaningless complexity, and what is
important complexity--that is, complexity that is driven by the needs of the project, rather than complexity that was thrown in out of laziness on the part of the programmer.
Yes, laziness: part of our job as programmers is supposed to be simplification of the problem (but not
oversimplification) so we can both understand the problem, solve the problem in the simplest way possible, and write code that can be maintained in the future.
And our routine above, which returns 'a+b', is now impossible to maintain.
You don't think that happens in the real world?
Poor naive fool. Just apply for a job at Symantec and I'll be happy to show you real-world examples of this sort of nonesense.