Proposal: Deprecate Builders
Daniel Zwolenski
zonski at gmail.com
Mon Mar 25 13:50:29 PDT 2013
I think there are a few things in standard FXML that are fairly dependent
on Builders. I cant remember exactly and its hard for me to look up
currently (there's no way to browse the OpenJFX source online is there?)
but from memory often when I tried to port between FXML and code there were
magic methods not available in the code so I assumed builders were the
source.
e.g. can you create a colour in FXML directly, fonts, images? Stuff like
that. I suspect at a minimum some of the tutorials will need updating to
not use convenience builder methods.
Also, Im again guessing but for FXML to optionally use builders doesn't it
need to have a dependency on the builder class? I suppose it could all be
reflection based, avoiding the compíler dependency, but it would still be
quite weird for the core JFX code to be looking for a class that is now
effectively third party.
Who inherited FXML after Greg?
Dont get me wrong, Im in the "strip them out camp", but just making sure
all the consequences are thought through. Probably any such problems can be
fixed but only if done in advance.
On Mon, Mar 25, 2013 at 9:31 PM, Richard Bair <richard.bair at oracle.com>wrote:
> Ya it was a good read (thanks Ali). I think Michael does a good job
> recounting the problems with this approach. I wouldn't use generics for it
> (I don't trust them for this kind of thing -- stay in the mainstream usage
> and generics are great, start getting clever and we've been burned over and
> over. I don't believe anybody when they tell me it will work any more :-)).
> Instead override with covariant return types.
>
> I think that is possible, but it would be painful to add all the withers
> to all the properties for the entire public API. But I do think that once
> we've got the builders deprecated, we can then take a long look at what to
> do instead -- using lambdas for example. There might be other ways to get
> what we want that are much less intrusive. Or maybe just have an annotation
> processor that will auto-generate the builders of your choice and let it be
> a 3rd party thing.
>
> Richard
>
> On Mar 25, 2013, at 1:09 PM, Tom Eugelink <tbee at tbee.org> wrote:
>
> >
> > Basically that is very close to my "withers" suggestion, only I chose
> not to beak Java Bean API specs and keep the setters void.
> >
> > Tom
> >
> >
> > On 2013-03-25 21:01, Ali Ebrahimi wrote:
> >> Hi Richard,
> >> Today is the day I predicted two years ago and proposed alternative for
> >> Builders.
> >> this is : https://javafx-jira.kenai.com/browse/RT-13851
> >>
> >> Best regards,
> >> Ali Ebrahimi
> >>
> >> On Mon, Mar 25, 2013 at 10:05 PM, Richard Bair <richard.bair at oracle.com
> >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
> >
> >
>
>
More information about the openjfx-dev
mailing list