Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Does JavaFX promote excessive mutability? And why is it so rigid at the same time?

 
Tom Nielson
Ranch Hand
Posts: 53
2
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've been doing serious Swing development for the past two years, and grew to appreciate that platform. But I'm not thrilled with the lack of visual customization, so I'm readying to transition to JavaFX 8.

I like JavaFX 8 and all the controls and visual customization it offers. But I am not quite sold from a data model architecture standpoint. Everything in JavaFX only works with Observable properties and collections. I get the advantages of bindings and everything. But what if I am fond of using Immutable Collections? What if I like my core business logic classes that do not support just GUI's but also processes to not have Observable properties?

I can certainly work around this and try to create observable wrappers around my non-observable classes, but it just feels awful messy. If I have a singleton list of immutable Airport objects that I want to project into a TableView, I have to first make all the properties of Airport Observable, and then I have to wrap the Airport objects into an ObservableList. Or in the TableView, I have to create a ReadOnly wrapper.

It almost feels like you are forced to make things mutable via Properties. Yeah there are many tools that mitigate the risks of mutability like binding, but Swing just feels so much easier especially with JTable. You want a value at a row and column, it returns a value at that row and column. If you edit a value at a row and column, you intercept that edit and do something with the new value (usually I wrote that value against the database and re-imported the immutable objects from that table).

I guess my question is... if I don't drink the Observable/Binding framework KoolAid, am I not going to enjoy JavaFX until I adapt to them?
 
John Damien Smith
Ranch Hand
Posts: 299
15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
> What if I like my core business logic classes that do not support just GUI's but also processes to not have Observable properties?

Might be a good use-case for the javafx.beans.property.adapter classes.
Or perhaps try an MVVM model (yeah, I know that link is WPF not JavaFX, but hopefully you can get the gist of it - and you probably already know MVVM anyway...).
Some of the utilities in DataFX may help you.

> I can certainly work around this and try to create observable wrappers around my non-observable classes, but it just feels awful messy. If I have a singleton list of immutable Airport objects that I want to project into a TableView, I have to first make all the properties of Airport Observable, and then I have to wrap the Airport objects into an ObservableList. Or in the TableView, I have to create a ReadOnly wrapper.

From a naive point of view, it doesn't seem too tricky to me. Maybe post an example (in a new thread here or on StackOverflow under the JavaFX tag) with the code which does this and it will be easier to see just how messy it is or what compromises are made or to suggest potential optimizations which might make it less messy.

> It almost feels like you are forced to make things mutable via Properties.

I don't think you are forced to. Certain things (such as setting up UI bindings) are definitely simpler if you have observable properties.

> but Swing just feels so much easier especially with JTable.

Sometimes what is familiar seems easier. (I have never written much Swing code, so it could indeed be easier with Swing...).
It is also possible that additional API could be added to the JavaFX core or a third party library which emulates or surpasses the ease-of-use provided by Swing in this regard.
There may also be tradeoffs between ease of use and flexible functionality which might not be readily apparent at first glance.

> what if I am fond of using Immutable Collections?

The standard collection type used throughout JavaFX is the mutable ObservableList - I don't think you have any option other than to use it.

I like immutable stuff too - it makes programs easier to reason about. It is especially useful when dealing with concurrency - though that is less of an issue in a system which is single threaded from an application developer standpoint (such as JavaFX). Still, even in single-threaded environments, having stuff immutable by default can make your life easier.

> if I don't drink the Observable/Binding framework KoolAid, am I not going to enjoy JavaFX until I adapt to them?

Perhaps not. Use of properties is pervasive to the core JavaFX API. Even if you don't use properties and bindings directly in your app code, you still need to code against the core API which does use such things all of the time. You can probably get away within your app code with plain java objects and immutable ones at that, but you may need to use beans adapters on your app objects and listeners on the JavaFX API properties to allow reasonable interaction between your app code and the JavaFX API.

----

In the end, the observable/binding framework of JavaFX is programming by side-effect, which has inherent risks in difficulty of understanding and reasoning about program state and the potential scope and impact of changes to property values - especially in larger programs. Because there is high potential for side-effects, it is important for the app developer to understand the impact of a change. For example, if you change a string property in a concurrent task and that string property is bound to label's text, that change to the string property can trigger a change to the label text which violates a JavaFX threading rule of not updating properties of the active scene graph off the JavaFX application thread. In practice, I have found that the observable/binding model seems to work well and appreciate its implementation in JavaFX, but opinions on that may vary. For small programs the side-effect based model works fine...

Even though it seems simple, be careful with things like laying out controls based upon binding calculations beyond very simple layout rules. The preferred method for layout in applications is to use built-in layout managers and set layout constraints on the layout managers and their child nodes. If this preferred method does not get you the customization you need, instead of using lots of bindings, subclass region and override layoutChildren() and perform layout there (that technique is used extensively in the internal JavaFX implementation - though it is not documented in tutorials for developers that I know of).

Use of immutable data is quite prevalent in functional programming techniques. Functions work best and are easier to reason about without side-effects. One of the things which can make functional programming great is it's prevalent lack of mutable state, for example using a map function from one immutable list to another rather than a for loop with a mutable counter that modifies values inside a list. On the other hand, GUIs are often built on changing data - so there is a bit of an impedance mismatch, as typified in this question: Clojure: how to architect desktop UI in which the question author posits creating an application which uses JavaFX for the UI technology (wrapped in Clojure) but relies as much as possible on immutable state within the application object model (and there are no good answers to that question).

----

One issue with JavaFX, is that it may not provide out-of-the-box the optimal level of functionality for its binding/observable setup. Perhaps take a look at ReactFX, to see how the in-built setup can potentially be enhanced. Though if you don't like bindings/observables, you may not like ReactFX either...
 
Tom Nielson
Ranch Hand
Posts: 53
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow, awesome answer thanks. Change or die, right? Fortunately the read-only wrappers are not so bad when I realized I was looking at JavaFX 2 examples, and not leveraging lambda expressions for the cell value factories.

I'll need to check out these libraries you listed. I also created my own implementation of ObservableList that wraps around an ImmutableList (and you can swap in a new ImmutableList by calling the "set()" method to refresh the data). I think I can adapt.
 
Tom Nielson
Ranch Hand
Posts: 53
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One quick question though... I was messing around with the JavaBeanBooleanProperty and there seems to be a lot of reflection involved. Would this hurt performance for a high volume of objects? I'll need to dig deep into this and try to fully understand...
 
John Damien Smith
Ranch Hand
Posts: 299
15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
> Change or die, right?

LOL, nice summary.
But yeah, true, things like properties and CSS are so deeply embedded into JavaFX, that either you learn and use or adapt to them or you don't use JavaFX.

> I was messing around with the JavaBeanBooleanProperty and there seems to be a lot of reflection involved. Would this hurt performance for a high volume of objects?

Indeed there is. And yes, reflection is a killer for very high performance if used extensively. It may or may not be a factor in your application, you will need to benchmark to see.

The other thing in JavaFX which uses a lot of reflection is the FXML loader. If you load very large FXML documents (e.g. 1000 elements), then performance is not great because it runs lots of reflective calls - it might take a second to load such a document. Eventually, the JavaFX team might offer an alternative to the runtime load function of text based FXML documents and provide the capability to have a template pre-compiled to byte code which does not rely on reflection (similar to the existing css=>binary converter).

 
Tom Nielson
Ranch Hand
Posts: 53
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I gave some very serious thought since your last post, even to a philosophical level. I think I've come to terms with how JavaFX is designed.

Programming "purists" are a funny bunch because coding standards are relative. Singletons were the rage at one time, now they are frowned on because they derail decoupling and testing efforts. Reflection still gets hate by many veteran developers, and yet some of the greatest Java libraries (like Guava and Guice) use it heavily. I'm sure there are OOP-purists who were against functional programming being put in Java. Unless you are writing C, assembly code, or binary, nothing is really purist when you are using high-level frameworks and tools built by others (like the Java language)... and those tools and frameworks will naturally change to meet shifting business demands.

Anyway, I digress. The core of what bothered me with JavaFX is the Property looking like more boilerplate. I was saying to myself "I have to create a getter, a setter, and now a Property getter? How many methods do I need to manage just one property!" I saw myself needing to do that to every single property to the hundreds of classes I built. But then again, in a GUI environment, much more boilerplate would be needed to keep a checkbox in sync with a backing boolean property. That makes the Property not look so bad (even advantageous), and encapsulation makes it easy to refactor that into the getter and setter method. In the end, mainly the mutable or strategic properties need to become Properties. Everything else, especially items in the TableView, can be wrapped in read-only wrappers.

GUI's are the core of the business I do. Everything else, including processes, are secondary to support the GUI's. It does not hurt to make mutable properties into Properties, even if they are not always used for GUI tasks. So I think I see the advantages here now.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic