EventDispatcherExtension, injection of event dispatcher into Model and the role of commands

kihu's Avatar

kihu

20 Feb, 2013 11:01 AM

Hey,

I'm a newbie in MVCS/Command pattern/Robotlegs area. I'm trying to understand how this framework works and what would be the best way to use it in a average-size project. My priority is to keep the code transparent. Usually my apps end up as huge chaotic webs of dependencies and it's nearly impossible to understand what is going on in the code.

So here is how I create the context:

_context = new Context()
                .install(
                        TraceLoggingExtension,
                        VigilanceExtension,
                        InjectableLoggerExtension,
                        ContextViewExtension,
                        EventDispatcherExtension,
                        ModularityExtension,
                        CommandCenterExtension,
                        EventCommandMapExtension,
                        LocalEventMapExtension,
                        ViewManagerExtension,
                        StageObserverExtension,
                        ManualStageObserverExtension,
                        MediatorMapExtension,
                        StageCrawlerExtension,
                        StageSyncExtension)
                .configure(ContextViewListenerConfig)
                .configure(BasicDemoConfig)
                .configure(new ContextView(this));

I just install extensions from MVCS Bundle plus my BasicDemoConfig.
Now, in my config.configure() method I do this:
injector.map(MainItemModel).asSingleton();

MainItemModel is a simple class not extending or implementing any other class. I am able to [Inject] IEventDispatcher into it, but if I try to use it inside the constructor, the dispatcher is null:

public function MainItemModel() {
        dispatcher.addEventListener(MyBasicEvent.STH_HAPPENED, sthHappenedHandler);
    }

Why did I want to inject EventDispatcher into model? At first I've tried to use commands to do all the work. My idea was to make commands manipulate models, view (or mediators) directly. It failed as I wasn't able to inject views into commands:
Injector is missing a mapping to handle injection into property

I was only able to inject events and models into command, so I thought I could let go of commands completely, and handle all communication with shared IEventDispatcher. But as stated above, I don't know how to access dispatcher in Model class.

Am I injecting EventDispatcher into model correctly? In my app there's a mediator with IEventDispatcher injected and it uses the dispatcher before I get the error in my model. So in the mediator, the IEventDispatcher is instantiated but in the model it's not - is it not the same instance?
Is my idea of writing application without commands a good idea? Am I correct that commands are only able to manipulate on Model?

  1. Support Staff 1 Posted by Ondina D.F. on 20 Feb, 2013 01:19 PM

    Ondina D.F.'s Avatar

    Hi kihu,

    I don’t have enough time right now to get into details and answer all your questions, so I’ll just give you the solution to your constructor issue.

    https://github.com/robotlegs/robotlegs-framework/wiki/common-proble...

    Use [PostConstruct] metadata to let the injector invoke a method of your class after all injections have been applied:

    [Inject]
    public var eventDispatcher:IEventDispatcher;
    
    public function SomeClass()
    {
    }
    
    [PostConstruct]
    public function someMethod():void
    {
        eventDispatcher.addEventListener(SomeEvent.SOME_TYPE, onSomethingHappened)
    }
    
    private function onSomethingHappened (event: SomeEvent):void
    {
        //do something
    }
    

    I hope this helps at least a little bit :)

    Ondina

  2. 2 Posted by kihu on 20 Feb, 2013 01:23 PM

    kihu's Avatar

    Thank you! I'll try this.

    Meanwhile, I've been told that adding listeners to model is not a good practice. Still have to learn much theory, I guess.

    Thanks again:)

  3. Support Staff 3 Posted by creynders on 21 Feb, 2013 08:53 AM

    creynders's Avatar

    Or you could inject the eventdispatcher as a constructor parameter if you need to dispatch an event immediately. However, I'd only do this when there's no other possibility and use Ondina's solution.

    public function MainItemModel( dispatcher : IEventDispatcher ) {
        eventDispatcher = dispatcher;
    }
    private var eventDispatcher : IEventDispatcher;
    
  4. Support Staff 4 Posted by creynders on 22 Feb, 2013 07:04 AM

    creynders's Avatar

    Ah, I only just saw

    I've been told that adding listeners to model is not a good practice. Still have to learn much theory, I guess.

    Not sure why anybody would give that advice though. Listening to model events is common practice.

  5. 5 Posted by kihu on 22 Feb, 2013 09:17 AM

    kihu's Avatar

    Hey, creyders, thanks for the advice. I went with Odina's [PostConstruct] solution and it worked. As for Model events I meant adding listeners to Model, so receiving - not dispatching events.

    It's criticized in Robotlegs "best practices" wiki:

    https://github.com/robotlegs/robotlegs-framework/wiki/Best-Practice...

    Listening for Framework Events in a Model
    
    While this is technically possible it is highly discouraged. Don’t do it. Just for the sake of clarity: Don’t do it. If you do, don’t say you weren’t warned
    
  6. Support Staff 6 Posted by Ondina D.F. on 22 Feb, 2013 05:19 PM

    Ondina D.F.'s Avatar

    Hey kihu,

    You’re right: Listening for Framework Events in a Model or Service is not a recommended MVCS practice. Camille would agree 100% on this;) He just misunderstood your question.

    Is my idea of writing application without commands a good idea?

    Not really:) I think commands are very useful and nice (they get gc-ed right after execution!!)
    Without commands it is much harder to keep the 4 tiers (MVCS) decoupled.

    Am I correct that commands are only able to manipulate on Model?

    Nope. Commands can also call methods on Services. They can actually do whatever you want them to do. Bootstrapping, mappings, clean your shoes.. ;)

    You mentioned the Best Practices in your last post. There you’ll find a chapter about commands too.

    Do you need more links to tutorials or examples, or did you find them already?

    Ondina

  7. Support Staff 7 Posted by creynders on 24 Feb, 2013 11:41 AM

    creynders's Avatar

    @kihu ah, ok I misunderstood. You're right, letting a model listen directly to events is a very bad idea.

    About the commands: what @Ondina said. And I understand the hesitation, but commands should actually be the "glue" between the different parts. You should aim to make your models, services and views as independent from each other as possible (it all depends though, but let's take it as a general rule for the moment) but obviously, somehow the various parts need to be patched together, that's what your commands do. They're the dirty workers. They configure, wire and call the methods of your MVS parts. So, in fact, they're allowed to do "anything". Personally I hardly ever use commands for my view-tier, but that's definitely also a possibility, to let them create view instances and pass them to the correct display object containers (through mediators) for instance.

  8. 8 Posted by kihu on 26 Feb, 2013 02:03 PM

    kihu's Avatar

    Hey, thank you guys for help! To be honest I was a little worried I'd be laughed at for being such an ignorant. Instead I've got some solid advice:)

    After a week of building an app with RL2 I feel a little more comfortable with the architeture, still a long way to 'pro' level, though. I've been using commands to operate on Model and then I dispatcher.dispatchEvent to the whole framework. Every relevant mediator has IEventDispatcher injected.

    If I want to send some events between Mediators, I rely on this injected IEventDispatcher. Only if I want to change something in Model, I use Commands.

    Example:

    User clicks button in View -> Mediator sends Event -> 
    mapped Command is executed -> this Command manipulates Model -> 
    Model dispatches another Event -> some Mediator listens to this other Event and reacts
    

    creynders: you wrote you sometimes manipulate views inside your Commands. If example above had mediators accessible in Commands, it would look like this:

    User clicks button in View -> Mediator sends Event -> mapped Command is executed
     -> this Command manipulates Model and View/Mediator
    
    I think the Model and View Layers are still independent in this scenario. Hmm, but now I see the first approach might be better in terms of clarity...

    Well, I still need to think these matters through.

    Do you need more links to tutorials or examples, or did you find them already?

    I've been reading readme files on GitHub and some examples found on the forum, but since you ask, could you point me to some materials about 'behaviors'?

    Thanks

  9. Support Staff 9 Posted by Ondina D.F. on 26 Feb, 2013 03:13 PM

    Ondina D.F.'s Avatar

    Hi kihu,

    I’m glad we didn’t scare you off ;)

    Every relevant mediator has IEventDispatcher injected.

    You don’t need to do this for a non-modular app. Mediators have access to the default event dispatcher:
    https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...

    User clicks button in View -> Mediator sends Event -> mapped Command is executed -> this Command manipulates Model ->
    Model dispatches another Event -> some Mediator listens to this other Event and reacts

    Yep, you got it!

    I've been reading readme files on GitHub and some examples found on the forum, but since you ask, could you point me to some materials about 'behaviors'?

    Hmm, I’m afraid I don’t know where to find that. Maybe Camille or someone else can help you with this.

    Ondina

  10. Support Staff 10 Posted by Ondina D.F. on 11 Mar, 2013 01:40 PM

    Ondina D.F.'s Avatar

    Kihu, I'm closing this discussion, but feel free to reopen it if you need to.

  11. Ondina D.F. closed this discussion on 11 Mar, 2013 01:40 PM.

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

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac