views:

108

answers:

1

According to this video here Google is recommending the use of the command pattern on top of its request handling API. There is also a helpful looking project gwt-dispatch that implements that pattern.

According to gwt-dispatch documentation I need to create four classes for each command:

  • an action (e.g. command)
  • a result (e.g. response)
  • an action handler
  • a module

Assume my service API has 100 methods across 8 BSOs, can somebody explain to me why I want to create nearly 400 new classes? What awesomeness does this pattern buy?

+3  A: 
  • One good reason to use the command pattern is, when you want to pass the command object to further delegates - so instead of copying all the arguments, it's easier to just pass the command object around. It's also useful for gwt-dispatch's rollback functionality (or the undo/redo functionality e.g. in Eclipse's UndoableOperations).

  • It helps to provide serveral variations of commands by using different constructors, and subclasses of commands.

  • I would not suggest to always use the pattern, but you don't save as much as you think, when you don't use it: You will often need result objects anyway - and it's possible to reuse the same return objects. In other cases, you can use the same object for the command and for the result.

  • The module can be used for multiple commands.

Chris Lercher
To support undo, presumably then one would have to persist these command objects on the server, or (more likely) keep them within the application state on the client, yes?
HDave
@HDave Where to store the commands for a later undo depends on the application. But the advantage of the pattern for the undo case is, that the command objects can store the necessary state, and it's also a good place to provide the "reverse" code.
Chris Lercher
In addition to undo/redo functionality, the command pattern also makes batching and caching much easier. When you have one service that transmits a `List<Command>` it's easy to have that service wait some short amount of time to send them all together rather than sending multiple HTTP requests. And caching of results is easy with a `Map<Command, Result>` that will quickly return the last results of a common command.
Jason Hall
@Jason - I totally get how it would help with caching. Simple compare each new command to any previous command and for any exact match you have a candidate for a cache hit. The batch idea is harder for me to imagine...especially for a "stateless" web app. When would it batch?
HDave
@HDave Imagine that you have a bunch of tabs in your view, and you want to set a preference to say which tab should be selected the next time the app loads. When you select a tab, you'd want to load the tab's data -- potentially multiple RPCs itself -- and set a preference for that tab -- another RPC. With batching, you could tell the client-side service to wait some amount of time (e.g., 200ms) before actually sending the request, and in the meantime accept other commands to send them all at once. This is an extra simple example, but hopefully you can see how it would be useful.
Jason Hall