Because the dispatcher methods are not static you can write your code to
have the dispatcher injected, and at test time provide whatever alternative
implementation you want. So long as you don't use the static get method
outside of your Gin module or whatever, you're golden.
Not good enough?

On Fri, Sep 4, 2009 at 12:20 PM, Brian Slesinsky <bslesin...@gmail.com>wrote:

>
> How do we test methods that schedule commands?
>
> Maybe there should be a way to test that a method schedules some
> commands without actually executing them? From a testing point of
> view, it would be nice to be able to push a context that captures all
> commands, call the method under test, and then pop the context and
> verify that it contains the commands you expect. (The API should be
> optimized away if it's not used, which would usually be the case in
> production.)
>
> Alternately, you might want to have a way to force commands scheduled
> by the method under test to run before doing your assertions, so that
> you can verify that the method under test had its intended effect,
> regardless of whether it uses commands to accomplish it.  I think if
> you can capture commands, then you could do this too. (It gets tricky
> to do if commands can schedule other commands, so it's worth writing a
> test utility, but probably doesn't require anything more than
> capturing from the core API.)
>
> - Brian
>
> On Sep 3, 7:08 pm, Bruce Johnson <br...@google.com> wrote:
> > Okay, here's a strawman for a new-and-improved proposal. All these would
> be
> > in core.
> > // "Deferred command" = on the other side of the event loop
> > interface DeferredCommands {
> >   public static DeferredCommands get();
> >
> >   public void add(Command cmd);
> >   public void add(Command cmd, boolean asap);  // asap = faster than
> > setTimeout(0)
> >   public void addPause();
> >
> > }
> >
> > // "Finally command" = before you end the current stack trace
> > interface FinallyCommands {
> >   public static FinallyCommands get();
> >
> >   public void add(Command cmd);
> >
> > }
> >
> > // "Incremental command" = call repeatedly quickly to avoid SSWs
> > interface IncrementalCommands {
> >   public static IncrementalCommands get();
> >
> >   public void add(Command cmd);
> >   public void add(Command cmd, boolean asap);
> >
> > }
> >
> > // "Timed command" = call based clock time (aka regular old timers)
> > interface TimedCommands {
> >   public static TimedCommand get();
> >
> >   public TimerController scheduleOnce(Command cmd, int millis);
> >   public TimerController scheduleRecurring(Command cmd, int millis);
> >
> > }
> >
> > // Allows optional control over a timer after it's created.
> > // If the return values in scheduleOnce, etc. aren't used, extra code can
> > maybe optimize away.
> > interface TimerController {
> >   public void pause();
> >   public void resume();
> >   public void cancel();
> >
> > }
> >
> > I think that maybe consolidating timers into this mix might be a bit
> much,
> > but, then again, if we're graduating "Command" to core, then it seems
> like
> > it would be nice to make it the uniform callback interface.
> >
> > -- Bruce
> >
> >
> >
> > On Thu, Sep 3, 2009 at 9:28 PM, Bruce Johnson <br...@google.com> wrote:
> > > I like it a lot Ray. (To be completely honest, I knew you were going to
> say
> > > all that, so I decided to sandbag and let you do the typing :-)
> >
> > > I question if it's really appropriate to explicitly say "PreEventLoop"
> and
> > > "PostEventLoop" considering that...sometimes...the event loop can
> actually
> > > run re-entrantly. Those names sound like a very strong guarantee that I
> > > don't think we can reliably guarantee. It's more like
> > > "PreCurrentJavaScriptStackFullyUnwinding" and "PostEventLoop".
> >
> > > Actually, to take a step back (which is my very favorite thing to do),
> > > there are several kinds of things that could be consolidated:
> >
> > > 1) Single-shot timers
> > > 2) Recurring timers
> > > 3) Incremental commands that run as soon as possible after the event
> loop
> > > (faster than setTimeout(0))
> > > 4) Incremental commands that run after the event loop via setTimeout(0)
> > > 5) Deferred commands that run as soon as possible after the event loop
> > > (faster than setTimeout(0))
> > > 6) Deferred commands that run after the event loop via setTimeout(0)
> > > 7) Execute-this-before-you-unwind-the-JS-stack-in-which-it-was-enqueued
> > > (aka BatchedCommand)
> > > 8) Arguably, runAsync (although it's purpose is so functionally
> different
> > > it would probalby be a mistake to munge it in)
> >
> > > #3 and #5 might look funny, but it is generally possible to run code
> > > *after* the event loop but *much* sooner than setTimeout(0), which is
> > > usually clamped to some pretty long duration such as 10ms. The reason
> you
> > > wouldn't want to do #3 and #5 as the default for deferred commands is
> that
> > > it would keep the CPU overly busy if you did it a bunch in a row. It
> would
> > > very likely drain mobile batteries quickly, even.
> >
> > > @Ray (or anyone): Can you think of an awesome way to reconcile those
> behind
> > > a consistent API?
> >
> > > On Thu, Sep 3, 2009 at 4:52 PM, Joel Webber <j...@google.com> wrote:
> >
> > >> ++(++Ray)
> > >> Anything we can do to sensibly get this crap out of .user and into
> .core
> > >> (or some other common location) would be very, very good.
> > >> If, as a side-effect, we could get DeferredCommand to *not* use
> > >> IncrementalCommand (the latter brings in fairly significant
> dependencies
> > >> that are enough to matter for small apps), that would be even better.
> >
> > >> On Thu, Sep 3, 2009 at 4:46 PM, Scott Blum <sco...@google.com> wrote:
> >
> > >>> ++Ray.
> >
> > >>> On Thu, Sep 3, 2009 at 4:38 PM, Ray Ryan <rj...@google.com> wrote:
> >
> > >>>>   The mechanism is just brilliant. I have reservations about the
> api.
> >
> > >>>> <bikeshed>
> > >>>> "it seemed kinda nice to have one less type"
> >
> > >>>> Except that we have one more type, BatchedCommand, which looks
> exactly
> > >>>> like Command, except with a different name, and you have to subclass
> it
> > >>>> rather than implement it...
> >
> > >>>> A simple thing we could do is:
> >
> > >>>>    - create com.google.gwt.core.client,
> > >>>>    - change com.google.gwt.user.client.Command to extend the new one
> > >>>>    - deprecate com.google.gwt.user.client.Command
> > >>>>    - And have BatchedCommand accept com.google.gwt.core.client
> >
> > >>>> And the two names, "DeferredComand" and "BatchedCommand", don't give
> > >>>> much clue as to which does what. And of course BatchedCommand
> doesn't
> > >>>> actually provide any batching service.
> >
> > >>>> If we were doing all this from scratch, I suspect we would wind up
> with
> > >>>> something like this in core (presuming we're happy with
> IncrementalCommand
> > >>>> and addPause):
> >
> > >>>>     package com.google.gwt.core.dispatch
> >
> > >>>>     public interface Command {
> > >>>>       void execute();
> > >>>>     }
> >
> > >>>>     public interface IncrementalCommand {
> > >>>>       boolean execute();
> > >>>>     }
> >
> > >>>>     public class PreEventLoopDispatcher {
> > >>>>       public static PreEventLoopDispatcher get(); { ... }
> >
> > >>>>       public void addCommand(Command c);
> > >>>>     }
> >
> > >>>>     public class PostEventLoopDispatcher {
> > >>>>       public static PostEventLoopDispatcher get(); { ... }
> >
> > >>>>       public void addCommand(Command c);
> > >>>>       public void addCommand(IncrementalCommand c);
> > >>>>       public void addPause();
> > >>>>     }
> >
> > >>>> Note the avoidance of statics to make commands more testable, a
> > >>>> recurring subject.
> >
> > >>>> Seems like we could do this, deprecate the existing classes, and
> make
> > >>>> them wrappers around the new.
> >
> > >>>> </bikeshed>
> >
> > >>>> On Wed, Sep 2, 2009 at 11:36 PM, Ray Cromwell <
> cromwell...@gmail.com>wrote:
> >
> > >>>>> Could this also be used as a general pattern to batch DOM updates
> from
> > >>>>> multiple Widgets performing updates? e.g. a current approach to
> avoid the
> > >>>>> overhead, of say, installing a dozen widgets, is to concatenate all
> the HTML
> > >>>>> together, slam it into innerHTML, and then wrap the widgets around
> the HTML.
> > >>>>> But this rather breaks the nice OO design people are used to with
> widgets.
> > >>>>> Templating is an alternative, but I'm wondering, why can't we make
> all of
> > >>>>> the attachment stuff happen via a batch queue. A special optimizer
> on the
> > >>>>> queue could even recognize instances of when DOM updates can be
> coalesced
> > >>>>> and leverage documentFragment or innerHTML.
> > >>>>> e.g.
> >
> > >>>>> VerticalPanel vp = ...
> > >>>>> vp.add(new Label())
> > >>>>> vp.add(new Label())
> >
> > >>>>> The objects are constructed, but the HTML mutations are
> > >>>>> deferred/queued. When adding a DOM mutation to the queue, you could
> check if
> > >>>>> existing queue data isOrHasChild the new DOM mutation element, and
> if so,
> > >>>>> just modify the queue element (coalesce) rather than appending
> another queue
> > >>>>> item. Then, when processing the queue, you only need to add the
> roots to the
> > >>>>> DOM, attaching/modifying enmasse.
> >
> > >>>>> This would preserve the OO-ness of constructing widget hierarchies
> > >>>>> without requiring 'foreign' string-based templating.
> >
> > >>>>> -Ray
> >
> > >>>>>  On Wed, Sep 2, 2009 at 5:13 PM, Bruce Johnson <br...@google.com
> >wrote:
> >
> > >>>>>>  On Wed, Sep 2, 2009 at 6:07 PM, Scott Blum <sco...@google.com
> >wrote:
> >
> > >>>>>>> I do agree with John that we should really discuss how this can
> be
> > >>>>>>> implemented.
> >
> > >>>>>> It's already implemented!
> >
> > >>>>>>>  Is there some magic trick to make the browser execute a piece of
> > >>>>>>> code at the time you want, or do we need to go and modify all our
> event code
> > >>>>>>> (like with the global uncaught exception handler)?
> >
> > >>>>>> No trick, it's as bad as you'd hope it wasn't. On the positive
> side,
> > >>>>>> it's already been done -- I'm just augmenting the tests for the
> various
> > >>>>>> subsystems such as RequestBuilder and event dispatching to make
> sure we
> > >>>>>> tighten the correctness noose as much as possible.
> >
> > >>>>>> Longer term, Bob and I both would really like to find a general
> > >>>>>> mechanism for making this pattern easy to do from any path into a
> GWT module
> > >>>>>> from "the outside", exactly along the lines of what Matt was
> talking about.
> > >>>>>> I think rolling this functionality into gwt-exporter (and then
> rolling that
> > >>>>>> sort of functionality directly into GWT proper) will get us pretty
> far down
> > >>>>>> the road.
> >
> > >>>>>> Code review request forthcoming, possibly tomorrow.
> >
> > >>>>>> -- Bruce
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to