I’ve read in a number of developer blogs I respect why Java sucks. These comments range from how Java’s UI tools suck to comments on how irrelevant Java is to Mac development. Apple has deprecated the Java to Objective C bridge in MacOS X v10.4, and the presumption that somehow third party software won’t be allowed on the phone means that Java must not be on the iPhone.
While there are a number of very valid points, I think part of the problem I have with some of the arguments boil down to this: yes, there are serious problems with Java AWT. There are problems with Java Swing. It’s clear that the whole notion of a “look and feel manager” bites the big one–perhaps on Linux where look and feel doesn’t matter, but on MacOS X and on Windows you bloody well better look like–and work like–a MacOS X or Windows application.
But it is worth noting that creating an application in Java that looks like a MacOS X or a Windows application on those respective platforms is not impossible. In fact, it’s not really all that difficult, so long as you observe a few simple rules. It’s significantly less difficult than writing a MacOS X application in Objective C using Cocoa then porting that application to C++ on MFC for Windows.
Second, while Java has its problems, it’s not like other application frameworks (what Jens Alfke mischaracterizes as an “operating system”) are easy to use or provide a comprehensive platform in which to write applications.
Completeness and Simplicity
To better illustrate what I’m trying to get at, it’s best that we draw a graph. On the horizontal axis we show complexity from left (the API doesnt’ to very much for you) to right (the API does everything you’d want and then some). On the vertical axis we’d plot simplicity from bottom (the API is a royal pain in the ass to use) to top (creating an application can be done by a near moron). Of course it’s easy to create something simple that doesn’t do much, and it’s easy to create something complex that is impossible to use. The sweet spot is finding something easy that does everything. And while the Apple Macintosh does an incredible job of hunting for and finding that sweet spot, it’s not as cut and dry as “Cocoa rules, Java sucks!”
Of course “completeness” and “simplicity” are rather subjective–so of course you may not place things where I do. But it is useful to place them in the middle rather than grouping everyting in the far upper right and the far lower left–which is what the fanboys (both pro and anti-whatever) tend to do.
When the Macintosh first came out, there were no controls; no views or subcomponents within a window which you could create in a modular fasion like you do with CWnd (MFC) or NSView (Cocoa) or JComponent (Swing) today. Instead, you were given the entire window to draw–and it was up to your code to determine what went where.
It was this sort of primtivism that motivated me to write YAAF more than a decade ago: YAAF started essentially as a C++ framework to do exactly two things on the Macintosh. First, it provided a way to easily map from an update event in an EventRecord returned by GetNextEvent (back then we didn’t have WaitNextEvent–and we had to walk uphill both ways in the snow) into an XGWindow object representing the C++ representation of my window. Second, it provided a tree-structure of XGView objects which allowed me to break up the content area of a window into logical subcomponents which would allow me to write things like a small class representing a horizontal ruler.
On the Macintosh other more popular frameworks proliferated: PowerPlant from Metrowerks and Apple’s MacApp were two of the best known.
Today this notion of drawing the entire window as a single unit seems rather silly: just subclass CWnd or NSView or whatever, override the OnPaint or Draw or Paint routine, grab the drawing context object and draw your ruler or drafting area or whatnot. But with the original Macintosh operating system (pre System 7), you just had everything from the bottom of the title bar on down as a single, unitary blank slate–and no code support to segregate the contents into manageable units.
(One exception was the original dialog boxes, which defined a control object–but you weren’t supposed to misuse the Dialog Manager and Control Manager for general windows. And it didn’t work too well.)
When Microsoft Windows 95 arrived on the scene it brought two things: from the Windows v3.0 world it brought the notion of a ‘window’ object hierarchy, with windows within windows. (Hense, the product name “Microsoft Windows.”) So instead of having to build one single window to draw the rulers, toolbars and controls contained by a single top level display window, you could break it into separate window objects with their own clipping regions. (In Microsoft Windows, a control (check box, radio button, etc) are all represented as custom windows in this manner.) And Windows 95 also introduced for the first time in the consumer level the notion of a flat (32-bit) address space.
This makes Win32 much easier to use than Mac OS (System 7)–though even back in the Mac OS System 6 days such things as handling color spaces and fonts were far easier than on Win32. (To date Windows still doesn’t have a decent bitblit that matches the power and functionality of Carbon’s CopyBits, and handling fonts in Windows is like pulling teeth.)
Even so, Win32 still was a pain in the ass to use. Windows were specified by custom window procedures (WinProcs) and there was no good way to store windows-specific data in a window. Further, when you really get right down to it, the right model to represent user interface elements is object-oriented programming: using individual programmatic objects to represent individual display objects. So Microsoft created MFC, which started life as a very thin wrapper around the Win32 API to map window procs and window handles into C++ objects. (Since then MFC has grown, expanded, morphed, and has been remapped several times for no better reason that I can see than Microsoft’s own “full employment for programmers” law, which means Microsoft has no less than a half-dozen different frameworks which do roughly the same thing.)
Throw into this mix NeXT, which built its own application framework–learning the lessons of Microsoft and Apple but making their own–and we arrive at today’s Macintosh verses Windows situation, where MacOS X Cocoa is definitely more complete, but perhaps only a hair easier to use. Both have automated layout tools, but Cocoa makes the mistake of flexability in message handling where a simple “chain of command” would do–while Windows is saddled with legacy APIs which are quite thoroughly broken. (For example, why should I have to map a DIB to an in-memory device context prior to performing a stretch blit–carefully keeping track of each of these objects so I don’t leak a damned thing–when all I want to do is load and draw a bitmap?)
Into this mess we need to toss Java, the language that was originally advertised as The Answer–but, like the other famous answer 42, no-one really knew what the question actually was.
Java was, of course, saddled with lots of programmers who felt they were striking out new and uncovered country–and rushed in to stake their claims regardless of their qualifications to actually do the job right. While the core Java RTL (java.lang, java.util) aren’t that bad–though they’ve been refreshed quite a bit since Java v1.3–the first useable version of Java–there are many parts of Java that are poorly designed (java.io) and parts which have no business whatsoever being designed in such an awkward way. (javax.naming) Then there are things which no serious experienced Java programmer would touch with a 10 foot pole, but would rather rewrite from scratch or use a third-party library instead. (I’m looking at you, java.util.logging. I mean, what the hell?)
In the early days Sun thought of Java as the “Internet Language.” The whole idea was that we were going to have these ‘net agents’ which could crawl around the network in some unspecified way and do some really cool–but unspecified–tasks for us. The ultimate goal, so the futurists told us, was that we would somehow start up some sort of ‘agent software’ which would crawl around jumping from computer to computer searching for a way to scam tickets to the latest rock concert. (I’m serious about that!)
And into this Sun volunteered Java as the programming language those agents would be written in. (Of course Microsoft also jumped into the fray by desiging Windows to be sufficiently open enough for these ‘agents’ to jump onto the computer to do really cool things–which has opened a hole large enough to make Symantec one of the five biggest software companies in the world by selling software which attempts to close this ‘agent’ (read: virus and worm) hole.)
Of course one of the things that an agent needs to do is display simple results–and so Java AWT was born as a means for a Java application to display simple information on a web page. This ‘simple’ then grew–to eventually make it “theoretically” possible (and I use the term “theoretically” rather liberally here) to create a full-blown application. Frankly, though, no-one really cared if Java could be used to build an application–Java was all about agents scamming tickets to the next Rush concert for its programmers.
And AWT sucked. Sure, it provided more functionality than System 7: LayoutManagers, as bad as they are, are a sure sight better than having no layout managers because you’re responsible for drawing the entire content area of the window without breaking the problem down into manageable components, but frankly AWT is a royal pain in the ass to use.
At some point the folks at Sun figured out that their Java agents weren’t going to reach out across a 9600 baud modem and scam tickets to Oingo Boingo for their programmers, and adrift the 49ers of the Java gold rush sought out to create a new framework, Swing.
In terms of simplicity Swing is quite a bit harder to use than MFC or Cocoa. There are no layout tools, and Swing suffers the problem of handling layout by using LayoutManagers–if only because no-one has figured out how to satisfy the desparate problem of arranging controls in a dialog box which preserve the correct look and feel on MacOS X and Windows. (Linux, on the other hand, solved this problem of desparate look and feels by setting the bar so damned low that people huddle around their screens like cavemen used to huddle around fire, marveling that the soft blue glow emitted actually manages to do something functional. So while on MacOS System 7 you could be blasted out of the water by putting your buttons 16 pixels apart instead of the recommended 14 pixels, in Linux world they were happy not to have to pop up XTerm and type cryptic voodoo-invoking magic.)
But Swing is a sure sight better than Win32 for creating applications, and it is a marked improvement over AWT.
Sadly Swing is, at one level, not much better than my own YAAF framework’s original humble beginnings: it does give you the power to lay out the contents of a window without having to draw the whole thing. You do have the power to programmatically subdivide the content region into something manageable. And if you are clever enough (and aren’t afraid to crank out custom LayoutManagers like there is no tomorrow), you can put together something that does look right on a wide variety of platforms under a wide variety of font size constraints and look and feels. But for the seemingly endless list of classes and frameworks and packages, Swing provides surprisingly little functionality in a surprisingly large amount of space.
I guess Sun had it’s own “full employment for programmers” law.
Sun’s Java Swing does not provide model/view/controller base classes and it requires a little bit of head banging to figure out the magic property to get Java Swing menus up in the menu bar on the Macintosh rather than along the top of the window. (System.setProperty(“apple.laf.useScreenMenuBar”,”true”);) But it is possible.
Sadly all application frameworks suffer in some small part by the whole “full employement for programmers” act: they tend to have parts which are significantly over-engineered or contain layers of apparent simplicity rangling difficult to use elements, rather than the more difficult task of engineering simplicity from the ground up. Even Cocoa, which is much revered by many in the Macintosh world, has elements that are way overengineered–such as the whole “outlets/actions” model in NIBs, which give you the incredible flexability of hooking up user interface elements in ways that no sensible human being would ever want to do. (This is as opposed to the MFC’s method of passing unhandled window events to its container, which accurately reflects the logical way we think of events being handled–and which is the way Apple’s development tools rangle event actions by default.)
But then, writing user interface applications is a tough problem–even in the Macintosh world, where as soon as a user interface problem is resolved and a new tool built to solve that problem in a semi-automated way, a new and cooler user interface thing comes along (CoreVideo) which introduces newer problems.
And Swing does manage to solve the problem of how to write a cross-platform application that just works on any platform it is run on–though granted, it takes one hell of a lot of work to make it look right.
There are problems with Java. I’ll be the first to admit that. The only reason why I’ve specialized in as much Java code on this web site is because at work I use C++ and Win32/MFC almost exclusively–and my sample Objective C programs are just too primitive–too “hello world” to be worth posting here. And while someday I intend to repackage YAAF and my C++ efforts on Win32 and MacOS Carbon, it’s more for historic reasons, since the YAAF code is just too ancient to really be of much use. (I mean for goodness sake I started YAAF on Windows 95 and System 6!)
But it isn’t as cut and dry as “Java sux” or “Cocoa Rulz!”
Any good programmer knows to use the right tools for the job. If I’m writing code for a Z-80 microprocessor, I wouldn’t even think about looking for a Java VM–instead I’d use a mix of Z-80 assembler and C. If I’m going to write the next visually cool MacOS X application, Cocoa is the only way to go–just as if I’m going to write the next really cool WinCE app for SmartPhones, it’d be done in Win32–because .NET and MFC is just too damned heavy weight.
For cross-platform applications I’d use Java Swing–and my own mix of utilities that I’ve posted elsewhere on this site, in order to allow my Java applications to look like a MacOS X or Windows application, and not some weird reject from the lack of visual taste that is known as Linux land.