Bug 212518 - [DataBinding] ConstantObservableValue contribution
Summary: [DataBinding] ConstantObservableValue contribution
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.4   Edit
Hardware: PC Linux
: P3 enhancement (vote)
Target Milestone: 3.4 M6   Edit
Assignee: Matthew Hall CLA
QA Contact:
URL:
Whiteboard:
Keywords: contributed
Depends on:
Blocks:
 
Reported: 2007-12-11 05:23 EST by Matt Carter CLA
Modified: 2008-03-27 14:47 EDT (History)
1 user (show)

See Also:


Attachments
Immutable static value observable (3.22 KB, patch)
2007-12-11 05:26 EST, Matt Carter CLA
no flags Details | Diff
Static/constant value observable (6.49 KB, patch)
2007-12-12 04:59 EST, Matt Carter CLA
no flags Details | Diff
Constant/Static value observable type. Proper contributor comments in this patch, forgot those. (6.77 KB, patch)
2007-12-12 05:02 EST, Matt Carter CLA
no flags Details | Diff
Tests for IObservableValue contract (4.00 KB, patch)
2007-12-12 12:40 EST, Matthew Hall CLA
no flags Details | Diff
Tests for IObservableValue contract - updated contribution comments (4.01 KB, patch)
2007-12-12 12:42 EST, Matthew Hall CLA
no flags Details | Diff
Test for null realm check in constructor (4.33 KB, patch)
2007-12-12 13:00 EST, Matthew Hall CLA
no flags Details | Diff
Immutable constant/static value observable (7.33 KB, patch)
2007-12-15 11:27 EST, Matt Carter CLA
no flags Details | Diff
Updated patch with renames and test case (13.78 KB, patch)
2008-02-07 20:05 EST, Matthew Hall CLA
no flags Details | Diff
mylyn/context/zip (2.73 KB, application/octet-stream)
2008-02-07 20:05 EST, Matthew Hall CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Matt Carter CLA 2007-12-11 05:23:52 EST
In my applications of data binding I have required in two places an observable class for a static, constant value.

I think this should be in core.

Contribution (patch) attached.
Comment 1 Matt Carter CLA 2007-12-11 05:26:15 EST
Created attachment 84944 [details]
Immutable static value observable
Comment 2 Matthew Hall CLA 2007-12-11 13:15:04 EST
I agree that this would be good in core, however I'd rather this class was internal and its functionality available through static factory methods in the Observables class:

IObservableValue staticObservableValue(Object value);
IObservableValue staticObservableValue(Object value, Object valueType);
IObservableValue staticObservableValue(Realm realm, Object value);
IObservableValue staticObservableValue(Realm realm, Object value, Object valueType);

This fits well with the other staticObservable(List|Set) methods already present in Observables.
Comment 3 Matt Carter CLA 2007-12-12 04:58:38 EST
(In reply to comment #2)
> I agree that this would be good in core, however I'd rather this class was
> internal and its functionality available through static factory methods in the
> Observables class

Agreed.
Comment 4 Matt Carter CLA 2007-12-12 04:59:28 EST
Created attachment 85041 [details]
Static/constant value observable
Comment 5 Matt Carter CLA 2007-12-12 05:02:06 EST
Created attachment 85043 [details]
Constant/Static value observable type. Proper contributor comments in this patch, forgot those.
Comment 6 Matthew Hall CLA 2007-12-12 12:40:03 EST
A few things that need to be checked:
* Checking for null realm in constructor
* Checking whether we're running within the realm.
* Calling getterCalled() in accessors (see IObservableValue, every method with @TrackedGetter in the javadoc must call ObservableTracker.getterCalled(this) before proceeding).
* valueType parameter should be an Object argument, not Class.  This is to support other concepts of type such as EMF's EClass, Groovy's MetaClass and so on.

I'll start by attaching a test case for the first three points above.

IObservableValue.setValue states that an UnsupportedOperationException will be thrown if setValue is not allowed.  Personally I would prefer that ConstantValue threw this instead of BindingException.

Which brings up a more general topic, should IObservables throw BindingException at all?  I see this all over the place in JDB but it doesn't seem appropriate.  Observables can be used without bindings, and getting a BindingException in those situations is confusing.  If the Perhaps the observables should throw more generic runtime exceptions, and if a Binding catches an exception, it should a BindingException which wraps the observable's thrown exception.  Just thought I'd bring it up.
Comment 7 Matthew Hall CLA 2007-12-12 12:40:55 EST
Created attachment 85094 [details]
Tests for IObservableValue contract
Comment 8 Matthew Hall CLA 2007-12-12 12:42:57 EST
Created attachment 85095 [details]
Tests for IObservableValue contract - updated contribution comments

Whoops, forgot to update contribution comments :)
Comment 9 Matthew Hall CLA 2007-12-12 13:00:35 EST
Created attachment 85100 [details]
Test for null realm check in constructor
Comment 10 Matt Carter CLA 2007-12-15 11:27:34 EST
Created attachment 85334 [details]
Immutable constant/static value observable
Comment 11 Matt Carter CLA 2007-12-15 11:36:13 EST
(In reply to comment #6)
> A few things that need to be checked:
> * Checking for null realm in constructor
> * Checking whether we're running within the realm.
> * Calling getterCalled() in accessors (see IObservableValue, every method with
> @TrackedGetter in the javadoc must call ObservableTracker.getterCalled(this)
> before proceeding).
> * valueType parameter should be an Object argument, not Class.  This is to
> support other concepts of type such as EMF's EClass, Groovy's MetaClass and so
> on.
> 

New patch attached with IObservableValue contract checked and all the above points from Matt Hall all sorted.

Thank Matt, this was helpful diligence and thanks for adding the test.

Seems this bug needed a bit more work than the daft little class I initially thought it was :)

Two more points for input if anyone has any:
-  ConstantValue could alternatively have been called StaticValue in line with *static*() methods in Observables. Static here however, such as in the Static case means "does not fire events" and "does not need disposing", the underlying list content is not immutable. I called it ConstantValue instead. If we prefer StaticValue it can be renamed.
- WritableValue is not an internal class but we have made ConstantValue an internal one. Both can be constructed directly in client code. Why was WritableValue made API without the indirection through Observables? (Note: I prefer it to be directly usable)
Comment 12 Matt Carter CLA 2007-12-15 11:37:42 EST
Matt it seems to me that your third test patch replaces the previous ones unless I am mistaken. If so you might want to obsolete the last two by checking 'Obsolete' on the Details page. I can't do this for you. It can be done too on patch submission.
Comment 13 Matt Carter CLA 2007-12-15 11:39:58 EST
(Correction to comment #11)
s/Static case/staticObservableList() case/
Comment 14 Boris Bokowski CLA 2007-12-15 13:18:52 EST
(In reply to comment #11)
> Why was WritableValue made API without the indirection through Observables?

To enable subclassing.

Reasons for the indirection:
 * in future versions, implementation can be changed freely
 * makes it easy for clients to discover functionality
 * follows the Java collections framework example
 * clients cannot subclass (i.e. the subclass contract does not have to be specified)

Reasons against it:
 * clients cannot subclass :)
Comment 15 Matthew Hall CLA 2007-12-15 15:57:58 EST
> (In reply to comment #6)
> Two more points for input if anyone has any:
> -  ConstantValue could alternatively have been called StaticValue in line with
> *static*() methods in Observables. Static here however, such as in the Static
> case means "does not fire events" and "does not need disposing", the underlying
> list content is not immutable. I called it ConstantValue instead. If we prefer
> StaticValue it can be renamed.

I agree that "static" isn't appropriate.  Some other possible names are ImmutableValue, UnmodifiableValue or FinalValue.

There are two aspects that need to be considered separately that should be considered as we discuss new API: mutability and modifiability.

Mutability indicates whether the object can change.  Modifiability indicates whether the object may be changed through a given interface.

ArrayList is mutable and modifiable.
Collections.unmodifiableList(ArrayList) is mutable but not modifiable through the returned List.
Collections.singletonList(T) is immutable and unmodifiable.

Mutable, modifiable : WritableValue, WritableList
Mutable, unmodifiable: Observables.unmodifiableObservableList()
Immutable, unmodifiable: Observables.emptyObservableList()
Immutable, modifiable: Not possible (modifiable implies mutable)

I'm starting to wonder if the use of "static" is appropriate even for collections.  It has nothing to do with the traditional meaning of the word in Java and doesn't really convey what the object does (I read the meaning of the method differently than you described).  Perhaps it would be better to rename/redirect the staticObservable* methods to unmodifiableObservable*?

Another thing that came up while writing the tests is that the base ObservableListContractTest assumes mutability, so I had to subclass the contract test just to disable all the tests that failed because of it.

Sorry this is so disjointed, I hope all my points came across clearly. 
Comment 16 Matthew Hall CLA 2007-12-17 02:27:35 EST
Please see bug 213145 for my proposal to fix the observable contract tests with regard to comment 15 earlier.
Comment 17 Matt Carter CLA 2007-12-17 04:25:32 EST
(In light of comment #14)

Perhaps ConstantValue should be exposed as API too then, it's the logical opposite of WritableValue.

(In reply to comment #15)

I agree with Matt's comments on the meaning of 'static' and the better terms available in line with the Java Collections API. 

I had to read all the nearby comments to understand the purpose of the Observables.static*() methods.

> Perhaps it would be better to rename/redirect the staticObservable* methods to unmodifiableObservable*?

+1

staticObservable*() are API though, so we'd obviously have to deprecate the existing methods and create renamed ones. I think the sooner the better. I wonder how many consumers use these methods.. few? I think Boris might disapprove of renaming existing API methods like this though.
Comment 18 Matt Carter CLA 2007-12-17 04:31:23 EST
Actually.. I don't like indirection at all unless it adds value. I think Observables should contain emptySet() and accessors for similar reusable objects but should not contain factory methods for objects that could be classes constructed just as easily and more naturally using their constructor.
That's my opinion though :)
Comment 19 Matthew Hall CLA 2007-12-17 08:59:44 EST
Looking at the file history I see that Observables.staticObservable* methods were present in the 3.3 release so cannot be changed now.  I should have checked that before making such a sweeping suggestion.

The most correct approach seems to be to fill out the javadoc.  I have a pending patch for bug 208322 which does just this.
Comment 20 Matthew Hall CLA 2008-02-06 18:18:24 EST
Taking ownership.
Comment 21 Matthew Hall CLA 2008-02-07 20:05:23 EST
Created attachment 89221 [details]
Updated patch with renames and test case
Comment 22 Matthew Hall CLA 2008-02-07 20:05:25 EST
Created attachment 89222 [details]
mylyn/context/zip
Comment 23 Matthew Hall CLA 2008-02-13 15:26:28 EST
Released to HEAD > 20080213

Thanks, Matt!
Comment 24 Matthew Hall CLA 2008-03-27 14:25:07 EDT
Verified by code inspection in I20080327-0100