From: Edwin C. <com...@gm...> - 2009-03-24 17:32:45
|
Hi Farrukh, Option C would not need OptionsBase and Options, but only an Options object and maybe not even that (see below after steps a-e). The Options object is a bit of a strange beast, as it creates a javascript object and allows you to set arbitrary properties on them and ask for these properties. Basically the Options object allows you to create any javascript object you like (not so strange considering that in OL an options object is created with an object literal that can be any object). I have been thinking about it and I would still like to make a case for Option C. The problem with Option A is that it makes it to easy to code around the abstraction layer that GWT-OL offers. The setAttribute methods are not part of what you want to expose as the GWT-OL API on each options object, as they are basically methods that allow you to code around your api by setting properties by their javascript name. If 100 users want to set a ZIndex and there is no setZIndex method, the setAttribute method allows users to make such a method themselves but then they are coding around the abstraction GWT-OL offers and each of them has to lookup the exact name that the OL Map object uses for this property. Options C makes it clearer than Option A that users are coding around the GWT-OL API, while stile permitting them to do so. I asked a colleague who is a long-time Java programmer and he said the natural way he would approach opening up the setAttribute methods is to extend MapOptions, e.g. CustomMapOptions extends MapOptions, and provide a setZIndex method in CustomMapOptions. I think however that we should take into account that GWT-OL is a GWT thing, and sometimes you want access to the javascript objects underneath. What would be a better place to get access to these javascript objects underneath than the JSObject (see below)... Here's some more detail of how I would envision things: a) Tear apart the DOM helper methods from ElementHelper and the Javascript (object) helper methods (now named setAttribute/getAttribute) b) Put the Javascript (object) helper methods in JSObjectHelper c) Check which DOM methods in ElementHelper still make sense with GWT 1.5 (which has a lot of methods for doing DOM stuff) d) Rename the setAttributeXxx methods to setPropertyXxx () e) Implement the setProperty methods on JSObject, which is now just an empty extension of JavaScriptObject ( http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/core/client/JavaScriptObject.html ). Notice that JSObject cannot be instantiated directly and that this is intentionally done by GWT. So you would have to do: JSObject object = JSObject.createObject(); // or createFunction, or createArray; object.setProperty("anyProp", 1); //go about setting properties Or as we do in all wrapper functions JSObject object = XxxImpl.create(); // create the JSObject that the Xxx wraps By doing point (a)-(e) we get a lot cleaner code, and then we don't even need the Options object anymore, or only use it to create an empty javascript object on instantiation. MapOptions object can be a JSObjectWrapper or extend Options. The object it wraps if it is a JSObjectWrapper is an empty javascript object created by JSObject.createObject(). The setters and getters of MapOptions are then implemented as follows //how the setters would look public void setZIndex(int index) { getJSObject().setProperty("zindex", index); } MapOptions is a JSObjectWrapper, the JSObject is the javascript object underneath What's more, every object that is a JSObjectWrapper now has a backdoor to set properties that are not yet supported by the abstraction layer offered by GWT-OL.This is a bad thing if we want to have a locked down API, but a good thing if we want to be flexible, and let user get to the javascript beneath to solve stuff where there are not yet abstractions for. Map map = mapWidget.getMap(); map.getJSObject().setProperty("zindex", index); //not officially supported by GWT-OL, but possible By the way, when it boils down to it, everything in Javascript is an Object so having setProperty methods on JSObject makes sense to my mind. In javascript you can do var x = new Object() x.prop = "property" equals var x = { prop: "property" } var x = function(){}; x.prop = "property"; // does not directly make sense, but is possible, and possibly useful var x = 1 x.prop = "property"; // does not directly make sense, but is possible, and possibly useful All in all, an important point I think is that the GWT-OL API should eventually provide an abstraction layer above the javascript layer, so for users the javascript layer is invisible. The setAttribute methods set attributes directly on a javascript object and therefore I think it should be clear to users that they are messing with the javascript objects underneath. Greetings, Edwin 2009/3/24 Farrukh Najmi <fa...@we...> > Edwin Commandeur wrote: > >> Hi all, >> >> In reaction to a recent issue that OptionsBase (the base class for >> specific Options objects) doesn't expose it's setAttribute methods, while >> this can be useful at times I have thought of 3 options for options: >> >> A.) Let all XxxOptions objects extend Options directly. PRO: * direct >> access to setAttribute methods; CONS: * Options is actually a way to >> construct an arbitrary javascript object, while XxxOptions are not arbitrary >> javascript objects (they are technically in OpenLayers, but not >> conceptually), but a javascript object with specific properties (or >> attributes). * the code suggestions in the IDE get cluttered by all the >> setAttributeXxx methods >> >> B.) Let XxxOptions have a 'mergeOptions(Options options)' method that is >> able to take an Options object on which arbitrary properties can be set, and >> merge them (copy all the properties) with the XxxOptions object. PRO: * >> XxxOptions can have the power of the Options object without having to expose >> all the Options methods itself. * no code suggesting clutter; CONS: * >> XxxOptions would need to still extend OptionsBase, so there will remain 2 >> classes which overlapping and thus one should be redundant. * It is >> inconvenient for users to have to create two Options objects to set options >> that were not foreseen by the GWT-OL API >> Code Example Option B: >> MapOptions mapOptions = new MapOptions(); >> mapOptions.setTileSize(new Size(300,300)); >> Options options = new Options(); >> options.setAttribute("zIndex", 1000); //fictional >> mapOptions.mergeOptions(options); >> >> C.) Let XxxOptions wrap Options and provide a getOptions method through >> which arbitrary properties can be set. PRO: see B) CONS: needs one step more >> to set an attribute than A) => although this is also an advantage since you >> want user to have to set as less 'arbitrary' properties as possible and not >> make it to easy for them to do this. >> Code Example Option C: >> MapOptions mapOptions = new MapOptions(); >> mapOptions.setTileSize(new Size(300,300)); >> mapOptions.getOptions().setAttribute("zIndex", 1000); >> >> Currently I would favor option C.) as it acknowledges that conceptually an >> XxxOptions object is not a subclass of Options. This is because Options is >> actually more a generic way to create a Javascript Object with different >> properties in java (so you don't have to do this using JSNI). >> > > For me both B and C are confusing with more than one typeof Option class > while A is clear. > I am personally not bothered by IDE suggetsion clutter issue. IMHO We > should not let IDE cosniderations > impact the naturalness of the API. > > So, with my limited experience at this API I feel A is best. Please do not > consider this a VOTE as I do not feel > as qualified as other team mates to carry the same weight of opinion. > > >> While we are on this I would suggest that we rename Options and the >> setAttribute methods, as JavaScript Objects do not have attributes, but >> properties. One possibility I am thinking of is that the setProperty methods >> should be methods of JSObject. That way a MapOptions object can be just a >> JSObjectWrapper from which you can request the JSObject through getJSObject >> and which allows setting properties dynamically. Possibly there is some >> security reason why GWT doesn't allow setting properties on >> JavaScriptObject, although I cannot think of one, because all properties of >> a javascript object can be modified runtime if you have access to the >> objects on the page: >> >> http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/core/client/JavaScriptObject.html >> >> Throughout the code base there are more place where DOM terminology: >> Elements that have Attributes, is used where Javascript terminology is more >> correct: Objects that have properties. >> See also: >> http://jennifermadden.com/javascript/objectsPropertiesMethods.html >> > > Again with my limited experience, above suggestion sounds reasonable. > Thanks. > > -- > Regards, > Farrukh > > Web: http://www.wellfleetsoftware.com > > > |