Saturday 14 April 2018

JavaFX out of Java 11

In somewhat recent news Oracle has moved JavaFX out of the standard Java install from Java 11. There is a certain fun that Donald Smith describes this as "making JavaFX easier to adopt by making the technology available as a separate download" — don't you always find having to download two things instead of one makes things easier... but that's not really what I want to chat about here.

I teach a couple of university courses that have usually used JavaFX: one in distributed software development, and another in functional programming in Scala. Not because we're particularly teaching UI programming, but because there are plenty of occasions where you're not teaching UI programming but still want students to be able to put something on the screen easily. It's in that context I'd like to say a little about JavaFX — the good, the bad, and the ugly.

I should perhaps also mention that I think that realm — just being so much easier — was Java's best route to being a relevant client technology again. I have this thing I need to knock up, do I set up npm, bower, etc, to do it in Electron -- nah, it's just a small thing at the moment, I'll just whip it up in JavaFX. And then just having a smooth progression where there just isn't a point where it feels uncomfortable to write your program in this toolkit. This is also where JavaFX didn't quite get it right.

Ok, enough rabbiting about the space I'd like Java UIs to sit in. How did JavaFX fare in my experience?

The good

The scene graph in JavaFX managed simplicity very well. I have a fairly common little demo that I write live in front of students for showing the concept of threads (as their Java unit doesn't always cover it). I put a spinning rectangle above a button, and have the button's action listener put the thread to sleep for 10 seconds. Instant frozen rectangle. Then we move the task onto a background thread, and the UI doesn't freeze. Five minutes, about twenty lines of code, gets the point across pretty well.

Hidden in there, of course, I'm doing some things Swing never really let you do. Mixing a shape primitive in a scene graph with controls (buttons). And as the rectangle spins its dimensions change but I don't have to worry about its drawing being clipped by its bounds. And the VBox I put them in just goes into the component graph, I don't have to deal with setting layout managers.

The bad

There's two places I think JavaFX fell down:

  • Both times they created it (the old JavaFX 1 in JavaFX Script, and JavaFX 2), they had far too particular a model for how you'd do your UI. JavaFX 1 dictated what language you worked in. JavaFX 2 didn't, but see below with the observable lists, it very much packaged the programming model into the controls. It didn't have the neat separation that HTML5 does -- that the scene graph just does displaying the scene graph, and you can chop and change different frameworks for how you tie your data model to that.
  • It tried to be too deep. Style your UI with CSS! Underlying every control there's a complex region model that lets you style multiple regions in every control! While this looked fun if you were really very interested in JavaFX, it meant that if you opened up the API documentation there was just so much of it. Separating what you could ignore from what you couldn't became a task for the reader, and it just looked scarily big for students that just wanted to whack some buttons, a canvas, and a graph on the screen.

The ugly

The part my students really found awkward was the controls. In 2017, I set the Scala students an assignment of writing a particle swarm optimiser. So that they could see it working, I also asked them to show various properties of the swarm at each frame of the simulation. That was supposed to be just a little prod in the assignment so students could easily see what was happening -- but it turned out they found writing the UI much harder than writing the particle swarm. Let's just highlight that for a moment:

A functional programming assignment, in Scala (a famously large language for students to get to grips with), and it turns out the fiddliest part is getting the UI to show some simple graphs on-screen. Hmm...

I think the issue there was that JavaFX's controls model is quite so deeply married to its observable lists. For students who are quite happy calling map on a sequence of values, to update them in one fell swoop, having to deal with code that says:

series.getData().add(new XYChart.Data(1, 23));

starts to looks weird. No, I don't want to get the data, I want to add a datapoint.... It's not that it's a lot of code, it's just that JavaFX imposes an opinionated mental model for how data in a UI should be updated, and if that's different to how you write the rest of your code then it's asking you to jump mindsets when you touch the UI parts of your code.

Where too next?

From outside Oracle, it does look like JavaFX has been put out to pasture. I used to have a cynical saying that when companies and governments fund projects, one of the things they really like about open source is that "we've released it to the open source community" sounds so much more successful end to a project than "we've dropped it like a stone".

Which is unfortunate, as in reverting to just supporting Swing until 2026, we've lost the simpler parts of JavaFX. The scene graph that just let you chuck shapes into VBoxes. Letting you paint outside your control's bounds if you want, so you can do things like have a row of buttons, but highlight one for some help text by circling it or making it wiggle. The slightly neater animation classes too. We've fallen back in time ten years to when the toolkit still got in the way for the simple but visually interesting stuff.

So what I'd like to see happen with JavaFX is for it to be modularised, rather than it being a big fat module put out to grass. For Oracle to back the scene graph to the hilt, and make sure you can add one dependency in gradle, and you'll get a really simple toolkit for putting together attractive little UIs, with the elementary controls such as buttons and text fields. Put the complex controls out to libraries, but putting some buttons and a canvas on screen, and making a button do a little dance so you can draw attention to it shouldn't be hard.

And, as seems to work for html, the frameworks can deal with different ways of tying data to code. The react-like ones that let your code appear relatively pure, and then do a diff on what's in the code. Or the reactive ones that treat every property like an observable that automatically updates its controls when you do. Or the d3.js like ones that treat it as sets of data that are new, changed, or removed. etc.