Whay we need Mediators in Robotlegs?

naghekyan's Avatar

naghekyan

11 Nov, 2013 08:13 AM

Seems the Mediators should be the laziest ones - just send events to eventDispatcher and when an event is triggered on eventDispatcher then call a view function. If this is the role of Mediators, then why we need them? We could just inject the eventDispatcher into the views as we do it in models and services in order to dispatch an event.

  1. Support Staff 1 Posted by Ondina D.F. on 11 Nov, 2013 12:50 PM

    Ondina D.F.'s Avatar

    Hello,

    I like the fact that you opened separate discussions for each of your questions :)
    But, since they seem to be related, I'll answer all of them in here.

    I have a feeling that you actually know very well which are the roles of a Mediator and when to use it, probably because you've already read the best practices, or some tutorials, or the rl book or went through discussions on this forum. In the context of your other questions, I think, what you are asking is whether the MVCS pattern is suited for games or not, right?

    Here, a few selected links:

    [1] games+robotlegs (you can search the forum for 'game', 'games' for more):

    http://knowledge.robotlegs.org/discussions/questions/759-best-pract...
    http://knowledge.robotlegs.org/discussions/questions/806-is-robotle...
    http://knowledge.robotlegs.org/discussions/questions/468-robotlegs-...

    [2] an interesting discussion on by-passing the mediator:

    http://knowledge.robotlegs.org/discussions/problems/222-lighter-fas...

    [3] assets loading:

    http://knowledge.robotlegs.org/discussions/questions/606-bitmap-han...
    http://knowledge.robotlegs.org/search?q=assets&t=d&recommend=1

    If you decide, you don't need a Mediator, the ViewProcessorMap will be your friend :)

    See the readme:
    https://github.com/robotlegs/robotlegs-framework/tree/master/src/ro...

    especially the part about injection into views:
    https://github.com/robotlegs/robotlegs-framework/tree/master/src/ro...

    and, other discussion on this forum:
    http://knowledge.robotlegs.org/search?q=viewProcessorMap&t=d&am...
    http://knowledge.robotlegs.org/search?q=view+processor+Map&t=d&...

    Let me know if it helps. Don't hesitate to ask more questions, if need be.

    Ondina

  2. 2 Posted by naghekyan on 11 Nov, 2013 02:51 PM

    naghekyan's Avatar

    Thanks for the links, but as the amount of the info the links provide is really hug and in different contexts, it is difficult to get the answer of my question. If you can explain than please tell me why we couldn't just inject the eventDispatcher into the views, as we do it in models and services, in order to dispatch an event and by doing that just get rid of Mediators at all?

  3. Support Staff 3 Posted by Ondina D.F. on 11 Nov, 2013 03:49 PM

    Ondina D.F.'s Avatar

    Oh, ok.

    In your config file:

    public class SomeConfig implements IConfig
    {
        [Inject]
        public var viewProcessorMap:IViewProcessorMap;
        [Inject]
        public var commandMap:IEventCommandMap;
    
        public function configure():void
        {
            viewProcessorMap.map(SomeView).toInjection();
            viewProcessorMap.map(AnotherView).toInjection();
            commandMap.map(SomeEvent.ANOTHER_TYPE, SomeEvent).toCommand(SomeCommand);
        }
    }
    

    In SomeView:

    [Inject]
    public var sharedDispatcher:IEventDispatcher;
    
    private function someFunction():void
    {
        sharedDispatcher. dispatchEvent(new SomeEvent(SomeEvent.SOME_TYPE, message));
    }
    

    In AnotherView

    [Inject]
    public var sharedDispatcher:IEventDispatcher;
    
    private function creationCompleteHandler(event:FlexEvent):void
    {
        sharedDispatcher.addEventListener(SomeEvent.SOME_TYPE, onGlobalDispatch);
                    
    }
    private function onGlobalDispatch(event: SomeEvent):void
    {
        trace(event.message);
        sharedDispatcher. dispatchEvent(new SomeEvent(SomeEvent.ANOTHER_TYPE, anotherMessage)); 
    }
    
  4. 4 Posted by naghekyan on 11 Nov, 2013 08:13 PM

    naghekyan's Avatar

    Can I consider that you agree with me that Mediators can be eliminated from Roboltegs at all without any losses in the great idea of the framework? And also you have posted above and example how I should do when I don't use mediators? So are there still reasons why we need mediators?

  5. Support Staff 5 Posted by creynders on 12 Nov, 2013 09:09 AM

    creynders's Avatar

    Can I consider that you agree with me that Mediators can be eliminated from Roboltegs at all without any losses in the great idea of the framework?

    Most definitely not. Mediators allow decoupling of the views from the rest of your system. W/o mediators your views will have way too much knowledge about the other parts of your application.

    The benefits are:

    1/ reusability. If your views are truly decoupled, it's really easy to reuse them in a different context, application etc. All they'll depend on are components and your message carriers (events, signals, ...) while if your views have direct dependencies on services, models, etc. it's a lot harder to take them out and reuse.

    2/ strict separation of tiers/concerns. Views should only deal with presentation logic. They shouldn't be bothered with how and where data comes from, they just need to take care of displaying the data. W/o mediators this is not possible.

  6. Support Staff 6 Posted by Ondina D.F. on 12 Nov, 2013 10:57 AM

    Ondina D.F.'s Avatar

    I completely agree with creyenders on the benefits of using Mediators.

    As a matter of fact, I chose, first PureMVC, and then Robotlegs, as frameworks for my projects, because of the way they implement the MVC design pattern. My projects are mostly large desktop AIR applications + backend databases...MVCS best meets the needs of my projects.
    Depending on the nature of a project, other design patterns might be a better fit than MVC(S).
    Forcing a project into a certain pattern is not a good idea, in my opinion. So, if you feel that MVCS is not suited for your app, use something else. Robotlegs 2 is very flexible in this regard. I know, I know, it is hard to decide what you need, if everything is kind of new (the framework, the patterns).

    A real fact from my own experience on the reusability of views:
    I was working on a project in a team of developers that used puremvc as a framework, while I was still maintaining a robotlegs-project with a similar structure as theirs. We ended up exchanging some components (mediated Views). The wiring of views to mediators is different in the 2 frameworks, but it was just a matter of a few minutes to plug our Views into the other framework, and that only because our Views were completely decoupled from the framework:)

  7. 7 Posted by naghekyan on 13 Nov, 2013 07:12 AM

    naghekyan's Avatar

    Fine, so both of you think kind of the same way, i.e. (citing creyenders)

    "Views should only deal with presentation logic. They shouldn't be bothered with how and where data comes from, they just need to take care of displaying the data. W/o mediators this is not possible."

    I agree that this decoupling is handy but in that case I cannot understand why Models and Services should inject eventDispatcher to dispatch events. Maybe we need some kind of mediators there too? Well Commands partially mediate Models and Services, as far as no one of them listens to eventDispatcher, but what about using eventDipatcher to dispatch events. This is also a coupling and event more, the same type of coupling.

  8. Support Staff 8 Posted by creynders on 13 Nov, 2013 08:46 AM

    creynders's Avatar

    The EventDispatcher is a native class, so when reusing models or services
    you won't need to copy it along.

    That said, don't get me wrong: models, services and views _are_ allowed to
    have dependencies. In fact most of mine do, but they're always encapsulated
    pieces that logically "belong" to the M, S or V. For instance: my services
    tend to depend on a corresponding parser class, e.g. TwitterFeedService
    depends on ITwitterFeedParser.
    Dependencies are only a real problem when two pieces of functionality are
    logically unrelated, yet they depend on each other simply to communicate
    their state. For instance, a LoginService and UserProfileView. The only
    connection they have is that they use the same data (e.g. UserVO) and it
    could be you want to show the user profile whenever a user has logged in,
    which means there needs to be some kind of communication (chain). Yet a
    LoginService should be able to function without the UserProfileView (maybe
    you only want to show the user profile whenever a user clicks a
    "profile"-button) and vice versa (maybe you want to use UserProfileView to
    show the details of other users too)
    If these two classes have a direct dependency it's a problem, because
    they'll be tied to each other, yet both should be completely independent
    from each other, since only then they're really reusable. Also, irrelevant
    dependencies tend to reduce readability and robustness and muddy the
    separation of concerns.

    And getting back to the EventDispatcher, it's a messaging class, even
    models and services need to be able to message their state to the system,
    how would the system otherwise know when their state is changed?

  9. 9 Posted by naghekyan on 13 Nov, 2013 05:27 PM

    naghekyan's Avatar

    Dear creynders I am talking about this syntax:

    public class GfxLoaderService {

        [Inject]
        public var eventDispatcher:IEventDispatcher;
    ...........

    This service can not be used out of RL framework as far as we don't have mapping and injection mechanism, right?

  10. Support Staff 10 Posted by creynders on 14 Nov, 2013 08:51 AM

    creynders's Avatar

    When used outside a RL-project the Inject-metadatatag is simply discarded
    by the compiler. So, yes, you can reuse it.
    If you think it's ugly, you can make `eventDispatcher` a constructor
    parameter, then you don't need the Inject-tag.

  11. 11 Posted by naghekyan on 15 Nov, 2013 08:49 AM

    naghekyan's Avatar

    If I make `eventDispatcher ` a constructor parameter, then how can I pass the `eventDipstacher` which creates RL to the constructor?

  12. Support Staff 12 Posted by Ondina D.F. on 15 Nov, 2013 09:31 AM

    Ondina D.F.'s Avatar

    The shared event dispatcher is available after context's initialization. It has already a mapping, so that you can do this in your class that needs it as a constructor argument:

    public class SomeModel
    {
        private var _someProperty:String;
    
        private var _eventDispatcher:IEventDispatcher;
    
        public function SomeModel(eventDispatcher:IEventDispatcher)
        {
            _eventDispatcher = eventDispatcher;
        }
    
        public function get someProperty():String
        {
            return _someProperty;
        }
    
        public function set someProperty(value:String):void
        {
            _someProperty = value;
            _eventDispatcher.dispatchEvent(new SomeEvent(SomeEvent.SOME_TYPE, value+" greetings from model"));
        }
    }
    
  13. 13 Posted by naghekyan on 15 Nov, 2013 10:18 AM

    naghekyan's Avatar

    And in in context configurations I need to map it like this?

    [Inject]
    public var eventDispatcher : IEventDispatcher;

    public function configure() : void {
         var someModel:SomeModel= new SomeModel(eventDispatcher );
         injector.mapValue(SomeModel, someModel);
    }

    There is no way to map as a singleton with explicit call of a constructor with desired arguments, is there?

  14. 14 Posted by matej on 15 Nov, 2013 10:34 AM

    matej's Avatar

    Every thing that is in constructor will be injected if you use injector to create that class.

  15. Support Staff 15 Posted by Ondina D.F. on 15 Nov, 2013 10:35 AM

    Ondina D.F.'s Avatar

    No, not like that:)

    you map your Model in a config class that implements IConfig like so:

    public class ModelsConfig implements IConfig
    {
        [Inject]
        public var injector:IInjector;
    
        public function configure():void
        {
            injector.map(SomeModel).asSingleton();
        }
    }
    

    In your class where you create your Context:

    context = new Context()
            .install(MVCSBundle)
            .configure(ModelsConfig)
            .configure(new ContextView(view));
    

    Context's ExtensionInstaller installs all the extensions contained in a given class that implements IBundle, meaning that you can create your custom bundle, if you want to.
    The MVCSBundle installs a number of extensions commonly used in typical Robotlegs applications and modules.
    EventDispatcherExtension is included in the MVCSBundle.

    The IEventDispatcher is mapped like so:

    https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...

    If you don't have the EventDispatcherExtension installed, for some reasons, you have to map the IEventDispatcher yourself before injecting it through [Inject] or as a constructor argument into your classes.

    If you want an additional dispatcher, you can use named injections:

    var specialDispatcher:IEventDispatcher = injector.getInstance(IEventDispatcher);
    injector.map(IEventDispatcher, "specialDispatcher").toValue(specialDispatcher);
    

    Injected like this:

    [Inject (name="specialDispatcher")]
    public var specialDispatcher:IEventDispatcher;
    
  16. Support Staff 16 Posted by Ondina D.F. on 15 Nov, 2013 10:40 AM

    Ondina D.F.'s Avatar

    @matej

    Every thing that is in constructor will be injected if you use injector to create that class.

    Right.
    But the Injector needs a rule for the constructor arguments as well.

  17. 17 Posted by matej on 15 Nov, 2013 10:57 AM

    matej's Avatar

    [PostConstruct]
    public function init():void{
    //all other mappings
    injector.map(SomeModel).asSingleton();
    }

  18. Support Staff 18 Posted by Ondina D.F. on 15 Nov, 2013 11:14 AM

    Ondina D.F.'s Avatar

    I think, the inherited configure() comes in very handy. I don't need to write yet another metatag ;)

  19. 19 Posted by matej on 15 Nov, 2013 11:46 AM

    matej's Avatar

    I agree :)

  20. Ondina D.F. closed this discussion on 23 Dec, 2013 09:25 AM.

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