Home

Java still mostly sucks. Film at 11

At my new company, Java has been designated as “the” language. I won’t comment on this decision, and actually they’re reasonably relaxed about it (if you can show that one of the other existing main languages in the company - PHP, Perl, C - will work better, you’re probably free to move ahead), but still, it means I found myself installing JDK1.5, Eclipse, Tomcat, ….

My last major Java project was done somewhere around ‘98-’99, which meant Emacs/JDE and homebrew GNUmakefiles. It was quite horrible, and we only managed to make some speed because I introduced JPython. I never looked back and if, only because I was (and am) still a Jini fan…

So, coming back to Java with JDK1.5 and Eclipse has shown some progress. The development environment is a whole lot better, maybe almost as good as Turbo C++ in the early ’90s. Still a long way to go to what Smalltalk offers, but the differences are getting small enough that it isn’t very painful anymore. Most of the Smalltalk IDE has been stole^H^H^H^Hreinvented, and we’ll just ignore the fact that you need roughly 400Mb for an IDE+Webserver development environment (excluding your sources, third-party jars, compiled .class files, and whatnot).

However, the language is quickly getting scarily close to the baroque bloatspec of C++. And all it does, with all these additional language features, is introducing more complexity. Granted, templates (oh, sorry: “generics”) let you leave out numerous annoying typecasts, and the automatic boxing/unboxing is an antiwart that almost (but not entirely) covers the wart of the primitive/Object dichotomy, but there’s still nothing there that helps me write clean, simple to understand, well-factored code. This is a dead end, and my prediction therefore is that Java is well underway to becoming just as obsolete as C++ (which is, IMNSHO, not obsolete enough at all, but still, a start :-) ). Just the fact that my train of thought is interrupted 5 times a minute (when I press “save” and thus “compile”) because I have to babysit the compiler through all its anal typing requirements should say a lot. Loss of concentration is probably the worst thing that can happen to a programmer…

Case in point about complexity: I wrote a SOAP/RPC service (a topic for another rant, but I’ll stickto my main point here). The service has a login() method, which returns a session key that is to be presented as the first argument in every other call. So, all my methods need to do a bit of access checking before they go ahead. The simple solution is to write every API function as:

ApiResult doSomething(String key, ...) {
   if (!authenticate(key))
       return new ApiResult("access denied");
   ...
}

I am the kind of programmer that thinks that “if” statements should be avoided, and if I repeat an “if” in every method in a class, my refactoring alarm starts to go off. Now, in Smalltalk, this would have a simple solution:

doSomething: key with: ...
  ^self withAuthentication: key do: [...].

withAuthentication: key do: aBlock
  ^(self authenticate: key)
    ifTrue: aBlock
    ifFalse: [Result newWithMessage: 'authentication failed']

A complete no-brainer with mostly similar solutions in Python, Perl and Ruby (to name some other dynamic languages).

I will spare you the code, but my first attempt was to use an anonymous inner class as a work-around for Java’s lack of closures. The result was much worse than the original code, enough to dub Java “LISB” (Lots of Irritating Stupid Braces). I got rid of the “if” statement, but at a price I was not willing to pay.

The other possibility was to use Aspect/J. Aspect-oriented programming is actually a nice idea, but not in Java. Aspect/J makes most of the Eclipse advantages melt away, because it becomes necessary much more often to recompile lots of classes, so Eclipse’s feel becomes much slower. Furthermore, it turned out to be non-trivial to write a so-called pointcut over methods with different numbers of arguments(depending on the API call, the method may have zero, one or two extra arguments after the initial key), and the Aspect/J list wasn’t able to get me a working example. But even the non-working code showed me that Aspect/J isn’t ready for mainstream yet - it slows down Eclipse too much, and the language isn’t powerful enough to express complex pointcuts and advice. After some 8 years of development (IIRC), a bit disappointing, to say the least.

Why is is that something that wouldn’t make me pause for more than 5 seconds in Smalltalk did cost me the better part of a workday without resulting in an acceptable solution? All I can conclude is that Java is a great language for two groups of people in an organization:

  1. Project managers - they need to manage double the number of developers, which means probably quadruple the amount of complexity. More work, more pay
  2. HR people - it’s easy enough to satisfy the requests of the previous group, because every code droid out there has sat through some kind of Java certification

But I still wonder what it does for the actual coders…


Stumble it!  Post to del.icio.us 

19 Responses to “Java still mostly sucks. Film at 11”

  1. Howard Stearns Says:

    Hi Cees. Nice examples. Thanks, I’m sure I’ll use them.

    Your #withAuthentication:do: is very cool, and can be changed slightly to include the cases where the do block also wants access to key for some reason. But how do you handle existing code where you can’t easily change all the call-sites to use #withAuthentication:do:?

    Some of the creators of AspectJ were pioneers in multi-methods (CLOS, in Common Lisp), where one could just add a wrapper around existing code, specialized on unauthenticated keys, and leave all the existing code:

    (defmethod do-something ((key unauthenticated) arg1 arg2 arg3)
    (make-instance ‘api-result reason: “Access denied.”))

    A far more object-oriented style, in my opinion. They called it Meta Object Protocols, and Open Implemention back then. Too bad they were not able to preserve this encapsulation when they went to Java! (Ironic, given that the naive often say that Java is more encapsulated than CLOS!)

    About manager’s preference for Java: Don’t understimate non-technical factors! There’s no question in my mind that Lisp is strictly more expressive than Smalltalk. And in the project I work on (Croquet), some of the key people are probably more proficient at Lisp than Smalltalk. And yet there are other factors…. For managers in “the enterprise”, the key factors are risk/predictability. Suppose some project can be done in two weeks with 2 really good Lisp/Squeak cowboys, but in in 20 weeks with 10 completely commodity programmers. And suppose that all projects, regardless of duration, always turn out to be +/- 8 weeks of estimate (often due to non-technical factors), and 50% of all project fail no matter what you do (pick your own favorite percentage). Now, if you play poker, which bet gives you the best odds of making your goal within 25% of your estimate?

  2. Kees Says:

    Cees,
    I think there is another reason for choosing Java as THE language, because the choosing groups avoids any risk for failure. If they choose a language that not the standard, they can be blaimed.
    But by choosing “the standard”, they also avoid the risk of being more successfull than this standard.
    Recently a company -in our little country- has choosen to use not the standard, the project switched from Java to Smalltalk. The project succeeded with only 3 Smalltalk developers, while the project was at a dead end before with 15 Java programmers.
    There is a nice article about “Choosing the standard language”: http://www.paulgraham.com/icad.html

  3. Lex Spoon Says:

    Great example, Cees, but not of dynamic features. This is about higher order functions.

    Many static languages have higher order functions, too. Since you are in the Java muckland, I feel obliged to plug Scala (http://scala.epfl.ch), which meshes well with Java but removes a lot of the nastiness.

    In Scala, the method could look like:

    def withAuthentication(key: Key)(action: =>Unit) = {
    if(authenticate(key))
    action
    else
    error(”authentication failed”)
    }

    Uses of it would look like this:

    withAuthentication(key) {
    …do stuff…
    }

    Many other statically typed languages have this kind of thing, too…. just not C, C++, or Java!

  4. cdegroot Says:

    I wasn’t specifically bashing Java’s static typing system in the example, that’s right (static typing isn’t bad per se, as long as it is accompanied by a good type inference engine, IMO). Just one of the other many things that it lacks. Shooting fish in a barrel… ;-)

  5. Isaac Gouy Says:

    Surprise! Smalltalk idioms might not translate to Java.

    You don’t say what happens to the ApiResult/Result object so I guess we’re free to assume nothing interesting happens to it, and suggest that authenticate() could simply throw an exception if authentication fails.

    Or if we were actually interested in programming effectively in Java, we could go to some Java forums and ask if there was an well-understood approach for this situation.

  6. cdegroot Says:

    Ah, our resident troll again (it’s my blog, I can be ad-hominem as I like :-) ).

    Isaac, do you know my Java credentials? If not, check them before assuming that I don’t know what I’m talking about (yup, arguing from authority as well, I’m really bad tonight).

    Throwing an exception is not really an option in a SOAP service, unless they added exceptions in SOAP since the last time I checked the spec….

    (and don’t get me started about the checked exception mess)

  7. Isaac Gouy Says:

    “before assuming that I don’t know what I’m talking about”
    So what is the appropriate Java idiom for this situation?

    “Throwing an exception is not really an option in a SOAP service”
    Why?
    http://www-128.ibm.com/developerworks/webservices/library/ws-tip-jaxrpc.html
    http://ws.apache.org/axis/java/user-guide.html#Exceptions

    “and don’t get me started about the checked exception mess”
    You can whine on about checked exceptions all you like, as long as you first acknowledge that you could choose to define an unchecked exception.

  8. cdegroot Says:

    Maybe you only have intelligent, well-informed, JAX-RPC compliant users of your SOAP services. But SOAP interop is sooo bad that even simple interfaces are hard to get working, let alone trying to get my customers/data suppliers to handle exceptions. That’s why I return a value telling them exactly what is wrong.

    Indeed, in normal cases, I wouldn’t have made an issue out of this and just thrown an exception. But the issue is that if you have reasons (however valid or not or debatable) not to use exceptions, Java simply isn’t expressive enough to allow me to choose otherwise. That is the core of my point - a programming language should be a tool, not a straightjacket. Straightjackets are for fools, and I don’t like languages that treat me like I’m a fool.

    (And if I start using unchecked exceptions, the Java police will come down and hunt me :-) )

  9. Isaac Gouy Says:

    Did they add exceptions in SOAP since the last time you checked the spec? Is throwing an exception an option in a SOAP service?

    Maybe you don’t think your SOAP engine will throw SOAP faults whether you use them or not; maybe you don’t think clients will have to handle SOAP faults whether you use them or not.

    Rolling your own error values is a great way to force clients to duplicate exception handling with error value tests in their code.

    You’ve already demonstrated that Java /is expressive enough/ to allow you to ignore the normal way of dealing with error conditions - the only straightjacket here is in your mind.

  10. cdegroot Says:

    Sigh. I’ll leave it at that, Isaac. As always, you fail to see the point (being here just another example of Java’s limited expressiveness, rather than debating how my customers should write code). You shift the burden to the programmer, and if that doesn’t work, you shift it to his customers (or the requirements, or whatever), all the while refusing to see anything wrong with Java. That’s the sort of reasoning that is typical of religious converts, who end up with loads of non-falsifiable statements that you simply cannot argue against. Therefore, I won’t.

  11. Isaac Gouy Says:

    But you didn’t leave it at that, you tacked on some more personal remarks.

    Your point was that Java doesn’t allow you to refactor code the way you would refactor code in Smalltalk. That’s true - Java doesn’t allow you to refactor code the way you would in Smalltalk.
    Smalltalk idioms might not translate to Java.

    The specific example you choose to make that point with seems to have been based on the belief that exceptions couldn’t/shouldn’t/wouldn’t propagate from SOAP server to SOAP client. afaict that was a mistaken belief - was it a misunderstanding?

    “non-falsifiable statements”
    On the contrary these statements are falsifiable
    - client programs will need to handle SOAP faults
    - returning error values forces clients to use 2 separate mechanisms, one to handle SOAP faults and one to handle application error values; and we can avoid that duplication in the many client programs by signalling application errors with SOAP faults
    - if (!authenticate(key)) demonstrates that Java is expressive enough to allow you to ignore the normal way of dealing with error conditions

    Are these claims you make against me falsifiable?
    “You shift the burden to the programmer… you shift it to his customers… while refusing to see anything wrong with Java.”

  12. cdegroot Says:

    Isaac - the SOAP interface specification is a requirement. In light of this requirement, Java is not expressive enough to cleanly implement a solution. Period.

  13. Isaac Gouy Says:

    “the SOAP interface specification is a requirement”
    Here’s the SOAP spec
    http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383507

    “In light of this requirement, Java is not expressive enough to cleanly implement a solution.”
    Huh?
    Is there something about Java that prevents use of SOAP faults? (It’s really hard to understand what you mean by such an unspecific claim.)

  14. Isaac Gouy Says:

    I wonder what happens when doSomething(String key, …) throws java.lang.NullPointerException ?

  15. Isaac Gouy Says:

    I wonder if java.lang.NullPointerException is logged and swallowed. I wonder if that would be the place to catch & convert ApiException into ApiResult.

  16. Dave Newton Says:

    My impression was that the ultiamte issue being discussed was that Java doesn’t allow you to /easily/ eliminate a particular noisy syntactic construct, in this case an identical “if” statement in a large-ish collection of methods.

    Of course, you /could/ use a proxy-based decorator which could certainly handle all of these requirements, but then you need to change your code to use the decorator rather than the underlying object. It would be trivial to create a way of associating objects and methods with said decorator.

    But… that sucks. Java doesn’t allow you to easily and /transparently/ manipulate itself to get what you want without resorting to such treachery or, even worse, direct byte-code manipulation.

  17. John Says:

    Your last experience was 7 years ago no wonder working Java has become more advanced. Though I agree that working with it is not much of a pleasure.

  18. cdegroot Says:

    John - “advanced”? I’d say “retarded”, in exactly the same way that C++ retarded itself by attempting to patch all the glaring holes in the original language spec going down a dead end. Java is all about trying to apply the most complex solution to any given problem (happily assisted by the W3C, it seems, who are doing their bit at the XML end). I wonder what sort of freak construct they’ll use by the time the Java boys decide to implement higher order functions/closures :-)

  19. Cees’ Blog » Blog Archive » Java Sucks, revisited Says:

    […] In my previous Java-bashing post, people started to pick the example apart rather than comment on the fact that Java still is missing some very obvious functionality, like closures. So I won’t come up with another example . […]

Leave a Reply

(note: comments may be moderated so don't always appear right away)


Copyright (C)2000-2005 Cees de Groot -- All rights reserved.