Monday, February 8, 2010

Getting Started with JavaFx

As my last posting noted, I'm intrigued by the JavaFx language. It's being marketed as a platform for Rich Internet Applications (RIAs), in competition with Flash (Flex) and Silverlight. I don't think it's going to be successful in that space, for reasons that I'll detail in a future post. However, it might just be the next big language for the JVM platform, a functional-object language with the marketing muscle of Oracle behind it.

With that in mind, I'm taking some time to investigate the language, and will be writing a series of posts about it. I won't spend a lot of time on the GUI aspects; there are already blogs that do that, and a whole page of examples with source code. Instead, I want to point out some of the things that I think are neat about the language, and some of the roadblocks that might be in its way as a general-purpose environment.

There will be a few code snippets along the way. You can compile and run them from the command line, using the javafxc and javafx tools from the SDK. There's also IDE support for NetBeans 6.x and Eclipse. I use the NetBeans plugin, and it seems fairly solid (although there seem to be some issues with NetBeans on Ubuntu 9.04 — sometimes it stops accepting keystrokes until I switch windows). If you don't already have NetBeans, you can download it pre-configured with JavaFx, from the JavaFx downloads page (and you'll find the SDK there too).

Before diving into code, there are a couple of terms that have special meaning with JavaFx:

script
A JavaFx source file. Although called a “script,” these files must be compiled into Java bytecode, and run from within the JavaFx environment. Scripts are translated into top-level Java classes with predefined methods used to invoke the script (think of main()), along with the various methods, variables, and code defined by the script.
class
Much like a class in any other language: a definition that combines data and methods, and must be instantiated for use. JavaFx classes are defined within a script, and the compiler creates nested Java classes to represent them.

Now it's time for “Hello, World”:

package experiments.language;

println("Hello, World");

That's it. It really does look like a script: there's no boilerplate class definition, no public static void main definition. Even the println() statement gives no hint that it's actually implemented by the class javafx.lang.Builtins.

All of this, however, is simply syntactic sugar: you could easily write a precompiler that takes a similar script and adds the boilerplate Java code. I'll leave you with something new, however: inline variable substitution, a la PHP:

package experiments.language;

def addressee = "World";
println("Hello, {addressee}");

Thursday, February 4, 2010

Book Review: Essential JavaFx

I recently received a copy of Essential JavaFx as book give-away at my local Java Users Group meeting. The JUG receives such books directly from publishers, with the expectation that JUG members will write reviews. My review of this book follows; I suspect that Dave won't be sending it back to the publisher.


My bookshelf holds a dog-eared copy of The UNIX C Shell Field Guide, written by Gail and Paul Anderson in 1986. To me, it represents the perfect mix of tutorial and reference, presenting an enormous amount of technical detail in a careful progression. Unfortunately, I can't say the same for their book Essential JavaFx: the material is disjointed, skimming the surface of many topics in seemingly random order, without truly examining any of them.

This book begins, as nearly all programming books do, with a simple “Hello, World” example. This part is, in fact, a little too simplistic: it walks the reader through specific screens and buttons of the NetBeans IDE. The actual program appears only as a screen-shot, without explanation of its structure. For a book that is targeted to an audience with “some previous programming experience,” this is disappointing: I want to see the program, not the IDE.

Chapter 2 attempts to remedy that initial surface treatment, by presenting a relatively complex example application. And it starts well, with a description of the way that a JavaFx application is built around a “scene graph,” and the admonishment to “think like a designer [...] visualize the structure of your application.” But then, it dives into variable definitions and control constructs, without so much as mentioning how they fit into the scene graph. And from there, the same chapter touches on accessing Java classes, visual effects, lazy expression evaluation (not identified as such), and animations &mash; a few paragraphs or pages for each, without explanation as to how they might fit together in an application.

Chapter 3 is a whirlwind treatment of the core JavaFx language. And there is a lot to this language: it is far closer to Scala than to Java, with influences from Python. Indeed, I could envision an entire book exploring the effective use of these core language features, perhaps even ignoring the GUI.

The subsequent chapters are much the same: quick hits without real content. Chapter 6, “Anatomy of a JavaFx Application,” is the closest that we get to a step-by-step tutorial, yet even here the Andersons forget their early advice: rather than starting with the application structure, they immediately create component subclasses, and only later assemble them into a scene graph.

In the end, I put the book down and turned to my IDE and “experiential learning.”


So, not so great a review of the book. But the language looks fascinating, and I plan to spend time working with it over the next few weeks. My first impression is that it might in fact be “the next big language” for the JVM: it seems to be a nice combination of strong typing, declarative configuration, and functional/object execution. I'm wondering if, like Java before it, JavaFx might be introduced to the world as a GUI language, yet end up as a language for server-centric applications.

Friday, January 29, 2010

Micro-Optimization is Easy and Feels Good

Have you ever seen code like this?

private String foo(String arg1, int arg2)
{
    StringBuilder buf = new StringBuilder();
    buf.append(arg1).append(" = ").append(arg2);
    return buf.toString();
}

If you ask the person who wrote this why s/he used a StringBuilder rather than simply concatenating the strings, you'll probably hear a long lecture about how it's more efficient. If you're a bytecode geek, you can respond by demonstrating that the compiler generate exactly the same code. But then the argument changes: it's more efficient in some cases, and is never less efficient, so is still a Good Thing. At that point it's usually easiest to (snarkily) say “well, you should at least pre-allocate a reasonable buffer size,” and walk away.

These arguments are not caused by the time quantum fallacy. The StringBuilder fan recognizes that different operations take differing amounts of time, and is actively trying to minimize the overall time of his/her code. Never mind that, in context, string concatenation is rarely a significant time sink. The rationale is always “it can't hurt, and might help.”

This is the same attitude that drives curbside recycling. It feels good to put an aluminum can in the bin: the can can be melted down and reused, saving much of the energy needed to smelt the aluminum from ore. Doing so, however, avoids the bigger questions of whether aluminum is the most environmentally sound packaging material in the first place, or whether you should even be drinking the contents of that can.

In the same way, micro-optimizations let you feel good while avoiding the bigger question of what parts of your code should be optimized. Experienced programmers know that not all code should be optimized: there's an 80-20 (or more likely 90-10) rule at work. But finding the 10% that should be optimized is, quite frankly, hard.

It's not that we don't have tools: profilers of one form or another have been around since before I started working with computers. Java has had a built-in profiler since at least JDK 1.2, and a good profiler since (I think) 1.4. For that matter, some carefully placed logging statements can give you a good idea of what parts of your code take the longest (just be sure to use a logging guard so that you're not wasting CPU cycles!).

The real barrier to profiling — and by extension, intelligent optimization — is coming up with a representative workload. “Representative” is the key word here: you can write a performance test that spends all of its time doing things that your real users never do. Even when you think that you know what the users will do, it's tempting to take shortcuts: to profile an eCommerce application, you might add 10,000 items to a single cart. But the optimizations that you make after this test could be meaningless if the real world has 10,000 carts containing one item. And even if you get that right, there may be different implications running on an empty database versus one that has lots of data.

So yes, it's hard. But ultimately, the brain cycles that you spend thinking about representative workloads will have a greater payoff than those you spend thinking about micro-optimizations. And the end result feels better too, much like foregoing a can of soda for a glass of water.