EventDispatcherExtension, injection of event dispatcher into Model and the role of commands
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?
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
Support Staff 1 Posted by Ondina D.F. on 20 Feb, 2013 01:19 PM
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:
I hope this helps at least a little bit :)
Ondina
2 Posted by kihu on 20 Feb, 2013 01:23 PM
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:)
Support Staff 3 Posted by creynders on 21 Feb, 2013 08:53 AM
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.
Support Staff 4 Posted by creynders on 22 Feb, 2013 07:04 AM
Ah, I only just saw
Not sure why anybody would give that advice though. Listening to model events is common practice.
5 Posted by kihu on 22 Feb, 2013 09:17 AM
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...
Support Staff 6 Posted by Ondina D.F. on 22 Feb, 2013 05:19 PM
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.
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.
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
Support Staff 7 Posted by creynders on 24 Feb, 2013 11:41 AM
@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 Posted by kihu on 26 Feb, 2013 02:03 PM
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:
creynders: you wrote you sometimes manipulate views inside your Commands. If example above had mediators accessible in Commands, it would look like this:
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.
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
Support Staff 9 Posted by Ondina D.F. on 26 Feb, 2013 03:13 PM
Hi kihu,
I’m glad we didn’t scare you off ;)
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...
Yep, you got it!
Hmm, I’m afraid I don’t know where to find that. Maybe Camille or someone else can help you with this.
Ondina
Support Staff 10 Posted by Ondina D.F. on 11 Mar, 2013 01:40 PM
Kihu, I'm closing this discussion, but feel free to reopen it if you need to.
Ondina D.F. closed this discussion on 11 Mar, 2013 01:40 PM.