Proposal: Deprecate Builders

John Hendrikx hjohn at xs4all.nl
Wed Apr 3 16:34:15 PDT 2013


I don't use Builders, but they exist in my opinion because of a lack in 
C style languages to access objects through a (possibly nested) hidden 
reference.

The second example shows the problem that always occurs when building 
object structures:
> Group g = new Group(gg ->  {
>      gg.getChildren().addAll(new Button(b ->  {
>          b.setText("Hello");
>      });
> });
What names should the variables have?  When constructing a deeply nested 
set of objects I rapidly run out of good names for my variables.  Giving 
them long descriptive names is incredibly counter-productive when you 
have to call several methods on them (ie, 
centerPanelWestBorderListGroup.setText() gets cumbersome).  Inevitable 
we end up with a mess of variables g1, g2, g3, button1, button2, etc...

This exactly what Builders prevent and also what the 
subclass-initializer pattern prevents.  These patterns allow for code to 
be moved around without having to worry about variable naming conflicts 
-- or having to worry about keeping variable names updated (let's add 
another panel around the centerPanel...)

I'm curious however what generic problem you are running into.  Long ago 
I wrote code that solved the casting and generics problems with the 
with-pattern.  It basically looked like this:

public final Button extends AbstractButton<Button> {
   // empty subclass, which only overrides self()
   protected Button self() {
      return this;
   }
}

public abstract AbstractButton<C> extends AbstractNode<C> {
    // contains the main code
    public C setText(String text) {
       ...
       return self();
    }
}

public abstract AbstractNode<C> {
   public C setColor(Color color) {
      ...
      return self();
   }

   protected abstract C self();
}

Now, the nice thing here is that the user can access setters accross 
classes without having to cast the result, and there's no generics in 
user code:

Button b = new Button().setColor(RED).setText("A");  // Note that after 
Node#setColor() I can still call Button#setText().

The disadvantage of course was the extra classes required (although the 
final classes are mostly empty, and only provide the self() method as 
Java has no mechanism to do this more directly) and of course it made 
creating new controls a bit more effort (have to extend an Abstract 
class, and provide a convience final class).

I'm wondering if this is also affected by the bug aforementioned and 
fails on JDK8, or if this is a different trick...

--John



More information about the openjfx-dev mailing list