[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 11:45 PM, Arthur Kalmenson wrote: > With this idea of using moniker classes, would you still provide the > class name as a parameter to runAsync or would the compiler just > assume the name of the runAsync call is the name of the class it lives > in? If you allow providing a class name, would you check it's the name > of the class the call is in? I like the automagic naming using the > class name. Sorry for the delay. There would definitely be no check that the supplied class name matches. It would interfere with an important use case. Without the check, a library writer can embed a call to runAsync and then public in the library's docs a public class to use to name that call. The public class would be visible to clients of the library, but the call to runAsync might be buried in some private implementation class. Thus, for this use case, the two classes would be different. I hadn't thought about automatically using the surrounding class if none is specified. Already something similar is done in that you can use JSNI references. Maybe it would also make sense to use the surrounding class automatically, if there happens to only be one call within the class and if no class was explicitly passed in. Hmmm. Lex --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
For what it's worth, I like the moniker class idea best. Staying type safe, IMHO, is always a good thing. With regards to the downside John Tamplin mentioned (multiple runAsync calls in one class), why not consider that a feature? Since the original idea of naming the runAsync call is to allow for prefetching, putting several runAsync class in one class could allow you to easily prefetch a particular large chunk of code. If you find you don't want to prefetch, nothing happens and little pieces download each time. If you put this together with Bruce's class hierarchy idea, you might be able to provide a single name to call to fetch the entire application. This could be integrated with a "Go offline" button for an easy download everything call. With this idea of using moniker classes, would you still provide the class name as a parameter to runAsync or would the compiler just assume the name of the runAsync call is the name of the class it lives in? If you allow providing a class name, would you check it's the name of the class the call is in? I like the automagic naming using the class name. Best regards, -- Arthur Kalmenson P.S. Naming to allow for prefetching is an awesome idea. I was thinking how one would prefetch components while watching the GWT Google I/O sessions. This would definitely make going offline easy too. On Wed, Jun 24, 2009 at 10:55 PM, Cameron Braid wrote: > All good points. > > Would interfaces be supported as well ? > > Are there any dangers of allowing arbitrary classes (or interfaces) to be > used as monikers ? > > i.e from your example, would there be anything wrong with using > EmailCompositionView.class as the moniker ? > >> void onComposeButtonClicked() { >> GWT.runAsync(EmailCompositionView.class, new AsyncCallback() { >> public void onError(Throwable e) { ... } >> public void onSucess() { >> new EmailCompositionView().activate(); >> } >> }); > > I guess the compiler would have to verify that each call to runAsync uses a > unique moniker - is there anything else ? > > Must the moniker class exists in your own module ? > > Would you only allow leaf classes to be used as monikers, i.e. could you use > OfficeSuiteSplitPoint.class as a moniker ? > > Cam > > 2009/6/25 Bruce Johnson >> >> Four additional arguments in favor of using "split point moniker classes" >> is that they >> 1) are easier to find within an IDE (i.e. "Show References" in your IDE >> from a moniker class declaration would show you the associated runAsync >> call), >> 2) can take advantage of inheritance as a way to group split points into >> meaningful families (which would make them more easily browsable and >> navigable in javadoc and in an IDE), >> 3) can be javadoc'ed to explain what they do, and >> 4) they could potentially be augmented with additional hints to the code >> splitter using annotations (these are a stretch; Lex might be able to think >> of more realistic example annotations) >> >> /** >> * Split points in this hierarchy relate to the email functionality within >> the office suite. >> */ >> class EmailSplitPoint extends OfficeSuiteSplitPoint { >> } >> >> /** >> * This split point carves out all heavyweight functionality related to >> composing emails, >> * most importantly, the rich text area clases. >> */ >> @ProhibitPreloading >> @MustBeExclusiveFragment >> class EmailCompositionSplitPoint extends EmailSplitPoint { >> } >> >> // ... elsewhere ... >> >> void onComposeButtonClicked() { >> GWT.runAsync(EmailCompositionSplitPoint.class, new AsyncCallback() { >> public void onError(Throwable e) { ... } >> public void onSucess() { >> new EmailCompositionView().activate(); >> } >> }); >> } >> >> On Wed, Jun 24, 2009 at 6:50 PM, Cameron Braid >> wrote: >>> >>> Each of these different libraries would be enclosed within a unique GWT >>> module therefore when you refer to the split point name, can't you just use >>> the module name + split point name ? >>> >>> in module ThirdParty : >>> >>> GWT.runAsync("one", new RunAsyncCallback() { ... }); >>> >>> in MyModule : >>> >>> GWT.runAsync("one", new RunAsyncCallback() { ... }); >>> >>> >> name="compiler.splitpoint.initial.sequence" value="MyModule#one" /> >>> >> name="compiler.splitpoint.initial.sequence" value="ThirdParty#one" /> >>> >>> Cam >>> >>> 2009/6/25 Lex Spoon On Wed, Jun 24, 2009 at 2:15 PM, Lex Spoon wrote: > Overall, unless I missed something, Okay, Bruce pointed out a new constraint to me: if different libraries name their runAsync calls, then we want to able to refer to those calls reliably even if different libraries choose the same name. This isn't an issue immediately, but it likely will be in the future. Thinking about libraries, I would add another constraint: we don't want libraries to have to expose their implementation. Library writers should ideally be able to document a named runAsync call without exposing th
[gwt-contrib] Re: naming runAsync calls
> > I guess the compiler would have to verify that each call to runAsync uses a > unique moniker - is there anything else ? I think that's it. Pretty easy to check, and pretty easy for a developer to reason about, too. Must the moniker class exists in your own module ? I don't think it ought to be so restricted unless anyone can think of a reason to. It would actually be a good bit harder to implement to enforce that rule. > Would you only allow leaf classes to be used as monikers, i.e. could you > use OfficeSuiteSplitPoint.class as a moniker ? This would also work, although it's still too new an idea to say whether it would be wise to use such a pattern in practice. --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
All good points. Would interfaces be supported as well ? Are there any dangers of allowing arbitrary classes (or interfaces) to be used as monikers ? i.e from your example, would there be anything wrong with using EmailCompositionView.class as the moniker ? void onComposeButtonClicked() { > GWT.runAsync(EmailCompositionView.class, new AsyncCallback() { >public void onError(Throwable e) { ... } > public void onSucess() { > new EmailCompositionView().activate(); > } > }); >> >> I guess the compiler would have to verify that each call to runAsync uses a unique moniker - is there anything else ? Must the moniker class exists in your own module ? Would you only allow leaf classes to be used as monikers, i.e. could you use OfficeSuiteSplitPoint.class as a moniker ? Cam 2009/6/25 Bruce Johnson > Four additional arguments in favor of using "split point moniker classes" > is that they > 1) are easier to find within an IDE (i.e. "Show References" in your IDE > from a moniker class declaration would show you the associated runAsync > call), > 2) can take advantage of inheritance as a way to group split points into > meaningful families (which would make them more easily browsable and > navigable in javadoc and in an IDE), > 3) can be javadoc'ed to explain what they do, and > 4) they could potentially be augmented with additional hints to the code > splitter using annotations (these are a stretch; Lex might be able to think > of more realistic example annotations) > > /** > * Split points in this hierarchy relate to the email functionality within > the office suite. > */ > class EmailSplitPoint extends OfficeSuiteSplitPoint { > } > > /** > * This split point carves out all heavyweight functionality related to > composing emails, > * most importantly, the rich text area clases. > */ > @ProhibitPreloading > @MustBeExclusiveFragment > class EmailCompositionSplitPoint extends EmailSplitPoint { > } > > // ... elsewhere ... > > void onComposeButtonClicked() { > GWT.runAsync(EmailCompositionSplitPoint.class, new AsyncCallback() { > public void onError(Throwable e) { ... } > public void onSucess() { > new EmailCompositionView().activate(); > } > }); > > } > > On Wed, Jun 24, 2009 at 6:50 PM, Cameron Braid wrote: > >> Each of these different libraries would be enclosed within a unique GWT >> module therefore when you refer to the split point name, can't you just use >> the module name + split point name ? >> >> in module ThirdParty : >> >> GWT.runAsync("one", new RunAsyncCallback() { ... }); >> >> in MyModule : >> >> GWT.runAsync("one", new RunAsyncCallback() { ... }); >> >> > value="MyModule#one" /> >> > value="ThirdParty#one" /> >> >> Cam >> >> 2009/6/25 Lex Spoon >> >> >>> On Wed, Jun 24, 2009 at 2:15 PM, Lex Spoon wrote: >>> > Overall, unless I missed something, >>> >>> Okay, Bruce pointed out a new constraint to me: if different libraries >>> name their runAsync calls, then we want to able to refer to those >>> calls reliably even if different libraries choose the same name. This >>> isn't an issue immediately, but it likely will be in the future. >>> >>> Thinking about libraries, I would add another constraint: we don't >>> want libraries to have to expose their implementation. Library >>> writers should ideally be able to document a named runAsync call >>> without exposing the precise arrangement of their internal classes. >>> >>> After some discussion at the office, a tweak to option 4 fixes things >>> up handily. Instead of passing in a string to the method, act like a >>> Java framework and require passing in a class literal. A typical use >>> in application code would pass in the enclosing top-level class: >>> >>> package org.foodity.impl; >>> class Cookies { >>> ... >>> GWT.runAsync(Cookies.class, new RunAsyncCallback() { ... }); >>> ... >>> } >>> >>> A library writer could instead specify a public class, so as not to >>> expose their internal factoring. >>> >>> A user of the name in a gwt.xml file would use the fully qualified >>> version: >>> >>> >> name="compiler.splitpoint.initial.sequence" >>> value="org.foodity.impl.Cookies" /> >>> >>> A user in another Java file would use imports to make the name short: >>> >>> import org.foodity.impl.Cookies; >>> >>> RunAsyncQueue.startPrefetching(Cookies.class); >>> >>> >>> Thoughts? The main downside I know of is the one John Tamplin has >>> pointed out: if there are multiple runAsync calls within a single >>> class -- as sometimes happens -- then the programmer has to code up >>> some new classes that will only be used for naming. Can we live with >>> that? >>> >>> Lex >>> >>> >>> >> >> >> > > > > --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
Four additional arguments in favor of using "split point moniker classes" is that they 1) are easier to find within an IDE (i.e. "Show References" in your IDE from a moniker class declaration would show you the associated runAsync call), 2) can take advantage of inheritance as a way to group split points into meaningful families (which would make them more easily browsable and navigable in javadoc and in an IDE), 3) can be javadoc'ed to explain what they do, and 4) they could potentially be augmented with additional hints to the code splitter using annotations (these are a stretch; Lex might be able to think of more realistic example annotations) /** * Split points in this hierarchy relate to the email functionality within the office suite. */ class EmailSplitPoint extends OfficeSuiteSplitPoint { } /** * This split point carves out all heavyweight functionality related to composing emails, * most importantly, the rich text area clases. */ @ProhibitPreloading @MustBeExclusiveFragment class EmailCompositionSplitPoint extends EmailSplitPoint { } // ... elsewhere ... void onComposeButtonClicked() { GWT.runAsync(EmailCompositionSplitPoint.class, new AsyncCallback() { public void onError(Throwable e) { ... } public void onSucess() { new EmailCompositionView().activate(); } }); } On Wed, Jun 24, 2009 at 6:50 PM, Cameron Braid wrote: > Each of these different libraries would be enclosed within a unique GWT > module therefore when you refer to the split point name, can't you just use > the module name + split point name ? > > in module ThirdParty : > > GWT.runAsync("one", new RunAsyncCallback() { ... }); > > in MyModule : > > GWT.runAsync("one", new RunAsyncCallback() { ... }); > > value="MyModule#one" /> > value="ThirdParty#one" /> > > Cam > > 2009/6/25 Lex Spoon > > >> On Wed, Jun 24, 2009 at 2:15 PM, Lex Spoon wrote: >> > Overall, unless I missed something, >> >> Okay, Bruce pointed out a new constraint to me: if different libraries >> name their runAsync calls, then we want to able to refer to those >> calls reliably even if different libraries choose the same name. This >> isn't an issue immediately, but it likely will be in the future. >> >> Thinking about libraries, I would add another constraint: we don't >> want libraries to have to expose their implementation. Library >> writers should ideally be able to document a named runAsync call >> without exposing the precise arrangement of their internal classes. >> >> After some discussion at the office, a tweak to option 4 fixes things >> up handily. Instead of passing in a string to the method, act like a >> Java framework and require passing in a class literal. A typical use >> in application code would pass in the enclosing top-level class: >> >> package org.foodity.impl; >> class Cookies { >> ... >> GWT.runAsync(Cookies.class, new RunAsyncCallback() { ... }); >> ... >> } >> >> A library writer could instead specify a public class, so as not to >> expose their internal factoring. >> >> A user of the name in a gwt.xml file would use the fully qualified >> version: >> >> > name="compiler.splitpoint.initial.sequence" >> value="org.foodity.impl.Cookies" /> >> >> A user in another Java file would use imports to make the name short: >> >> import org.foodity.impl.Cookies; >> >> RunAsyncQueue.startPrefetching(Cookies.class); >> >> >> Thoughts? The main downside I know of is the one John Tamplin has >> pointed out: if there are multiple runAsync calls within a single >> class -- as sometimes happens -- then the programmer has to code up >> some new classes that will only be used for naming. Can we live with >> that? >> >> Lex >> >> >> > > > > --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
Each of these different libraries would be enclosed within a unique GWT module therefore when you refer to the split point name, can't you just use the module name + split point name ? in module ThirdParty : GWT.runAsync("one", new RunAsyncCallback() { ... }); in MyModule : GWT.runAsync("one", new RunAsyncCallback() { ... }); Cam 2009/6/25 Lex Spoon > > On Wed, Jun 24, 2009 at 2:15 PM, Lex Spoon wrote: > > Overall, unless I missed something, > > Okay, Bruce pointed out a new constraint to me: if different libraries > name their runAsync calls, then we want to able to refer to those > calls reliably even if different libraries choose the same name. This > isn't an issue immediately, but it likely will be in the future. > > Thinking about libraries, I would add another constraint: we don't > want libraries to have to expose their implementation. Library > writers should ideally be able to document a named runAsync call > without exposing the precise arrangement of their internal classes. > > After some discussion at the office, a tweak to option 4 fixes things > up handily. Instead of passing in a string to the method, act like a > Java framework and require passing in a class literal. A typical use > in application code would pass in the enclosing top-level class: > > package org.foodity.impl; > class Cookies { > ... > GWT.runAsync(Cookies.class, new RunAsyncCallback() { ... }); > ... > } > > A library writer could instead specify a public class, so as not to > expose their internal factoring. > > A user of the name in a gwt.xml file would use the fully qualified version: > > name="compiler.splitpoint.initial.sequence" > value="org.foodity.impl.Cookies" /> > > A user in another Java file would use imports to make the name short: > > import org.foodity.impl.Cookies; > > RunAsyncQueue.startPrefetching(Cookies.class); > > > Thoughts? The main downside I know of is the one John Tamplin has > pointed out: if there are multiple runAsync calls within a single > class -- as sometimes happens -- then the programmer has to code up > some new classes that will only be used for naming. Can we live with > that? > > Lex > > > > --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 2:08 PM, Lex Spoon wrote: > Thoughts? The main downside I know of is the one John Tamplin has > pointed out: if there are multiple runAsync calls within a single > class -- as sometimes happens -- then the programmer has to code up > some new classes that will only be used for naming. Can we live with > that? Would enums fix that? It's proposal 3.14E308, or something, so maybe it should be skipped, but it's easy to add another constant to an existing enum and they're just as easy to document. Maybe provide a marker interface like SplitPointNameMarker in the GWT library and 3rd-party libraries can do this: public enum SplitPoints implements SplitPointNameMarker { SplitOne, SplitTwo; } GWT.runAsync(SplitPoints.SplitOne, callback); GWT.runAsync(SplitPoints.SplitTwo, callback); To me, using MyClass.class as an identifier is a lot like using an open-ended enum, so it would make sense to me for runAsync to have three overloads: runAsync(Class id, AsyncCallback callback); runAsync(Enum id, AsyncCallback callback); runAsync(AsyncCallback callback); but I might be crazy. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 2:08 PM, Ray Cromwell wrote: > However, I'm curious, what is the effect of the following: > > GWT.runAsync("foo", callback1); > GWT.runAsync("bar", callback1); > > That would appear to me to generate identical code, but with two different > named output files. I think the case is more interesting if you do this: final MyAsyncCallback callback = chooseACallback(); GWT.runAsync("foo", callback); callback.mutate(); GWT.runAsync("bar", callback); The behaviour on the far side of the split would presumably be impacted by the mutation in step 3. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 5:08 PM, Lex Spoon wrote: > Thoughts? The main downside I know of is the one John Tamplin has > pointed out: if there are multiple runAsync calls within a single > class -- as sometimes happens -- then the programmer has to code up > some new classes that will only be used for naming. Can we live with > that? I think so. It's less anxiety-inducing to create a class as a moniker (even if it's a bit artificial) rather than fret about picking a good string literal ("will it collide?", "what naming scheme should I use?", "I wish I hadn't used that other naming scheme in that other part of the code...should I go fix it up right now?"). Plus, your IDE can help you create moniker classes and, when needed, efficiently rename/refactor them. --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 5:08 PM, Ray Cromwell wrote: > I prefer 4 as well, because I think it will be less prone to error and it is > more directly associated with the runAsync call. > However, I'm curious, what is the effect of the following: > GWT.runAsync("foo", callback1); > GWT.runAsync("bar", callback1); > That would appear to me to generate identical code, but with two different > named output files. Ideally, the compiler would figure out that they are the same and do something smart. Right now, though, the results would tend to be bad. > On the other hand, what about this: > GWT.runAsync("foo", callback1); > GWT.runAsync("foo", callback2); > here, two different callbacks try to use the same name. This is a subtopic common to any naming scheme: What happens if the same name is specified for two calls? It either needs to be a compile error, or a warning. Either way, the name is not allowed to be used. Lex --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
I prefer 4 as well, because I think it will be less prone to error and it is more directly associated with the runAsync call. However, I'm curious, what is the effect of the following: GWT.runAsync("foo", callback1); GWT.runAsync("bar", callback1); That would appear to me to generate identical code, but with two different named output files. On the other hand, what about this: GWT.runAsync("foo", callback1); GWT.runAsync("foo", callback2); here, two different callbacks try to use the same name. -Ray On Wed, Jun 24, 2009 at 11:26 AM, Ian Petersen wrote: > > On Wed, Jun 24, 2009 at 11:15 AM, Lex Spoon wrote: > > On Wed, Jun 24, 2009 at 12:48 PM, Ian Petersen > wrote: > >> The following should be allowed: > >> > >> @SplitPointName("foo") > >> final AsyncCallback callback = chooseACallback(); > >> > >> if (flipACoin()) > >> GWT.runAsync(callback); > >> else > >> GWT.runAsync(callback); > > > > I don't see how to literally allow that, because there are two calls > > to runAsync. The aren't allowed to have the same name. > > In retrospect, I don't know why I thought that case should be > allowable, but it seems we're converging on option 4, so nevermind. > > Ian > > > > --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 2:15 PM, Lex Spoon wrote: > Overall, unless I missed something, Okay, Bruce pointed out a new constraint to me: if different libraries name their runAsync calls, then we want to able to refer to those calls reliably even if different libraries choose the same name. This isn't an issue immediately, but it likely will be in the future. Thinking about libraries, I would add another constraint: we don't want libraries to have to expose their implementation. Library writers should ideally be able to document a named runAsync call without exposing the precise arrangement of their internal classes. After some discussion at the office, a tweak to option 4 fixes things up handily. Instead of passing in a string to the method, act like a Java framework and require passing in a class literal. A typical use in application code would pass in the enclosing top-level class: package org.foodity.impl; class Cookies { ... GWT.runAsync(Cookies.class, new RunAsyncCallback() { ... }); ... } A library writer could instead specify a public class, so as not to expose their internal factoring. A user of the name in a gwt.xml file would use the fully qualified version: A user in another Java file would use imports to make the name short: import org.foodity.impl.Cookies; RunAsyncQueue.startPrefetching(Cookies.class); Thoughts? The main downside I know of is the one John Tamplin has pointed out: if there are multiple runAsync calls within a single class -- as sometimes happens -- then the programmer has to code up some new classes that will only be used for naming. Can we live with that? Lex --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 11:15 AM, Lex Spoon wrote: > On Wed, Jun 24, 2009 at 12:48 PM, Ian Petersen wrote: >> The following should be allowed: >> >> @SplitPointName("foo") >> final AsyncCallback callback = chooseACallback(); >> >> if (flipACoin()) >> GWT.runAsync(callback); >> else >> GWT.runAsync(callback); > > I don't see how to literally allow that, because there are two calls > to runAsync. The aren't allowed to have the same name. In retrospect, I don't know why I thought that case should be allowable, but it seems we're converging on option 4, so nevermind. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 11:20 AM, John Tamplin wrote: > I prefer 4. As I said, I'm happy with 4. > What will the fallback behavior be for runAsync calls without a name -- an > automatically generated name? >From Lex's original post, it seems the name will be used to manipulate the split point from within the running program somehow. It would seem to me that an anonymous split would simply not be manipulatable and the name could be null, if it needs to be anything at all. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 2:15 PM, Lex Spoon wrote: > Overall, unless I missed something, it's down to style and taste. I'd > pick 1, then 4, then 6. Ian has indicated preferring 6, then 4, then > 1. I presume Cameron prefers 4 over anything else. Shall we go with > 4, then, everyone? > > // proposal 4 > GWT.runAsync("NameGoesHere", new RunAsyncCallback() { } ) > I prefer 4. What will the fallback behavior be for runAsync calls without a name -- an automatically generated name? -- John A. Tamplin Software Engineer (GWT), Google --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 12:48 PM, Ian Petersen wrote: > The following should be allowed: > > @SplitPointName("foo") > final AsyncCallback callback = chooseACallback(); > > if (flipACoin()) > GWT.runAsync(callback); > else > GWT.runAsync(callback); I don't see how to literally allow that, because there are two calls to runAsync. The aren't allowed to have the same name. However, they could be named differently even though they use the same callback, like this: AsyncCallback callback = chooseACallback(); if (flipACoin()) { @SplitPointName("foo") AsyncCallback callback1 = callback; GWT.runAsync(callback1); } else { @SplitPointName("bar") AsyncCallback callback2 = callback; GWT.runAsync(callback2); } It works fine, but IMHO it's verbose. Overall, unless I missed something, it's down to style and taste. I'd pick 1, then 4, then 6. Ian has indicated preferring 6, then 4, then 1. I presume Cameron prefers 4 over anything else. Shall we go with 4, then, everyone? // proposal 4 GWT.runAsync("NameGoesHere", new RunAsyncCallback() { } ) Going once going twice Lex --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Wed, Jun 24, 2009 at 9:32 AM, Lex Spoon wrote: > It's the *call* of runAsync that the compiler pays direct attention > to, not its argument. That's why I am pushing back against approaches > that annotate some aspect of the argument. I think the push-back is a really good idea. It seems like this is a tricky thing to get right and it would be a royal pain to redo it. My personal favourite is option 6, with some caveats. I think, to make option 6 work, you need the compiler to be able to prove that a given argument to runAsync is assigned exactly once before passing it to runAsync, and that it's not reused. I think you can satisfy the first requirement by requiring that the local is declared final. I don't know if it's possible to make sure it's not passed to two different runAsyncs. So, what I'm saying is this: // final is required to make sure callback is assigned only once @SplitPointName("foo") final AsyncCallback callback = chooseACallback(); GWT.runAsync(callback); // this should be a compiler error because it's a second split point with the same callback instance GWT.runAsync(callback); The following should be allowed: @SplitPointName("foo") final AsyncCallback callback = chooseACallback(); if (flipACoin()) GWT.runAsync(callback); else GWT.runAsync(callback); If it's not possible (or not feasible) to make it a compiler error to reuse a callback, then I prefer option 4 over option 1, but either would be fine. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
Is there any other design criterion that people can see? The main ones I see are that it's easy to implement and maintain, it's easy to spec, and that developers can use it without needing any major code refactor. That narrows it down to either an annotation on the method (option 1), or an extra argument to runAsync (option 4). Does object to flipping a coin between these two? On Tue, Jun 23, 2009 at 12:04 PM, Ian Petersen wrote: > On Tue, Jun 23, 2009 at 8:43 AM, Lex Spoon wrote: > That's a tough question to answer. I don't have a Java environment at > hand, so can someone remind me whether or not you're allowed to > annotate local variable declarations? If so, you could assign your > CakeMaker to an annotated local and then pass the local to runAsync. > I suspect you can't annotate locals, though It seems that they can. Proposal number 6. :) @RunAsyncName("Foo"); RunAsyncCallback callback = chooseMyCallback(...); GWT.runAsync(callback); However, I would dearly like to get this implemented and not add new proposals. Is there a reason to prefer this over the others? > In another vein, I am have second thoughts about Bruce's original > suggestion of annotating the type that's instantiated and passed to > runAsync. Is the ambiguity I mentioned a real problem or just a > phantom? Is the fragment beyond a given split point defined by the > callsite, the type of the argument to runAsync, or both? In other > words, suppose I have a concrete implementation of AsyncCallback > called MyCallback. If I invoke runAsync in two distinct places but > pass an instance of MyCallback to both, are the fragments on the > "other" side of the invocation the same or different? Does it matter > how MyCallback is implemented or if it's parameterized somehow? If > the concrete type of the argument to runAsync defines the fragment, > maybe it's enough to annotate the type. It's the *call* of runAsync that the compiler pays direct attention to, not its argument. That's why I am pushing back against approaches that annotate some aspect of the argument. Lex --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Tue, Jun 23, 2009 at 8:43 AM, Lex Spoon wrote: > On Mon, Jun 22, 2009 at 7:33 PM, Ian Petersen wrote: >> Here's what I mean: >> >> // ... surrounding code ... >> GWT.runAsync(new AsyncCallback() { >> public void onFailure(Throwable caught) { >> // deal with failure >> } >> >> @SplitPointName("I like Bruce's idea") >> public void onSuccess() { >> // deal with success >> } >> }); >> // ... surrounding code ... >> >> I'm not sure if it's better or worse, but it seems more flexible than >> requiring a surrounding method. > > Okay, call it proposal 5, annotation of onSuccess methods. > > I'm not clear on how we should associate onSuccess methods with > runAsync calls in the general case. Note that the argument to > runAsync doesn't currently have to be an anonymous inner class: > > class Bakery { > private static class CakeMaker implements RunAsyncCallback {...} > public static void makeOrder(CakeType cake) { > GWT.runAsync(new CakeMaker(cake)); > } > } > > It gets even more interesting if the CakeMaker type is abstract, and > the implementation is made by a builder class. The builder might even > have multiple implementations: > > class Bakery { > private static abstract class CakeMaker implements RunAsyncCallback { } > private static class CakeMakerBuilder { > ... > public CakeMaker build() { > class CakeMakerImpl1 extends CakeMaker { > public void onSuccess() { ... } > } > class CakeMakerImpl1() { > public void onSuccess() { ... } > } > if (someConfigProperty) { return new CakeMakerImpl1(); } else { > return new CakeMakerImpl2() } > } > } > } > > > Which onSuccess method(s) should be annotated, and how should GWT > interpret those annotations? That's a tough question to answer. I don't have a Java environment at hand, so can someone remind me whether or not you're allowed to annotate local variable declarations? If so, you could assign your CakeMaker to an annotated local and then pass the local to runAsync. I suspect you can't annotate locals, though I'm officially stumped--I'm probably too far removed from the code. It seems to me that the two most viable options are annotating the surrounding method as Lex originally suggested or adding a string literal parameter to runAsync as Cameron suggested. In another vein, I am have second thoughts about Bruce's original suggestion of annotating the type that's instantiated and passed to runAsync. Is the ambiguity I mentioned a real problem or just a phantom? Is the fragment beyond a given split point defined by the callsite, the type of the argument to runAsync, or both? In other words, suppose I have a concrete implementation of AsyncCallback called MyCallback. If I invoke runAsync in two distinct places but pass an instance of MyCallback to both, are the fragments on the "other" side of the invocation the same or different? Does it matter how MyCallback is implemented or if it's parameterized somehow? If the concrete type of the argument to runAsync defines the fragment, maybe it's enough to annotate the type. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Mon, Jun 22, 2009 at 7:33 PM, Ian Petersen wrote: > Here's what I mean: > > // ... surrounding code ... > GWT.runAsync(new AsyncCallback() { > public void onFailure(Throwable caught) { > // deal with failure > } > > @SplitPointName("I like Bruce's idea") > public void onSuccess() { > // deal with success > } > }); > // ... surrounding code ... > > I'm not sure if it's better or worse, but it seems more flexible than > requiring a surrounding method. Okay, call it proposal 5, annotation of onSuccess methods. I'm not clear on how we should associate onSuccess methods with runAsync calls in the general case. Note that the argument to runAsync doesn't currently have to be an anonymous inner class: class Bakery { private static class CakeMaker implements RunAsyncCallback {...} public static void makeOrder(CakeType cake) { GWT.runAsync(new CakeMaker(cake)); } } It gets even more interesting if the CakeMaker type is abstract, and the implementation is made by a builder class. The builder might even have multiple implementations: class Bakery { private static abstract class CakeMaker implements RunAsyncCallback { } private static class CakeMakerBuilder { ... public CakeMaker build() { class CakeMakerImpl1 extends CakeMaker { public void onSuccess() { ... } } class CakeMakerImpl1() { public void onSuccess() { ... } } if (someConfigProperty) { return new CakeMakerImpl1(); } else { return new CakeMakerImpl2() } } } } Which onSuccess method(s) should be annotated, and how should GWT interpret those annotations? Lex Spoon --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
+1 Ian! Great point. Not sure why we didn't think of that before. On Monday, June 22, 2009, Ian Petersen wrote: > > On Mon, Jun 22, 2009 at 2:08 PM, Lex Spoon wrote: >> The options I see are: >> 1. Annotate the surrounding method with something like @RunAsyncName("Foo") >> 2. Use the fully-qualified method name surrounding the call. >> 3. Use the fully-qualified type name of the callback object. >> 4. Use a new parameter to runAsync indicating the name. > > One possible refinement to option 1, since it seems likely to "win": > put the annotation on the onSuccess rather than on the method that > contains the runAsync invocation. > > Here's what I mean: > > // ... surrounding code ... > GWT.runAsync(new AsyncCallback() { > > public void onFailure(Throwable caught) { > // deal with failure > } > > @SplitPointName("I like Bruce's idea") > public void onSuccess() { > // deal with success > } > }); > // ... surrounding code ... > > I'm not sure if it's better or worse, but it seems more flexible than > requiring a surrounding method. > > To be a little bit forgiving to the developer, you could make it a > compile-time warning if onFailure is annotated and an error if both > onFailure and onSuccess are annotated with different names--it makes > the generator code more complex but lets the user be a little bit > forgetful. Not sure if that's really necessary, though. > > Ian > > > > --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Mon, Jun 22, 2009 at 2:08 PM, Lex Spoon wrote: > The options I see are: > 1. Annotate the surrounding method with something like @RunAsyncName("Foo") > 2. Use the fully-qualified method name surrounding the call. > 3. Use the fully-qualified type name of the callback object. > 4. Use a new parameter to runAsync indicating the name. One possible refinement to option 1, since it seems likely to "win": put the annotation on the onSuccess rather than on the method that contains the runAsync invocation. Here's what I mean: // ... surrounding code ... GWT.runAsync(new AsyncCallback() { public void onFailure(Throwable caught) { // deal with failure } @SplitPointName("I like Bruce's idea") public void onSuccess() { // deal with success } }); // ... surrounding code ... I'm not sure if it's better or worse, but it seems more flexible than requiring a surrounding method. To be a little bit forgiving to the developer, you could make it a compile-time warning if onFailure is annotated and an error if both onFailure and onSuccess are annotated with different names--it makes the generator code more complex but lets the user be a little bit forgetful. Not sure if that's really necessary, though. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
Great writeup. Thanks for bringing some organization to the thread. I agree with you that #1 seems overall best after the analysis. Now can we bikeshed about the annotation name? @RunAsyncName() seems harder to understand than something that says "code splitting", such as @SplitPointName("Foo"). After all, we do call these things "split points". On Mon, Jun 22, 2009 at 5:08 PM, Lex Spoon wrote: > > Okay, we now have a suite of options. Does anyone see any > particularly strong reason to pick among them? > > The options I see are: > 1. Annotate the surrounding method with something like @RunAsyncName("Foo") > 2. Use the fully-qualified method name surrounding the call. > 3. Use the fully-qualified type name of the callback object. > 4. Use a new parameter to runAsync indicating the name. > > #2 is what's in trunk right now, but it is quite verbose. I think we > shouldn't stick with that unless we can make it more concise. One way > to do htat would be to make JSNI references more concise if they refer > to a method that isn't overloaded. We could let "*" be used as the > parameter list in that case. As much as I like that idea, it would > take a few days to implement, so the opportunity cost would be high. > > For #3, it's not necessarily unambiguous, as pointed out. Thus, it > loses one of the main feature of #2. Additionally, it looks harder to > spec to me. We would have to tell people something like: to name a > runAsync call, make sure to put the call within a method with at least > one argument, and then specify the type of that first argument. Can > anyone tighten up that spec and make it competitive? > > Overall, both #2 and #3 take extra work compared to the others. #2 > requires implementation work, and #3 requires at the least some extra > working to spec it. > > #1 and #4 both look good to me, though I admit a slight preference for > #1. That slight preference is mainly because it would mean we get to > stick with a single GWT.runAsync method in the magic GWT class, which > seems better for a few small reasons. That said, we could certaily go > that route if there's a reason to prefer it. > > Thoughts welcome. I still think the annotations (option 1) look good, > but don't want to push for that it if will cause some trouble or miss > some opportunity. Is there a reason to prefer 4 over 1? Is 2 or 3 > worth the extra work, or else, does anyone see how to make 2 or 3 > easier to implement? > > > Lex > > > > --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
Okay, we now have a suite of options. Does anyone see any particularly strong reason to pick among them? The options I see are: 1. Annotate the surrounding method with something like @RunAsyncName("Foo") 2. Use the fully-qualified method name surrounding the call. 3. Use the fully-qualified type name of the callback object. 4. Use a new parameter to runAsync indicating the name. #2 is what's in trunk right now, but it is quite verbose. I think we shouldn't stick with that unless we can make it more concise. One way to do htat would be to make JSNI references more concise if they refer to a method that isn't overloaded. We could let "*" be used as the parameter list in that case. As much as I like that idea, it would take a few days to implement, so the opportunity cost would be high. For #3, it's not necessarily unambiguous, as pointed out. Thus, it loses one of the main feature of #2. Additionally, it looks harder to spec to me. We would have to tell people something like: to name a runAsync call, make sure to put the call within a method with at least one argument, and then specify the type of that first argument. Can anyone tighten up that spec and make it competitive? Overall, both #2 and #3 take extra work compared to the others. #2 requires implementation work, and #3 requires at the least some extra working to spec it. #1 and #4 both look good to me, though I admit a slight preference for #1. That slight preference is mainly because it would mean we get to stick with a single GWT.runAsync method in the magic GWT class, which seems better for a few small reasons. That said, we could certaily go that route if there's a reason to prefer it. Thoughts welcome. I still think the annotations (option 1) look good, but don't want to push for that it if will cause some trouble or miss some opportunity. Is there a reason to prefer 4 over 1? Is 2 or 3 worth the extra work, or else, does anyone see how to make 2 or 3 easier to implement? Lex --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
You could always change the signiture of GWT.runAsync to include a String parameter as the first parameter. I must be a literal in code, and would be optimized out / ignored by the compiler : GWT.runAsync("foo", new RunAsyncCallback() { Cam 2009/6/20 Lex Spoon > > There are multiple reasons that people end up wanting a way to name > calls to runAsync. One of them is the specification of an initial > load sequence that I just implemented. Looking ahead, they would be > useful for prefetch requests. It's hard to say "download fragment Foo > if you can", if you don't have a way to name fragment "Foo". > > > To name the calls, ideal would be if a Java annotation could be put on > the method call. Unfortunately, Java annotations cannot currently be > placed on a method call. One fallback would be to annotate the class > that is passed into the call. This is problematic, too, however, > because in Java 5 and 6 you can't annotate an anonymous inner class. > > As a next best approach, what would people think of annotating the > surrounding method? In practice, there is only one runAsync call > within a single method. We could, at least to start with, insist that > any named runAsync must be in its own method. Note that this is never > a real constraint on people's code, because they can always split out > a large method into two smaller ones, each of which has its own > runAsync call. It would look like this: > > @RunAsyncName("CwBasicButton") > @Override > protected void asyncOnInitialize(final AsyncCallback callback) { >GWT.runAsync(new RunAsyncCallback() { > > public void onFailure(Throwable caught) { >callback.onFailure(caught); > } > > public void onSuccess() { >callback.onSuccess(onInitialize()); > } >}); > } > > > Since typical programs have well under 100 calls to runAsync, I don't > think any sort of hierarchical naming scheme is necessary. Simple > identifiers, such as "CwBasicButton", look like they would work. > > This looks like a straightforward and easily understood way to name > calls to runAsync. What do others think? > > Lex > > > > --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Fri, Jun 19, 2009 at 10:22 AM, Ian Petersen wrote: > On Fri, Jun 19, 2009 at 9:57 AM, Bruce Johnson wrote: >> My worry about Ian's proposal is >> that method overloading complicate things > > Excellent point--wasn't thinking about overloads. Now that I've had more time to think, my RunAsyncRef constructor could have this signature: public RunAsyncRef(Class enclosingType, String methodName, Class... argumentTypes) Not sure if that's better or worse than JSNI syntax, but it solves the overload problem. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
I've been working to improve load behavior of a very large application with a few dozen runAsync calls, and for Javadoc clarity I've been putting each call in its own method anyway -- found this very useful to track the purpose and timing of each split, and document any known implications. So in practice, this enclosing method seems like a natural place to hang these annotations. I do like Ian's idea too, as I have general trouble tracking the concordance of extra naming symbols to the methods they annotate. APIs that do a lot of this keep me dancing on ctrl-H in Eclipse. - R On Fri, Jun 19, 2009 at 11:44 AM, Ian Petersen wrote: > > On Fri, Jun 19, 2009 at 8:33 AM, Lex Spoon wrote: > > This looks like a straightforward and easily understood way to name > > calls to runAsync. What do others think? > > As a brainstorm-quality idea, what about requiring that runAsync > invocations are in their own methods (as you mentioned) but not > requiring an annotation? Any given method already has a fully > qualified name (it's even globally unique within the program) so why > introduce yet another name in the annotation? > > Some compiler magic to make this happen might be a nice-to-have: > > RunAsyncRef ref = new RunAsyncRef(ClassContainingMethod.class, > "methodName"); > > You could statically determine that it's valid, use ref as a token to > refer to fragments as necessary, and avoid having to specify > package.ClassName.methodName because you take advantage of the import > statements. Dunno what you'd do with it, of course. > > Ian > > > > --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Fri, Jun 19, 2009 at 9:57 AM, Bruce Johnson wrote: > My worry about Ian's proposal is > that method overloading complicate things Excellent point--wasn't thinking about overloads. I think your solution might be more elegant--it seems easier to explain, understand, and enforce "must sub-interface" than "must invoke from unique method". One potential problem I see, and Lex will have to say whether or not it's a real problem, is that your solution provides a name for the type, not the invocation and could thus be ambiguous. Using a method name names the invocation. > (would you use JSNI-style refs to disambiguate?). Using JSNI seems like a pain. If using a method name is even a good idea, maybe the spec could require that the method in question have a particular signature. Then overloads would be irrelevant. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
A slight tweak to what Ian said: What if we got this effect by simpy requiring you to use interfaces that extend AsyncCallback as a way to reify split points? interface EmailCompositionView extends AsyncCallback { ... } Then you definitely have a fully-qualified name for a split point if you need it: the name of the interface itself. My worry about Ian's proposal is that method overloading complicate things (would you use JSNI-style refs to disambiguate?). And my worry with user-assigned names is that actually may conflict, when you consider that library writers probably will want to ship libraries with split points. Again, using interfaces guarantees we don't introduce a new axis of name conflict. -- Bruce On Fri, Jun 19, 2009 at 11:44 AM, Ian Petersen wrote: > > On Fri, Jun 19, 2009 at 8:33 AM, Lex Spoon wrote: > > This looks like a straightforward and easily understood way to name > > calls to runAsync. What do others think? > > As a brainstorm-quality idea, what about requiring that runAsync > invocations are in their own methods (as you mentioned) but not > requiring an annotation? Any given method already has a fully > qualified name (it's even globally unique within the program) so why > introduce yet another name in the annotation? > > Some compiler magic to make this happen might be a nice-to-have: > > RunAsyncRef ref = new RunAsyncRef(ClassContainingMethod.class, > "methodName"); > > You could statically determine that it's valid, use ref as a token to > refer to fragments as necessary, and avoid having to specify > package.ClassName.methodName because you take advantage of the import > statements. Dunno what you'd do with it, of course. > > Ian > > > > --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---
[gwt-contrib] Re: naming runAsync calls
On Fri, Jun 19, 2009 at 8:33 AM, Lex Spoon wrote: > This looks like a straightforward and easily understood way to name > calls to runAsync. What do others think? As a brainstorm-quality idea, what about requiring that runAsync invocations are in their own methods (as you mentioned) but not requiring an annotation? Any given method already has a fully qualified name (it's even globally unique within the program) so why introduce yet another name in the annotation? Some compiler magic to make this happen might be a nice-to-have: RunAsyncRef ref = new RunAsyncRef(ClassContainingMethod.class, "methodName"); You could statically determine that it's valid, use ref as a token to refer to fragments as necessary, and avoid having to specify package.ClassName.methodName because you take advantage of the import statements. Dunno what you'd do with it, of course. Ian --~--~-~--~~~---~--~~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~--~~~~--~~--~--~---