Writing a core library that will be used by some projects using Robotlegs and others not.

Mark's Avatar

Mark

19 May, 2011 09:27 PM via web

I'm currently in the middle of rewriting a lot of our core library that was originally based on Cairngorm 2.

The core library is a collection of reusable commands, services, models, etc that will be used on multiple projects (many of them will not be using Robotlegs, some will).

I am all for presuming IoC, but commands in Robotlegs projects extend a Robotlegs Command class. I would like to avoid this if at all possible.

This being said, how would you suggest writing your commands to be framework independent, but still work well with Robotlegs projects?

  1. Support Staff 2 Posted by Stray on 20 May, 2011 07:05 AM

    Stray's Avatar

    Hi Mark,

    Your point is a great one - and that's exactly why in Robotlegs commands don't need to extend the Command class - they just need to implement a public execute() method.

    All the various command maps simply check for the presence of this function, they're not bound to the base class - that's just there as a convenience to provide the eventDispatcher, injector, maps and so on.

    You can provide any of these that you need using a public property or a setter function, and the [Inject] tag will simply be ignored in environments not using SS and then you can use whatever object-creation solution you're using in that particular app.

    The eventDispatcher is the most obvious one. It needs to be typed to IEventDispatcher.

    Hope that helps - let me know if you need more details,

    Stray

  2. 3 Posted by Mark on 20 May, 2011 12:46 PM

    Mark's Avatar

    Thanks Stray,

    That definitely answers some of my questions.

    Two additional questions:

    1) Most commands I've used in the past, assume an execute method that accepts an event, but Robotlegs does not accept an event, it expects it to be injected as a property on the command. If you were me, for projects not using Robotlegs, would you build a controller that instantiates the command and and just sets the event on the command instead of passing it in the constructor? If so, how would this affect future apps that could possibly be built using Parsley for instance which (I think) requires an event in the execute method?

    2) So contextView, commandMap, injector, and mediatorMap are not necessarily required in the commands?

    Thanks again!

  3. Support Staff 4 Posted by Stray on 20 May, 2011 12:56 PM

    Stray's Avatar

    Hi Mark,

    in order...

    1) Yes, you could just set the event on the command in any way you like. And I think the requirement to pass an event to a command is an over specification - which is why we didn't take that route in robotlegs, because you may wish to have one command execute several others, and those wouldn't need access (necessarily) to an event.

    I guess you could deal with that using an optional parameter in the execute() function, and something like

    [Inject]
    public function set someEvent(someEvent):void
    {
        _someEvent = someEvent;
    }
    
    public function execute( evt:Event = null):void
    {
        if(evt != null)
        {
            _someEvent = evt;
        }
        // rest of code...
    }
    

    2) Yes - they're only required if you then go on to use them. So you can skip the lot if you're not going to be using them, and just extend and inject the ones you need if you do end up using a command in Robotlegs.

    It's always nice when someone asks a question and we can say "Ah... we already thought of that!" :)

    Stray

  4. Support Staff 5 Posted by Joel Hooks on 20 May, 2011 05:44 PM

    Joel Hooks's Avatar

    another approach would be to add [Inject] directly over execute(event) to utilize method injection.

  5. 6 Posted by Stray on 20 May, 2011 06:21 PM

    Stray's Avatar

    Nice thought, very nice indeed.

    :)

  6. Support Staff 7 Posted by Till Schneidereit on 20 May, 2011 10:25 PM

    Till Schneidereit's Avatar

    I had the same idea, but unfortunately that won't currently work: As
    the execute method is invoked manually by the framework in any case,
    placing an [Inject]-tag above it will result in it being invoked twice
    - once by Swiftsuspenders, once by Robotlegs.

    Additionally, [Inject]-tags aren't processed in a guaranteed order, so
    there'd be no way of making sure that execute is invoked last.
    [PostConstruct] would at least take care of that, though.

    As I see it, there are two ways to make this scenario nicer:
    1. Don't manually invoke anything at all, but simply let the injector
    do its thing. The upside is that we wouldn't have to know anything at
    all about the class used as a command: Command mappings would
    conceptually boil down to "on receiving this event, tell the injector
    to construct that class". The downside is that one would have to
    annotate the execute method. I quite like that we have that as a
    convention right now.

    2. Implement Injector#getMethodDependencies(type : Class, method :
    String) : Array;
    To be used like this:
    var args : Array = injector.getMethodDependencies(commandClass, 'execute');
    var command = injector.instantiate(commandClass);
    command['execute'].apply(command, args);

    While I like the first option for its conceptual cleanliness, I guess
    the second one is much less of a breaking change (in fact, it's not a
    breaking change at all: Every command that currently works would
    continue to work just the same).

  7. Support Staff 8 Posted by Stray on 25 May, 2011 08:46 AM

    Stray's Avatar

    Thanks Till,

    personally I think having to annotate the execute method would be a deal breaker for me - way too easy to forget to do it, and (as usual with meta data) no way to pick it up with unit testing where you're manually running execute();

    Also it would kill existing commands - which you noted :)

    So - option number 2 is maybe preferable... but hmm... humm... I would worry that this new method - getMethodDependencies is a piece of rope (made from strings ;) ) that devs can use to hang themselves... though I could be totally wrong. I just feel nervous of adding anything that allows you to write more code that isn't compiler-safe.

    Stray

  8. Stray closed this discussion on 10 Jun, 2011 03:52 PM.

Comments are currently closed for this discussion. You can start a new one.