I have only recently started using DeferredCommand, but figure it
might not hurt to throw in a GWT Command interface novice's
impressions to the discussion. The current DeferredCommand presents an
interface that feels like a Collection interface but behaves like an
Executor. The API modification suggestions all appear to reuse this
paradigm. However, if DeferredCommand (or a CommandDispatcher) is
effectively an Executor, doesn't it make sense to call it an Executor?
Refactoring from the current DeferredCommand could look something like
this:

//interface for GWT based Executor's
//could be renamed to Executor under GWT's packages
interface GwtExecutor {
  public void submitCommand( Command command );
  public void submitIncrementalCommand ( IncrementalCommand command );
  public void submitPause();
}

// execute code after all currently pending event handlers have
completed
class DeferredExecutor implements GwtExecutor {
  public static DeferredExecutor get();
}

//execute before you end the current stack trace
class FinallyExecutor implements GwtExecutor {
  public static FinallyExecutor get();
}

Note, this makes conceptual reuse of the good things in the Java
Executor and ExecutorService without using the actual interface itself
and any baggage that might include. Also, adding a one-off execution
model becomes a new implementation of GwtExecutor.

Along these lines, I'd like to add another voice to the discussion of
adding Runnable and Callable<V> to the JRE emulation.  I don't see any
technical difference between JRE's Runnnable and GWT's Command
interfaces beyond the method names, and would therefore assume any
limitations on exception throwing with Runnable should be true for
Command. Assuming the association of Runnable with Thread and Callable
with Executor packages is not a deal breaker, then here's a possible
GwtExecutor API:

interface GwtExecutor {
  public void submit( Runnable run );
  public <T> void submit( Callable<V> callable, AsyncCallback<V>
callback );
  public <T> void submitUntilFalse( Callable<Boolean> callable );
  public void submitPause();
}

Using the above, submitUntilFalse() replaces submitIncrementalCommand
(), though there may be a better way to implement the concept. The use
of AsyncCallback<V> when submitting a Callable<V> allows for some
Future<V> like behavior, and possibly some more interesting code
flows.

I didn't include a TimedExecutor above because to me time-based
execution of a Command or a Runnable has more in common with a
scheduler conceptual model than an Executor. Also, I think its cleaner
to only associate things that define when an item is executed within
the stack/event flow as Executors.. For what its worth, here's a
delayed scheduler example using Runnable and Callable<V>:

class DelayScheduler {
  public static Scheduler get();
  public ScheduleController scheduleOnce( Runnable run, int millis );
  public ScheduleController scheduleRecurring( Runnable run, int
millis );
  public <T> ScheduleController scheduleOnce( Callable<T> callable,
AsyncCallback<T> callback, int millis );
  public <T> ScheduleController scheduleRecurring( Callable<T>
callable, AsyncCallback<T> callback, int millis );
}

interface ScheduleController {
  public void pause();
  public void resume();
  public void cancel();
}

I've already gotten fairly long winded here, but one final point I'd
like to make is that regardless of approach, I think the current
Command interface should be kept for the simpler case of adding a
Command to a MenuItem. I don't think that would be well served by
making either a Command that takes a dispatcher in its execute method
or using Runnable.

V/r,

Jason A. Beranek


On Sep 5, 11:35 am, Eric Ayers <[email protected]> wrote:
> Just to flush out my dissention a little more, I don't see what
> re-architecting it is going to do for the user experience, and I know
> it is going to cause at least as much pain as benefit for the
> developer experience.
>
> I love writing shiny new APIs too, but going with the minimal screwing
> with the API approach, you could just make a new
> DeferredCommand.addBatchedCommand(Command cmd) and get this new
> functionality and be done with it.
>
> 1) The new  dispatch-my-command-before-the-event-loop may be important
> for the Css injection case, but I haven't seen any suggestion that its
> going to be used for anything other than that - an important, but very
> infrequently used feature.
>
> 2) If you want to make a new testable deferred/incremental command
> class, fine, you can do that, but I don't think it requires yet
> another round of deprecating deferred command stuff - you can write it
> on top.  Again, most developers aren't going to be mocking out and
> overriding timers for their test cases, yet the implication is that
> all developers need this (they don't)
>
> 3) Look at what will happen to the API after the suggested round of
> deprecations.  There will be more ways NOT to do something than the
> recommended way to actually get work done.  And pedantic arguments
> aside, it will be yet another collection of custom class names where
> we could have used 'Runnable' and 'Callable' that java developers are
> already familiar with.
>
> All I'm asking is for us to think about, "Is a shiny new API it really
> worth the ugliness for developers?  Do users get something significant
> in return for developer pain?"
>
> Signed,
> A developer
>
>
>
>
>
> On Fri, Sep 4, 2009 at 11:36 PM, Eric Ayers<[email protected]> wrote:
> > -1 for renaming and deprecating the DeferredCommand, etc calls unless
> > there is really something significant other than the name change.   As
> > a maintainer, I get sick of APIs moving around underneath my code and
> > having someone else tell me its broken.  Furthermore, you'll make
> > obsolete every good tutorial and blog post already written that tells
> > you how to do fun stuff in GWT with these tools.
>
> > On Fri, Sep 4, 2009 at 11:00 PM, Miroslav
> > Pokorny<[email protected]> wrote:
>
> >> Slightly off topic more of a design comment.
>
> >> For me Job would be a better name than Command. Command reminds me of
> >> the command pattern while job is always a background task that might
> >> execute sooner or later.
>
> >> It also seems like there are lots of "duplicate" add methods for lack
> >> of a better of description, whereby each type of Command has it's own.
> >> What about a central manager type class with a single add( Job,
> >> JobType) where JobType is Incremental, Timed, etc.
>
> >> For the Timed version there would be factory to pass the when or how
> >> often etc, or as in the previous email from Bruce AsapJob.
>
> >> I can also see a benefit of allowing developers to change the command
> >> (job) type by changing the JobType parameter which seems simpler /
> >> more flexible than the hard coded static adds and super type.
>
> >> Just an idea...
>
> >> On 05/09/2009, at 4:35 AM, Ray Ryan <[email protected]> wrote:
>
> >>> I like the Finally name.
>
> >>> Since you have a single Command object used by Incremental along
> >>> with everyone else, you're implying interface
>
> >>> Command {
> >>>   /**
> >>>    * @return whether this command should be run again.
> >>>    * Checked only by {...@link IncrementalCommands} and {...@link
> >>> TimedCommands}
> >>>    */
> >>>   boolean execute();
> >>>  }
>
> >>> That's a bit redundant with the TimerController--would it even be
> >>> honored by TimedCommands?
>
> >>> Let me propose this (actually, I think steal it from Brian Brian
> >>> Slesinsky) , to allow every command to reschedule itself or not.
>
> >>> rjrjr
>
> >>> interface Command {
> >>>   /**
> >>>    * @param dispatcher To allow this command to requeue
> >>>    *    itself, or add other commands. Presto, it's
> >>>    *    all three of timed, incremental and one off
> >>>    */
> >>>   void execute(CommandDispatcher dispatcher);
> >>> }
>
> >>> interface CommandDispatcher {
> >>>   enum When {
> >>>     FINALLY,
> >>>     ASAP
> >>>   }
>
> >>>   public static CommandDispatcher get();
>
> >>>   public void add(Command c);
>
> >>>   public void add(Command c, When w);
>
> >>>   public void addDeferred(Command c, int millis);
> >>> }
>
> >>> That's the whole thing. For convenience, we could also offer stuff
> >>> like the following. Perhaps
> >>> // better to see what evolves
>
> >>> abstract class IncrementalCommand implements Command {
> >>>   public void execute(CommandDispatcher dispatcher) {
> >>>     if (doExecute()) {
> >>>       dispatcher.add(this);
> >>>     }
> >>>   }
>
> >>>   /** @return true to keep going */
> >>>   abstract boolean doExecute();
> >>> }
>
> >>> and
>
> >>> public class TimedCommand implements Command {
> >>>   private final wrappedCommand;
> >>>   private final interval millis;
> >>>   private boolean stopped;
>
> >>>   public TimedCommand(int millis, Command wrappedCommand) {
> >>>     this.wrappedCommand = wrappedCommand;
> >>>     this.millis = millis;
> >>>   }
>
> >>>   public void stop() {
> >>>     stopped = true;
> >>>   }
>
> >>>   public void execute(CommandDispatcher dispatcher) {
> >>>     if (!stopped) {
> >>>       wrappedCommand.execute(dispatcher);
> >>>       dispatcher.add(this, millis);
> >>>     }
> >>>   }
> >>> }
>
> > --
> > Google Code Jam 2009
> >http://code.google.com/codejam
>
> --
> Google Code Jam 2009http://code.google.com/codejam

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

Reply via email to