Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 158398

Summary: [DataBinding] Data-Binding Facade: Bound Controls
Product: [Eclipse Project] Platform Reporter: Andy Maleh <andy>
Component: UIAssignee: Boris Bokowski <bokowski>
Status: RESOLVED WONTFIX QA Contact:
Severity: enhancement    
Priority: P3 CC: bradleyjames, cervezas, dev, djo, noelgrandin, peter, qualidafial, villane, wmitsuda
Version: 3.2   
Target Milestone: ---   
Hardware: All   
OS: All   
URL: http://www.obtiva.com
Whiteboard:

Description Andy Maleh CLA 2006-09-22 20:17:50 EDT
Hello,

I am currently involved with an RCP project where we use data-binding heavily. I work with David Orme, one of the data-binding committers.

Data-binding has been great in making UI development easier. However, developers complain about the syntax being too cryptic and abstract especially when revisiting old code to do maintenance.

I propose a solution to the problem through a facade that I partially programmed.

Following the 80/20 rule, the facade will simplify data-binding in 80% of the cases when the binding task is simple. In the remaining 20% of the cases, regular data-binding syntax may be used instead.

Here are examples of using data-binding without and with the facade (note that there are two facade approaches):

* * *

1- Text:

Without Facade:

Text text = new Text(parent, style);
dbc.bindValue(SWTObservables.get(text), BeanObservables.get(model, property));

With Facade:

Text text = new BoundText(parent, style, model, property).getControl();

With Alternative Facade:

Text text = new BoundText(parent, style).bind(model, property);

2- Combo:

Without Facade:

Combo combo = new Combo(parent, style)
ComboViewer comboViewer = new ComboViewer(combo);
dbc.bindValue(SWTObservables.get(comboViewer), BeanObservables.get(model, selectionProperty));
dbc.bindList(SWTObservables.get(comboViewer), BeanObservables.get(model, collectionProperty));

With Facade:

Combo combo = new BoundCombo(parent, style, model, collectionProperty, selectionProperty).getControl();

With Alternative Facade:

Combo combo = new BoundCombo(parent, style).bind(model, collectionProperty, selectionProperty);

* * *

As stated before, data-binding syntax was found cryptic by our developers, so the newly proposed facade hides its complexity, shielding the developers from the low-level syntax that happens underneath.

For the remaining 20% of the cases, the developers may use the low-level syntax to accomplish their tasks.

I reviewed this Facade approach with the developers on our project, and they all seemed to like it. 

Note that this facade approach was used very successfully for a custom control in our project. This control, called TimeSpanSelector, required complex data-binding logic, and we wanted to use it in multiple screens in the application, so I wrapped it with BoundTimeSpanSelector, which handled all data-binding related tasks and logic, and then dropped that with one line of code in every screen that needed it.

I would like to review the facade idea (both approaches) with people in the data-binding team and Eclipse community. It would be nice to contribute some feedback, discuss the proposed facade approaches, and brainstorm over refining the approaches even further.

Best regards,

Andy Maleh
Consultant
Obtiva Corp.
www.obtiva.com
Comment 1 Peter Centgraf CLA 2006-09-28 09:20:10 EDT
This seems like a useful enhancement, especially for developers who are used to explicitly creating controls in code.  In particular, I appreciate how your Combo example provides a single method for binding both contents and selection.  Very graceful.

I have concerns about the details of how this would work in practice, though.  How does the facade integrate with an existing DataBindingContext? ... Eclipse Forms?  ... GUI builders? ... EMF?  How would a client configure validation?  How would a client manipulate the binding after it is created, e.g. to add a binding listener for debugging?  It's not clear from your example that the Binding is even reachable, i.e. would not be available for garbage collection as soon as it's created.

I'm not saying these are fatal problems, but I think we need more spec before we can judge if this is practical.
Comment 2 Andy Maleh CLA 2006-09-28 12:08:04 EDT
Thanks for your feedback Peter.

"I have concerns about the details of how this would work in practice, though."

Some of those points are in the 20% of the 80/20 rule :-) Good points nonetheless. 

"How does the facade integrate with an existing DataBindingContext?"

We can have an overloaded constructor or method take the existing DataBindingContext as a parameter. 

Facade Approach 1:
Text text = new BoundText(dbc, parent, style, model, property).getControl();

Facade Approach 2
Text text = new BoundText(parent, style).bind(dbc, model, property);

This is how it was done for our TimeSpanSelector control actually.

Another idea that needs brainstorming and further refinement is to have a separate FacadeContextManager 

class. It acts as the main point for configuring the DataBindingContext. Facade Bound controls may then 

collaborate with FacadeContextManager to obtain a singleton DataBindingContext and do data-binding. 
Pros: Hides data-binding details from the user.
Cons: Handles only simple common scenarios

"... Eclipse Forms? ... EMF?"

I would leave this to version 1.1 or 2 of the facade as the goal of the facade is not to do 100%, yet to 

begin with a small simple facade that simplifies data-binding for the most common cases.

" ... GUI builders? "

This facade is definitely meant to be used by developers that want to write their own data-binding code 

and want the syntax to be simple. That is less of a concern for GUI Builders as they are automated, so 

they can use standard data-binding syntax if need be.

"  How would a client configure validation? "

Possible approaches:
BindSpec is passed through an overloaded constructor or through a method:

Facade Approach 1:
Text text = new BoundText(parent, style, model, property, bindSpec).getControl();

Facade Approach 2
Text text = new BoundText(parent, style).setBindSpec(bindSpec).bind(model, property);

Another approach is to provide setValidator, setModelToTargetConverter, etc... methods on bound controls so that the developer does not have to construct a BindSpec.

"How would a client manipulate the binding after it is created, e.g. to add a binding listener for 

debugging?  It's not clear from your example that the
Binding is even reachable, i.e. would not be available for garbage collection
as soon as it's created."

Possible approach:
Binding binding = boundText.getBinding();

Let me re-emphasize that the proposed facade is incomplete and I was hoping to collaborate with other 

Eclipse community members over here to polish it. Any feedback or suggestions for improving the facade API are greatly appreciated.

Andy
Comment 3 Boris Bokowski CLA 2006-09-29 14:20:35 EDT
I am reluctant to add any convenience methods (or classes) for creating bindings to the API at this point.  This does not mean I am against it, I just think we need to focus on getting minimal but useable public API out in this cycle (3.3).
Comment 4 Matthew Hall CLA 2009-01-21 22:58:11 EST
-1

The problem I see, at least with the proposal as described, it that BoundText / BoundCombo presume that the client is using only SWT/JFace and Beans.  Indeed the problem in general is that there are too many assumptions.

Currently there are no bundles with core.databinding.beans and jface.databinding as dependencies, so that would require introducing a new bundle just for that purpose.  I don't see an advantage in introducing an API that will only help those who are combining those two specific libraries, and leave other users in the cold.

As of 3.3, DataBinding has followed an imperative style e.g. SWTObservables.observeText(control) as opposed to the old declarative style (adding observable factories to DataBindingContext and then asking the DBC to bind two objects using the observable factories as advisors).  While this has the tendency to make binding code a little verbose and sometimes ugly, it also helps make the programmer's intentions explicit.

With that said, the properties API (bug 194734) may open up a new possibility:

IValueProperty property = BeanProperties.value("name");
Text text = new BoundText(parent, style, model, property);

However this presumes that we want to bind to the text property of the Text control.  So we could:

IValueProperty textProperty = WidgetProperties.text(SWT.Modify);
IValueProperty nameProperty = BeanProperties.value("name");
Text text = new BoundText(parent, style, textProperty, model, nameProperty);

However at that point you might as well:

Text text = new Text(parent, style);
dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(text),
              BeanProperties.value("name").observe(model));

or even:

Text text = new Text(parent, style);
dbc.bindValue(text, WidgetProperties.text(SWT.Modify),
              model, BeanProperties.value("name"));

However even this last example assumes that the user is using properties which might be unnecessarily restrictive.
Comment 5 Boris Bokowski CLA 2009-01-22 00:15:59 EST
Let's close this then, based on Matt's and my reluctance. Andy, would something along the lines of the proposal in bug 203492 help?
Comment 6 Andy Maleh CLA 2009-01-22 11:58:56 EST
Sure, this does not have to be part of the JFace Data-Binding core libraries, especially that some projects may be using EMF instead of PropertyChangeSupport.

Also, developers wanting a simplified syntax can use the new Eclipse Glimmer project instead:
http://andymaleh.blogspot.com/2007/12/glimmers-built-in-data-binding-syntax.html

To clarify my earlier intentions, the BoundControl's approach was making assumptions on purpose to simplify the API. This is the same 80/20 rule we follow when using Java instead of C because of the assumption that programmers don't want to manage memory themselves. The point is to have as small of a syntax as possible on top of the more complex APIs for 80% of the cases, and then only revert to the more complex APIs for 20% of the cases.

That said, it's OK if we end up building this API outside of JFace Data-Binding.
Comment 7 Matthew Hall CLA 2009-01-22 12:36:30 EST
Andy, have you looked at the UFace project?

http://code.google.com/p/uface/

Also the JavaBuilders project is working toward SWT support:

http://code.google.com/p/javabuilders/