Support Staff2 Posted by creynders on 25 May, 2011 07:34 AM
As you say
an action may happen in one view, that I want to trigger an
event in another SPECIFIC view
this has nothing to do with mediators but view-to-view
communication. There's a bunch of solutions for that: you could let
an event bubble through the display list, or have the views tightly
Mediators are only for framework-to-view and vice versa
IMO if you have a situation where multiple display objects MUST
communicate directly with each other, chances are they actually
constitute one view with one mediator.
Your example of multiple views of the same type showing
different data sets, can (should?) be solved w/o view-to-view
communication, but by letting the mediator decide whether it needs
to update its corresponding views dataset or not (based on a
setting in the view)
Support Staff3 Posted by Stray on 25 May, 2011 07:40 AM
(Just saw creyender's reply - which is also good!)
a mediator shouldn't have an API, because the mediator is just a
short-lived hook on the application layer for getting your view
Mediators should be state-free because of the
disposal/re-creation when the view is removed and re-added. Don't
think of the mediator is part of your view layer - the stateless,
disposable, new-instance-each-time nature of mediators makes them
unsuitable for use as view controllers.
If you want to communicate between 2 mediators directly then
presumably that's because you need to communicate between 2 views.
It would sometimes be better to simply communicate between those
views within the view layer - depending on the parent/child nature
of those views.
On the 'can't use events issue' - is there no way to use a more
specific event? Or add a filtering property to those events? Many
people have solved the 'targeting a specific instance' problem
without resorting to wiring the mediators together.
Finally - mediators are not singletons, they're disposable, so
injection can result into a situation where the instance is no
longer available for garbage collection (having been injected into
another mediator), and then the instance that is created when the
view hits the stage a second time is a new instance and is no
longer the one you've injected.
This leads to memory leaks, multiple-listener bugs and
hard-to-diagnose bugs. It also - inevitably - leads to
race-condition problems, because the mediators have to be created
in a specific order so that the injection value is available. It's
not trivial - for example - to inject a child view mediator into a
parent view mediator, because the parent view mediator is created
and requires the injection before the child view mediator is
In addition, if you inject (into another mediator) a mediator
for a view of which there are multiple instances, which of the many
mediators of that class should be injected?
For all those reasons, as of 1.7 (to be released shortly)
mediators won't event be available for injection (you can inject
into a mediator, but you can't inject the mediator into anything
else) - we've already completely cleaned that from the mediatorMap
in development forks (it was a side-effect and never intended
If you're still wishing to go down this path then may I suggest
that you check out and adopt AS3 signals instead - they'll allow
you to use a request-response pattern which opens up the
possibility of more focussed communication. Search for
request/response on here and you'll find quite a few descriptions
of how to implement it using signals and/or events.
Hopefully that's helpful (even if it doesn't fit with what you
had wanted to hear),
The reason I think it makes sense to talk to the mediator's directly, is
because in our app the Mediator's are responsible for initiating and
receiving service calls.
I know Stray, that you advocate like "pure" mediators, but we're using them
to also be our control layer in a lot of cases (seems to work fine).
So, we have a set up where mediator's can catch framework event, start a
service call, and pass the appropriate set of data back to the view. There
are some cases where a view might trigger an event, which we want to
triggers a load event in another sibling mediator, and it seems a waste to
be dispatching that over the global event bus when I can get just grab the
mediator for that specific view instance from the mediatorMap, and make a
call on it.
View > View communication doesn't really work, basically we would need to
tell the view to dispatch en event, so the mediator could catch it, and then
perform a load. That seems backwards.
On Wed, May 25, 2011 at 1:40 AM, Stray <
[email blocked]> wrote:
For an example, think of one parent view, with 3 complex child views. When
an event happens in one of the child views, we need to:
1. Tell the parent mediator to switch views
2. Tell the sibling mediator to start loading it's data
What I'm proposing is that the parent mediator would catch the view event,
switch views in the viewStack, and then grab the mediator for the new child,
and say mediator.loadData(id);
This is nice because when you look at the parent mediator class, you can
easily tell what's going on, rather than this super loose coupling, where
the parent dispatches an event to the global bus, which it's intended for
one of it's immediate descendants.
On Wed, May 25, 2011 at 1:40 AM, Stray <
[email blocked]> wrote:
Support Staff6 Posted by Stray on 25 May, 2011 02:41 PM
You're absolutely free to architect any way you like - just be
aware that the next RL release doesn't support injecting mediators
into other classes at all - it continues to be outside of how the
framework was intended to work, and, having fully appreciated how
unstable it is, we're now completely cleaning up those mediator
mappings on the injector.
The workaround will be to either patch your own version of the
mediator map to reintroduce it, or do your own injector mapping in
a command (you can get the mediator for that view from the
mediatorMap). Or of course you can stick with the version you're
running now - there's no really significant reason to update.
It seems like the architecture you're going for is largely
dictated by your earlier decision to bypass the command layer. If
it works for you then it works - the guidelines are only based on
our best attempt to lead people down a path that won't get them
into trouble. We don't have any evangelical-style messages to
preach - we're just basing them on our own experiences in building
our own projects and in helping out on other projects that have run
You kind of pitched your question as if you wanted a discussion
- but then it seems that really you're happy with what you're doing
and not that interested in thinking about other ways to do it and
why they might be useful... so I'm confused about what you were
Yep, we definately have our hands tied a bit because of previous
architectural decisions, but there's no reason we cant use events
to communicate between view tiers, I'm just not convinced as to the
benefits. I'm looking for a discussion, but not a one sided one
I guess I was looking for a better explanation of the "why"
behind why we should never access a mediator directly from another
mediator. The FAQ's are little more than "don't do this", which
doesn't work for me.
I can see where using [Inject] of mediator's would be a complete
mess, I'm not talking about that at all, I'm talking about
retrieving a specific mediator for a specific instance of a view.
Are you saying that the "mediatorMap.retrieveMediator(view);" API
is going to be removed completely?
The mediatorMap.retrieveMediator(view) is staying - it's only the ability to inject a mediator into another mediator that is going.
So, I've already explained the garbage collection, memory leak, wrong-instance and repeated-handlers issues that are part of the 'don't do it' reasoning. Did those explanations not make sense? You didn't really respond to any of them.
If your view never leaves the stage, and these mediators never get removed, these are of less concern. If your view does leave the stage, and your mediator is destroyed and a new one created, then you'll run into all of these problems. The specific instance you grab at one point in time is not guaranteed to be the same specific instance that is currently mediating this view.
Retrieving and working with a specific mediator is appropriate within the short-lived thread of a Command executing, but it's dodgy outside of that situation, so creating persistent references is dangerous... do it at your peril.
Well, I didn't respond cause I think most of those only would apply if we
were lazily injecting mediator's all over the place...?
We wouldn't have GC issues since we would not even be storing a reference to
the mediator anywhere, simple grabbing it inside a function, and making a
call on it, we can't get the wrong view, since again we're not injecting,
we're grabbing the mediator for the specific child instance we want, at
runtime, and making a call on it.
I guess what I'm getting from this is, you need to be careful, but if done
properly there's nothing really inherently wrong with calling a function on
a mediator. You just need to implement it in a way that will not cause any
sideeffects (which is pretty damn easy to do really).
The only side effect that I can see that would apply to our implementation,
is the coupling, and this is the one I just don't get, what's the big deal
if you create a top-down one-way mediator coupling...
On Wed, May 25, 2011 at 9:43 AM, Stray <
[email blocked]> wrote:
Support Staff11 Posted by creynders on 25 May, 2011 05:11 PM
TBH and with all respect, but this does sound a bit like someone
who builds his house w/o inner walls, then uses some iron bars to
hold the floors from crashing and wonders why that's really so bad,
since - it holds, doesn't it?
I mean, yeah sure, you can reference mediators from other
mediators, you can basically do anything you want with RL, but
what's the use of using a dependency injection framework if you're
going for tight coupling anyway??
Look, the reason why it's bad to call services directly from
mediators is because it brings you into problems. What if another
mediator needs that same data? Or if at some point in the future
you actually need to call another service before that one? You'll
be refactoring, refactoring and refactoring. You'll sink deeper and
deeper, and sure, there are patches. There always are, just like
having mediator-to-mediator communication is a patch, but it's
nothing more than that.
The idea behind avoiding tight coupling is NOT to make it easy
while you're coding the use case as first defined. It's intended to
avoid problems along the way, when use cases change, requirements
change, services get ported, merged or split up, when customers
decide they really prefer to have the views on a page-per-page
basis instead of all together on one screen, et cetera ad
infinitum. All of the above changes will bring you into troubles
when you start using mediator-to-mediator communication.
My sincere advice is - and I know it's a hard one - refactor it
to use commands. Do it now, because the mess will only become worse
and worse and worse and you'll end up with an application that
behaves erratically, is not reusable, nor scalable, nor portable.
And, yes, I had to learn it the hard way too, until I really
understood that it's not about getting things done NOW, but it
really is about having something that is flexible enough that
future changes are easily made. These days I almost never refactor.
I ADD things. That's only possible if none of your mediators have
direct references to services and/or models.
Unfortunately thats just not an option, we don't have the QA
resources to handle such a major refactor, even if I wanted to I
wouldn't get permission. The app is live, and doing well, and
there's no way we can tear it apart at this point.
I think you're exagerating what I'm proposing, I'm not saying
lets couple everything together, I'm saying in specific instances,
under a specific use case, it might make sense to call an API on
the mediator itself. Thats all.
And just to be clear, no where in the app currently do we do any
mediator coupling at all. I'm just floating the idea...
I'm not happy with our current service > mediator
implementation either, but I'm stuck with it. For the most part it
works fine, and the app is actually fairly robust and scalable. The
nature of the app is that views almost never share data, so we
haven't run into many issues. The biggest issue we have with this
approach is when services complete, and the mediator is no longer
in existence, definitely a major design flaw on my part.
Support Staff13 Posted by creynders on 26 May, 2011 07:37 AM
Obviously if it's already released it would be hardly worth it,
unless if it's an ongoing project.
And yes, I did exaggerate - I've been known to do that once in a
while :) - but it's a bit like using a global variable: you can get
away with it, and it works faster, but you know it can get you into