Is Over Abstraction Java's Achilles Heel?
|
|
Is over abstraction Java's Achilles Heel? It's been talked about by Kimbro Staken and again by James Turner, and finally a rant by Russell Beattie. The problem is that many Java API's tend to be overly abstract and it just seems there's a culture that makes things harder than necessary. It's as if Java developers in their quest for the ultimate flexible and extensible framework have completely sacrificed usable APIs.
I wrote once about some tips on how to build more usable APIs, unfortunately there's this irrational itch in the Java world to build the perfect framework. Exhibit, the massive number of Java frameworks all put together to solve a problem that should have been solved by now. Equally more troubling are the fact that most of these frameworks are never employed to build something useful. To top it off, the community can't seem to pinpoint what the real problem is (revealed by this recent poll).
It's a paradox that simplicity (i.e. over C++) was the primary reason why Java gained its massive popularity. However, the heart of the problem seems to be emanating from no other than the source. That is, Sun Microsystems. In its incessant need to scratch an itch, it has bludgeoned and ultimately conditioned the community to accept extremely flexible however overly complex APIs. Let's just line up the usual suspects: JINI, Swing, EJB, JMX and JAXP1. So its simply no surprise that a majority of Java developers see overly complex APIs as the norm, matter of fact its the standard to emulate!
Unfortunately, the only advice that most people give is "make the most common case easy to do". But how does one pray tell find the common case? The quick answer is to build an application to test out the API, however that only tests out one case. Maybe that means you need to write more than one app, which rarely anyone ever does. So you would have to take a wild guess by picking what you think to be a common case or let's say common "use case". Choose one then wrap it around either a single function or one big facade. Unfortunately, these aren't without its own problems.
The single function doesn't work too well with Java because of the lack of named, optional, default arguments then add to the fact that many have been taught that such a construct is frowned upon by OO zealots. It's unfortunate that Java as a language doesn't support the simplification of procedural like constructs, even a language like C does a better job. So if you wonder why other languages make it easier, this should be your main suspect.
The Facade pattern would appear to be the more appealing to the OO zealots. Afterall, it's in the GOF book (i.e. the Bible for OO) However, it's froth with its own set of usability problems. The pattern doesn't demand that the Facade's methods have no sequencing dependencies. That is, many times it does matter if you call method B before you call method A. This in fact makes it much more difficult to use than the single function strategy above.
Two strategies come to mind to fix these problems. Brian Slesinky's Half-Bean and Struct Arguments are patterns to circumvent the Java language function construct limitations. The second strategy is to apply "refactoring to implicit invocation". The idea is to encapsulate implicit method invocation dependencies into coarse grained objects2. These two strategies are complementary and can be used with great effectiveness. Now, you can still scratch your itch and have unusable APIs3.
In conclusion, it's incorrect to say that Java APIs are over abstracted, rather its the otherway around, Java APIs are under abstracted, in the sense that features that should otherwise be hidden are exposed throughout the API.
1. I'm sure there are more, but this is worthy of yet another poll2. "Why Document Passing is Loosely Coupled"
3. This leads me to a final thought, BEAs asynchronous controls which is in its way to JSR status may just be the perfect ingredient that makes Java APIs more usable. See this for more details.

