Keep your JavaFX code clean

March 5, 2009

clean_code

I’ve been dabbling with JavaFX script lately and can’t help but notice JavaFX script’s propensity for poor code hygiene. After reading Bob Martin’s Clean Code, I’m hyper aware of code cleanliness. I don’t think there are any fundamental problems with the JavaFX script, only that best practices and good standards have yet to be laid out. I’m sure there was some pretty poor Java code written back in 1995!

Before I go further, let me point out that I think JavaFX script can be just as clean as any other language. I only wish to insight the community to better itself.

Below, I’m going demonstrate how clean JavaFX script can be by transforming some example JavaFX script code that Sun ships with NetBeans into something that better adheres to the principles laid out in Clean Code. You’ll find the original code by downloading NetBeans and selecting File -> New Project, then Samples -> JavaFX -> Building Blocks -> Image -> Background Image. Hopefully the code’s author won’t take offense as none is intended!

In Clean Code, Bob talks about keeping methods small (3 to 4 lines preferably) with a single purpose. Also, he talks about naming variables better in order to eliminate superfluous comments and thus make the code inherently more obvious.

Take a look at the following code – how obvious is this code to you?

// vertical position of moving line
var y : Number;

var timeline = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames : [
        KeyFrame {
            time : 0s
            values :
                y => -20
        },
        KeyFrame {
            time : 3s
            values :
                y => 200 tween Interpolator.LINEAR
        }
    ]
};

// Visual representation
Stage {
    scene : Scene {
        content : [
            // Shows image on the background
            ImageView {
                image : Image { url : "{__DIR__}background.png" }
            },
            // Paints two moving lines
            Group {
                transforms : Translate { y : bind y } // Bind position of lines to y
                content : [
                    Line {
                        startX : 0, startY : 20, endX : 200, endY : 0
                        stroke : Color.RED
                    },
                    Line {
                        startX : 0, startY : 20, endX : 200, endY : 0
                        stroke : Color.RED
                        transforms : Translate { y : 10 }
                    }
                ]
            }
        ]
    }

    width : 200
    height : 232
    title : "Background Image"
}

// Start the line animation
timeline.play();

It’s very easy to let things run-on in JavaFX script. I find it difficult to follow such deeply nested code as its not easy to discern what goes with what.

Here’s my refactored version of the code, which in-lines very little:

def imageUrl = "{__DIR__}background.png";
def backgroundImage = Image { url: "{__DIR__}background.png" };
def backgroundImageView = ImageView { image: backgroundImage };

var verticalPositionOfLine: Number;

def firstKeyFrame = KeyFrame {
    time: 0s
    values: verticalPositionOfLine => -20
}

def secondKeyFrame = KeyFrame {
    time: 3s
    values: verticalPositionOfLine => 200 tween Interpolator.LINEAR
}

def timeline = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames: [ firstKeyFrame, secondKeyFrame ]
}

def lineOne = Line {
    startX: 0,
    startY: 20,
    endX: 200,
    endY: 0
    stroke: Color.RED
}

def lineTwo = Line {
    startX: 0,
    startY: 20,
    endX: 200, 
    endY: 0
    stroke: Color.RED
    transforms: Translate { y: 10 }
}

def lineGroup = Group {
    transforms: Translate { y: bind verticalPositionOfLine }
    content: [ lineOne, lineTwo ]
}

def lineScene = Scene {
    content: [ backgroundImageView, lineGroup ]
}

Stage {
    scene: lineScene;
    width: 200
    height: 232
    title: "Background Image"
}

// start the line animation.
timeline.play();

This code seems infinitely more obvious to me, but then again, I wrote it.

What do you think about the general hygiene of JavaFX script you’ve seen thus far? How should we better author our JavaFX script?

About these ads

21 Responses to “Keep your JavaFX code clean”

  1. Brian Says:

    Yes, I think your version of the code is much easier to understand (not to mention maintain). Perhaps the current ugliness of the JavaFX code is a result of the declarative nature of JavaFX. I have noticed similar untidy practices in other languages such as Python and ActionScript which I find quite overwhelming at times. I definitely think a more judicious use of the language’s declarative nature and adopting a more disciplined style that has more in common with established Java code cleanliness practices would definitely help developers learn and understand the language better and provide a more solid foundation for the language as a whole.

  2. Sebastian Says:

    I agree that the second version is much cleaner and much more understandable. However I cannot fully agree that this is due to the declarative nature of JFX – there are also a lot of Java programs that do not offer clean code, especially when it comes to Swing UIs (actually even looking at my own code from a while ago, I notice that many things could have been expressed in a clearer way).

    S.

  3. Nick Says:

    It’s quite interesting that JavaFX Script was developed as a declarative language primarily to let the structure of the code reflect the GUI so that the code is easy understandable. On the other hand I agree, that code like that above has the opposite effect. On the other hand the modified version does not quite reflect the GUI. I think there’s a way in between the two solutions, which both makes the code more readable but also reflects the structure of the GUI.

  4. Ken Says:

    @ Brian and Sebastian,

    As Sebastian noted, I don’t think it’s necessarily the declarative nature of JavaFX script that tends it toward unreadability. I think it’s the nested in-lining of variables that causes the most confusion.

    In Java, you would never to something like this (as least I surely wouldn’t!) (note that the blog comment ignores my spacing):

    JButton button = new JButton(new Icon() {
    public void paintIcon(Component c, Graphics g, int x, int y) {
    // do some painting.
    }
    public int getIconWidth() {
    return 16;
    }
    public int getIconHeight() {
    return 16;
    }
    });

    This is only one level of nesting, and I still consider it poor form. The icon should be pulled out into it’s own variable at the least. I realize that JavaFX script is not Java, but I think what makes code readable transcends the implementation language.

    -Ken

  5. Ken Says:

    Hi Nick,

    I don’t think that we lose the power of declarative language by pulling things out into variables. In fact, I think this makes it more obvious how the UI is structured, as you can actually read the code. The variable names provide a concise description of what they are. In-lining the content means you have read and comprehend all the code each time you want to understand what’s going on.

    How would your re-write this code?

    -Ken

  6. Maya Incaand Says:

    Speaking as a Java FX beginner who knows a bit of Java, I think Nick is right; it would be a mistake to try and turn JavaFX into Java.

    I don’t like either form of the code above; I have redone it but when I paste it in here, my layout gets messed up.

    NetBeans has an autoformat facility which is really annoying, new line for everything, even if related (they are working on it apparently).

    Brackets all over the shop so you can’t tell where a thing starts and finishes.

    Timeline{
    code
    }.play()

    is very readable/understandable if you put repeatCount and each keyframe on one line and pair brackets underneath each other with appropriate spacing.

    You only need a couple vars for this simple example; if you start putting eveything into vars/defs then you will end up with something unreadable for a more complex example because the “flow” will be lost.

    • Ken Says:

      Hi Maya,

      I would argue that you won’t be able to retain any sense of flow as examples get more complicated. That is, you won’t be able to remember what that Line or Rectangle, for example, was parented to (e.g. was it part of the outer Group or was it that HBox?). If you have a script that is in-lined and scrolls for more than a page, there is no way you’ll be able to easily follow it. Pulling things out into variables allows your final Scene definition to be compact and readable.

      -Ken

  7. Maya Incaand Says:

    Hi Ken

    I hear what you are saying but having worked through many examples by now, I don’t agree.

    The reason is that you don’t consider the code in isolation from the “picture” you are trying to create.

    If the picture is in your mind (a design) then it is very easy to remember what goes with what.I don’t have a problem with vars/defs, I would just tend to limit the use of them.

    By the way, this discussion is not limited just to vars, I saw another simple example the other day (an animated cartoon face) where the author had divided the project into 5(!) fx files (eyes,teeth, etc); I rewrote it as one and the code was much simpler to follow.

    Like I said, JavaFX is not(intended to be)Java.

  8. Brian Says:

    @Sebastian and Ken
    Yes, I think you’re both right. It’s not the declarative aspects of the language at the root of messy code. Perhaps the more verbose nature of Java forced the logical evolution to the current state of accepted form and in the absence of those syntactical barriers, the JavaFX code monkeys have been let loose and need to be rounded up again. At least that’s what occurs to me when I look at the two forms of code. Hopefully it’s not just a result of my Java brainwashing. But I still think that the same Java clean code practices can and still should apply to JavaFX, or Python or any other modern high level language and inlining should be used very judiciously.

  9. Maya Incaand Says:

    Hi Ken, Brian

    I put a png of the code here: http://drop.io/t3tqdys
    (hope it works).

    The Scene content is a pair of lines on a background image.

    The Timeline moves the lines over a 3 second interval between -20 and 200.

    Both these things can just be “read” once you are used to the syntax.

    There are just two vars, a y-coordinate and the image Url.

    I agree there should be a balance in this, I just don’t agree with you about where it should be.

    I also think this will evolve with subsequent releases of JavaFX, right now everybody is just getting to grips with it.

  10. Sebastian Says:

    @Ken

    I tend to agree. The thing is: I still deem a declarative approach to be a good thing, but only down to a certain level – burying all variables inside a labyrinth of anonymous inner classes does not seem like a good idea to me in ANY language, not just Java and JavaFX.

    @Brian

    I do not think you are blinded by Java ;) … before starting my Ph.D. and consequently started using Java only, I have been developing PHP/HTML/JS applications for some five years and still I do not like the nested structures.
    Your transformed version of the initial JFX script already shows that clearer structure is possible. I just fear, we will not see it that often in JFX applications in the next few years.

    Best,
    S.


  11. [...] you ever wonder, why JavaFX code is so ugly, with a lot of paranthesis etc.? Keep your code clean is the logical [...]

  12. Richard Says:

    I don’t like the first form because so much indentation is hard to read. I don’t like the second form because you cannot correlate code structure to visual structure without jumping around in the code.

    I think you’re right, we haven’t figured out what good style in JavaFX is yet. I think breaking everything down into def’s is ugly too. I think defining both KeyFrames separately is very ugly.

    And setting the width/height on the Stage instead of the Scene is a bad practice. Bad on us! We shouldn’t be showing examples of setting width/height on Stage instead of Scene.

  13. Ken Says:

    Hi Richard,

    Your right in that pulling out everything into defs isn’t the right answer, but I think there is a balance (one I have yet to find!). I’m sure best practices will emerge out of good solutions as we go along. I think we’ll discover, though, that nesting things much more than 3 levels deep will be untenable.

    -Ken
    P.S. I’m looking forward to the designer tool that Tor alluded to.

  14. Richard Says:

    I blogged my version of the code:

    http://weblogs.java.net/blog/rbair/archive/2009/03/keep_your_fx_co.html

    It runs between the two styles, but favors the first. Short example, so its easy to make the first form look good, so you need to produce a really horrible 3 page long example and then we can go another round and see what the code looks like :-)

    Notice that I use the more compact KeyFrame literal syntax (which I can do since there is no action function declared on these keyframes) and that goes a long way towards cleaning it up, as does using translateY instead of transforms and since the Line’s are simple they can go on one line.

  15. Richard Says:

    Hi Ken,

    I agree, going more than a few levels deep gets really bad (though I might extend it to 5 levels before I start to get lost). I think the same general problem with deeply nested if/while/for statements applies here. I suspect breaking out deep parts of the tree into separate files is probably going to win out as deep trees also tend to have reusable chunks. We’ll see I guess as we go along.

  16. Ken Says:

    Nice…I think you’ve got a good balance there.

    I’m not sure how to articulate the rules to follow when writing JavaFX script, but I do know that it should be *readable*, where readable means that I can follow the code relatively effortlessly. I think you’ve done that with your code snippet.

    Your right about a larger file being the true test – I’ve seen some pretty gnarly JavaFX script that was virtually impenetrable!

    -Ken

  17. John Says:

    For UI design Java needs a new app that is not a “text editor”.

    Java needs Interface Builder (for JavaFX / Swing + MiG layout, whatever). Not more “text editing”.

    Engineers, chip designers, artists use AutoCAD, Photoshop, Final Cut Pro, Pro Tools, …whatever — not “text editors”. Who gives a crap about the storage format for a UI? Certainly not Interface Builder users. This app is the gold standard in UI design, originally created in the 80s! Second place contenders are still far behind. For anyone interested it’s currently an XML format, before that a binary .plist format (bad for version control). The point is nobody edits .xib files by hand in a “text editor”.

    Judging by what Sun have done with the UI design tools in NetBeans it is safe to say that it is an impossibility for Sun to create anything close to Interface Builder within the next 100 years. This appears true for other efforts too. Shame.

    Thus we need a new build tool that converts an Interface Builder .xib file to JavaFX….!

    Where can such a godsend be found?

    - John

  18. Ken Says:

    Hi John,

    I agree that we need an “Interface Builder”-like tool in Java, and I’m OK with it storing the UI in an opaque file — in fact I think I might prefer opaque storage.

    However, I don’t think that there is anything to be gained by converting XIB files to Java UIs. For example, in Interface Builder, you can mark components with certain properties to change the way they render; that is you can indicate that an OutlineView should render as a SourceList, or that a button should render as a Disclosure button. These things just won’t translate, which I think makes trying to convert a XIB file to a Java UI a futile effort.

    -Ken

  19. Joseph Says:

    Why is sun focusing on a differen’t language? When they could be focusing on Java. We don’t need another scripting language. We already have to many.

    • Ken Says:

      Hi Joseph,

      While I don’t think the quality and speed are there yet in JavaFX, I *do* think that a UI centric language is much needed. Java is a general purpose language, while JavaFX is aimed strictly at creating user interfaces. Good operability between the two will be critical to the success of JavaFX. That operability is somewhat there, but not completely. The last time I checked (which was a few moths ago), it wasn’t easy to embed JavaFX code in a Java app. The reverse, however, is very straightforward.

      -Ken


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 27 other followers

%d bloggers like this: