Short-lived Commands with Parsley

This week we had to decide on a MVC Framework for our next game at Wooga. In the end we had to decide between Robotlegs and Parsley. Both of them had pros and cons which I will maybe explain at a later time.

One aspect we came across was the support of Short-lived Command Objects. These Commands hold no state and will be garbage collected after execution. In Robotlegs they are supported via the ICommandMap interface. Parsley also provides an implementation of this pattern called DynamicCommand. In contrast to Robotlegs, Parsley provides 4 different ways to build and configure a context:

  • MXML: DynamicCommand Tag. Only for Flex projects.
  • XML: DynamicCommand Node. No compiler check on types possible.
  • ActionScript: No way to configure dynamic Commands.
  • Configuration DSL: Programmatic configuration of Dynamic Commands.

Because our game should not use the Flex framework, the last option is our only choice if we want to have strongly typed Command mappings like in Robotlegs.

DynamicCommands via Configuration DSL

Because a documentation is not available for this case it was a bit tricky to find the solution (thanks for the hint, Jens). This was the first result:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var contextBuilder:ContextBuilder = ContextBuilder.newSetup()
    .viewRoot(this)
    .newBuilder();

var targetDef:DynamicObjectDefinition = contextBuilder
    .objectDefinition()
        .forClass(CommandType)
            .asDynamicObject()
                .build();

DynamicCommandBuilder
    .newBuilder(targetDef)
        .builder
            .messageType(MessageType)
            .stateful(false)
        .build();

contextBuilder.config(ActionScriptConfig.forClass(MainConfig));
contextBuilder.build();

Note that you can not use the ActionScriptContexBuilder.build() notation anymore. Instead you have to configure the whole context via the DSL. In line 18, the actual configuration (MainConfig) which contains all object definitions is passed in.

Because this configuration is very hard to read and redundant if you want to map several Commands, I encapsulated the mapping to a separate class CommandMap. Now the configuration looks like this:

1
2
3
4
5
6
7
8
9
10
var contextBuilder:ContextBuilder = ContextBuilder.newSetup()
.viewRoot(this)
.newBuilder();

var commandMap:CommandMap = new CommandMap(contextBuilder);
commandMap.register(LoginCommand, LoginRequest);
commandMap.register(LogoutCommand, LogoutRequest);

contextBuilder.config(ActionScriptConfig.forClass(MainConfig));
contextBuilder.build();

Until now I found no way to map or un-map Commands after the context has been built. The only way would be to destroy the context they are registered in.

To get a better impression how short-lived commands are used in Parsley, I implemented a small example, which you can access on GitHub. The CommandMap class can be found here.

And this is how the login example looks like. Invalid credentials lead to an error pop up. Valid login works with “admin” and password “test“:

Summary

The Robotlegs implementation is very straight forward. Commands can be mapped and un-mapped at any time. This is not possible in Parsley. But you have other features that give maybe similar results (for example MessageInterceptors).

Because Parsley reflects on the types you can pass data directly to the execute method. This way, each concrete execute method can receive strong typed parameters (see line 9). No framework class has to be extended for custom Commands. This is how a command can look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class LogoutCommand
{
    [Inject]
    public var service:ISessionService;
   
    [MessageDispatcher]
    public var dispatcher:Function;
   
    public function execute(message:LogoutRequest) : ServiceRequest
    {
        return service.logout(message.sessionId);
    }
   
    public function result(success:Boolean) : void
    {
        dispatcher(new LogoutSuccess(success));
    }
}

I also like the native support of synchronous and asynchronous Commands in Parsley. No special configuration is necessary, because Parsley reflects on the return type of the execute() method (line 9, ServiceRequest).

Links:

  1. Florian says:

    Just out of curiosity, what framework did you choose at the end? ;)

  2. Mattes says:

    We have chosen Parsley and are quite happy with this decision right now. What I especially like about parsley is its non intrusive way. So you don”t really see the framework in code and you can better focus on the actual implementation.

    One other important thing is the message system. We are using normal objects as messages. The advantage over events is that they are more lightweight. And if you create separate objects instead of using the same event with selectors you are completely type save. That means you can easily refactor messages. Because Parsley reflects on the type, no separate configuration is necessary. If you want the intercept certain events at one place they only need to share the same type (e.g. through interface or by extension). You can also easily transfer strong typed data without boiler plate code like with events. But this is maybe another blog post ;)

    One other thing regarding this post. Actually we never used commands yet because in our architecture the model contains only data (no logic) but instead the controllers hold the state. There are only few controllers that doesn’t hold state and they are more like utility classes.

    Give Parsley a try, it is really sophisticated :)

  3. Florian says:

    We have chosen Parsley too, I was just curious to know if you chose another framework and why ;)

    I think the non intusive argument doesn’t work anymore in comparaison with other second generation flex frameworks (Swiz, Robotlegs, …) because they all are now.

    We also like the messaging system. Another important points for us were how extensible Parsley is, that it works for Flex & Flash and it handles well Flex Module.

    BTW, we made a Parlsey Console that allows you to track all the things that happen in your application such as messages sent, content of contexts, receivers, …
    Check it out here : http://lab.kapit.fr/display/parsleyconsole/Parsley+Console

  4. Mattes says:

    Thanks for your response. Nice that you also use Parsley. There are not many people like you out there ;)

    Your console application looks really sophisticated, nice work! Will give it a try next time.

    Actually I use parsley since the early non-public versions (about 3,5 years ago) and I also like its flexibility for configuration. Especially now with meta data tags. For my previous company I wrote a screen management framework. It could be configured via xml configs and was deeply integrated with parsley.

    In the decision process, the Flex support was not an argument. Because we are developing games, Flex is to heavy for us. Instead our decision was basically made upon a challenge where we tried to implement a pure as3 module framework within 30 minutes that incorporates child contexts. Because we succeeded, we have chosen Parsley. You can find a more advanced version of that here: https://github.com/MattesGroeger/as3-parsley-modules

  1. There are no trackbacks for this post yet.

Leave a Reply

*