Proposal: Deprecate Builders

Sven Reimers sven.reimers at gmail.com
Mon Mar 25 12:24:12 PDT 2013


Disclaimer: I am a casual user of builders..

So one part of the argument is the question: Does it make sense to offer
the builders as part of the JavaFX API (and with that as part of a future
JSR - staying backward compatible)?

>From my point of view I would say anyone can create a JavaFX 8/9 whatever
compatible builders as a separate jar-file.

So I think Richard is right - get rid of them officially - there are enough
other options.

-Sven


On Mon, Mar 25, 2013 at 7:46 PM, Jonathan Giles
<jonathan.giles at oracle.com>wrote:

> I fall into the camp of never using builders in my projects, so I won't
> feel impacted by the move. However, I know a lot of people do use them, and
> I wonder whether another option is to supply the builders as a separate jar
> file for JavaFX 8.x as well. This 8.x builders.jar file could use the
> flattened structure and therefore be 'proper'. This file would be a
> separate library that developers can download and use, as is common in the
> Java world. The benefit is that people who don't use builders will never
> have to see them (or be impacted  by their cost), whilst they are still
> available for the subset of people who do prefer their usage.
>
> Perhaps the concern is the extra work required to modify the *Builder
> generator, which I can't imagine is super trivial, but assuming it doesn't
> take a large amount of time then I think this is something to consider -
> assuming people feel strongly that builders should remain in some form.
>
> -- Jonathan
>
>
> On 26/03/2013 6:35 a.m., Richard Bair wrote:
>
>> We made a mistake. When we released JavaFX 2.0 we included a (large) set
>> of *Builder classes to provide a builder-pattern approach to building
>> JavaFX UIs. The builder-pattern approach provides several very nice
>> features:
>>         - Ability to setup generic configuration once and "stamp out"
>> multiple copies
>>         - Structured code style that closely approximates the "container
>> hierarchy" of the UI
>>         - Strongly-typed "declarative" style programming
>>
>> The Builders did come at a cost. There are a lot of them, and if used,
>> require more class loading which slows down startup. When Pack200 is not
>> being used, they represent a sizable fraction of the code base. They
>> clutter up the JavaDoc (although this could be solved by having a "Builder"
>> section like there is an "Enum" section and "Interface" section).
>>
>> But all those advantages and costs were weighed and we concluded Builders
>> were worth it, and they went in. Based on the above, I would still conclude
>> that Builders are OK. However, it turns out our implementation has some
>> intractable problems with respect to binary compatibility.
>>
>> In order to ensure our Builders are always up-to-date with the latest API
>> added to the core classes, the Builders are auto-generated using an
>> annotation processor. Also, in order to keep the size of the builders small
>> relative to the rest of the platform, we employ complex use of generics in
>> order to allow the builders to inherit. That is, ControlBuilder extends
>> from ParentBuilder extends from NodeBuilder just as Control extends from
>> Parent extends from Node. But accomplishing this was no easy feat. Although
>> the "id(String)" method is defined on NodeBuilder, it must return a
>> ControlBuilder when used from the ControlBuilder. All of this was
>> accomplished using generics, and as it turns out, depended on two bugs in
>> JDK 6 and JDK 7 in order to work (although we didn't know it at the time).
>> Those bugs were fixed in JDK 8, and as a result, the builders no longer
>> work correctly for certain cases. Just about any option we take is going to
>> lead to a binary incompatibility in 8, however we find this unacceptable.
>> If we cannot avoid it, then whatever we choice we make for 8 had better be
>> a final solution -- not something we will later decide we need to tweak
>> further.
>>
>> And this is what puts us in a tight spot. After having painfully looked
>> over all of the alternatives, it seems to come down to this:
>>         a) Flatten the builder hierarchy so that ControlBuilder extends
>> Object the same as ParentBuilder would and all other Builders.
>>         b) Stop using builders. Phase them out in a controlled manner.
>>
>> Option (a) works because we remove all generics from the equation. There
>> are some 73 or so methods on NodeBuilder. These would be redefined on the
>> Builder for each class that extends from Node. This solution works by
>> solving the root problem -- generic use in builder subclassing scenarios.
>> This solution however changes the cost/benefit analysis for Builders,
>> because now they would then comprise a much larger fraction of the overall
>> platform size. And this runs at cross purposes with embedded use cases.
>>
>> Option (b) works by removing Builders from the scenario entirely. Because
>> this would be a *huge* breaking change, it would have to be managed
>> carefully in a way that, in fact, won't break anybody (for at least several
>> years). To implement this option, we would:
>>         1) Add @Deprecate to all Builders with a URL in the description
>> to a page describing the change and how to migrate
>>         2) Stop auto-generating builders. We'd take whatever we had in
>> the latest 2.x line and reuse them as-is.
>>                 - This means that as new API is added to the platform,
>> the builders wouldn't be updated to match
>>         3) Remove the Builders from the Java 8 JavaDoc
>>         4) Split the builders into a separate jar from jfxrt.jar. It
>> would also be on the java.ext.libs path so that it is automatically picked
>> up so that people are not broken when running FX 2.x apps on 8.x without
>> modification. They'd still work.
>>         5) Provide a download link to the fx2-builders.jar containing all
>> these builders.
>>         6) Encourage people to use fx2-builders.jar instead of relying on
>> builders being on the class path by default
>>         7) In Java 9, remove the builders from the class path (this is
>> several years down the road)
>>
>> This proposal is essentially saying that the fix to make Builders work
>> correctly reduces the value of the builders to the point where they just
>> aren't worth it, and when considering Mobile / Embedded use cases, the
>> extra cost of the builders is prohibitive. It also is based on the theory
>> that the Builders are not being used by everybody, and so many people would
>> not be negatively impacted but rather only positively impacted by no longer
>> paying for the additional cost in bytes for the builders. It also
>> recognizes that people who *are* using the builders and *do* like the
>> programming style (including Jasper and many of our own) will see a loss of
>> functionality that they have grown to like.
>>
>> The other thing to bear in mind is that most of the benefits of Builders
>> don't have to come from Builders -- there are alternatives. For example,
>> the 'Ability to setup generic configuration once and "stamp out" multiple
>> copies' benefit can also be achieved by helper methods.  The 'Structured
>> code style that closely approximates the "container hierarchy" of the UI'
>> advantage can be accomplished using FXML instead, or by using this pattern
>> (which creates a boat-load of inner classes so it has its own problems):
>>
>> // The first set of braces defines it as an anonymous subclass, the
>> second set as an initializer
>> Group g = new Group() {{
>>      getChildren().add(new Button() {{
>>          setText("Hello");
>>      }});
>> }};
>>
>> Another option which we've discussed a bit is whether we could use
>> lambda's to do configuration in a builder-like style in Java 8, somewhat
>> like Groovy does. So for example:
>>
>> Group g = new Group(gg -> {
>>      gg.getChildren().addAll(new Button(b -> {
>>          b.setText("Hello");
>>      });
>> });
>>
>> This approach doesn't generate the mass of anonymous inner classes that
>> the other double-brace approach does, but accomplishes the same basic job
>> of using builders for (more or less) declarative construction of a
>> container-hierarchy in code.
>>
>> So this is the long and the short of it. Eva can follow up with an
>> in-depth post about the binary compatibility concerns if you wish. My
>> proposal after having weighed the options is to phase out the Builders by
>> deprecating them in 8 and removing them from the class path in 9. I believe
>> that FXML or Lambda's or alternative languages all provide other avenues
>> for achieving the same goals as builders but without the additional cost in
>> byte codes or classes.
>>
>> We have some cases where SceneBuilder is presently relying on the
>> Builders, and we'd have to provide alternatives for that functionality it
>> is presently using (such as annotations for constructor arguments).
>>
>> Richard
>>
>
>
>


-- 
Sven Reimers

* Senior Expert Software Architect
* NetBeans Dream Team Member: http://dreamteam.netbeans.org
* Community Leader  NetBeans: http://community.java.net/netbeans
                              Desktop Java:
http://community.java.net/javadesktop
* Duke's Choice Award Winner 2009
* Blog: http://nbguru.blogspot.com

* XING: https://www.xing.com/profile/Sven_Reimers8
* LinkedIn: http://www.linkedin.com/in/svenreimers

Join the NetBeans Groups:
* XING: http://www.xing.com/group-20148.82db20
* NUGM: http://haug-server.dyndns.org/display/NUGM/Home
* LinkedIn: http://www.linkedin.com/groups?gid=1860468
                   http://www.linkedin.com/groups?gid=107402
                   http://www.linkedin.com/groups?gid=1684717
* Oracle: https://mix.oracle.com/groups/18497


More information about the openjfx-dev mailing list