Proposal: Deprecate Builders

Ali Ebrahimi ali.ebrahimi1781 at gmail.com
Mon Mar 25 13:23:06 PDT 2013


Hi,
just follow comments in jira task, your approach also suggested.

Ali Ebrahimi

On Tue, Mar 26, 2013 at 12:39 AM, 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<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