PureMVC Architects Lounge

PureMVC Manifold => Bug Report => Topic started by: Don-Duong Quach on July 18, 2007, 01:43:38

Title: [ FIXED ] Dynamic mediators / registerMediator / removeMediator
Post by: Don-Duong Quach on July 18, 2007, 01:43:38
Hi Cliff,

I'm not sure if this is a bug or a design issue.  But I ran into an issue with removeMediator not removing the observers created with registerMediator. 

I'm trying to setup a panel that is rarely used in the application but can be opened and closed on demand.  So I'd like to dynamically register the Mediator and add the panel to the stage and subsequently remove the panel and Mediator on close. 

How would you handle this scenario? Is this a bug with removeMediator?


Title: Re: Dynamic mediators / registerMediator / removeMediator
Post by: puremvc on July 18, 2007, 03:11:28

The automagical registration of Mediators was added in a late iteration of the framework.

By that time, patterns of usage were emerging in tests that suggested that we would typically handle transient View Components such as popups or seldom used panels by having a long-living Mediator that is responsible for its creation and removal.

The Mediator's instantiation might be deferred, but once created it would manage the existence of the transient component throughout the remainder of runtime. Otherwise we incur double object creation time costs each time the component (and its Mediator) are created.

The Mediator instance has a relatively miniscule size, owing to its simplistic role. So to the question of leaving the Mediator around after it is created or to incur the time to create another new one if you happen to visit the seldom used View Component again, I'd almost always advocate the former.

This means subsequent removal of Mediators is not really expected, though it should work.

I will test this, and it may result in a maintenance release if the Observers are not being removed from the observerMap on removeMediator. I am going to move this thread to the Bug Report forum.


Title: Re: Dynamic mediators / registerMediator / removeMediator
Post by: puremvc on July 19, 2007, 05:55:42

You're absolutely right, the associated Observer instances were not being removed from the View's observerMap when removeMediator was done.

I have corrected the problem, and updated the framework and unit tests. The new framework version is 1.5 and is now the currently downloadable  version.

Since removing Mediators after their creation is seldom done and not really advised (see earlier in the thread for those just tuning in), this is not something that will change the behavior of any existing application or require any recoding. 

The change entailed adding a compareNotifyContext method to Observer and IObserver. This allows the View to compare the Mediator being removed to a given Observer's Notification Context reference without breaking the Observer's encapsulation of that reference.

The removeMediator method of the View now goes through the observerMap (where notification name is key and an array of observers is value) and for each observer list, removes the Observers pointing to this specific Mediator reference. If this causes the Observer list length  to fall to zero (no more observers for this notification name), the reference to the observer list is set to null, freeing it as well.

The Unit tests have been updated to test the new Observer.compareNotifyContext method.

Below are screenshots showing before and after a removeMediator test in the debugger. They show that the Observers are removed, and further, when the last observer in an observer list is removed, the list itself is removed.



Note that the keys still exist in the array; both for removed Mediators and for Notifications that now have null observer lists.

Though the keys remaining are tiny and few, the act of adding a Mediator then removing it should be idempotent; it should, as a good nature hiker, leave no trace.

However, I've found no good way to remove the keys of an associative array other than to copy the array elements over to a new array, bringing over only the ones that are not null, then replacing the original array reference. The splice method only works for strict arrays, these are associative arrays.

Copying the arrays is the answer, but I'm not yet decided as to whether to have a cleanup function or to do it inline. This is an minor optimization that will be thought out and included in a future maintenance release.

Again, thanks for catching this and bringing it to my attention. The plan is to push the framework to an extremely stable state quickly and not touch it anymore. While this wasn't a fatal flaw, finding and dispatching any issues early on is the name of the game.


Title: Re: Dynamic mediators / registerMediator / removeMediator
Post by: Don-Duong Quach on July 19, 2007, 06:51:54
Hi Cliff,

Thanks for responding and posting a fix so quickly.  I understand your explanation, but I'm wondering what scenario would warrant the removal of a Mediator?  Why have a removeMediator method at all?

Title: Re: Dynamic mediators / registerMediator / removeMediator
Post by: puremvc on July 19, 2007, 06:57:19

It is true that there is rarely a time when you would want to call removeMediator. However, when you are writing a framework, it's difficult to predict everything people will try to do with it.

I did not want to rule out the possiblity that someone would want to dynamically register and remove Mediators, even though my tests and thinking on the subject at the time had pretty much led me to think it would be rare.

In coming FAQ's and the courseware, etc, I'll elaborate, but for now, at least if you do decide you want to do this, it won't ever cause a problem.