Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: In MVC systems, why doesn't controller observe model?  (Read 7924 times)
Mazoonist
Newbie
*
Posts: 3


View Profile Email
« on: October 13, 2011, 07:00:07 »

PureMVC has opened my eyes in a lot of ways. I had been struggling to understand MVC for a long time. One thing I could never understand (at least in terms of Flash and AS3) was why the View should delegate events to the Controller. Suppose I have a group of buttons in the view, and they are in an array (also defined in the View), and they share an event listener. The first thing the listener does is figure out which button was clicked using event.currentTarget.

The View can do this because it has the array and all the references to the buttons. If I pass the event to the Controller to process it, the Controller will not have the array reference, nor any references to any of the other buttons, and so some other way must be found to identify the button. Using the name property might be a solution, but then the same problem pops up: the Controller then needs to know all the names.

The book "Actionscript 3.0 Design Patterns" advocates passing the event to the Controller to handle it. Their scenario goes like this: Model is instantiated first.
The Controller is instantiated and given a reference to the Model in its constructor.
The View (or views) is then instantiated and given reference to the Model and Controller.

Notice that, in the above, the Controller is never given a reference to the View, although the authors seems to indicate that the Controller can have a reference to its view, and even should in some cases.

However, the book "Head First Design Patterns," while not an AS3 book, seems to advocate a system something like this:
Model is instantiated first.
The Controller is instantiated and given a reference to the Model in its constructor.
The Controller then instantiates its View and passes a reference to both the Model and itself to the View's constructor.

Since the Controller now has a reference to its View, it could then freely add event listeners to the View's buttons itself. The Controller could then house the array that refers to the View's buttons, like:

private var buttonArray:Array = [view.button1, view.button2, view.button3];

In this scenario, the View becomes something like the view components of PureMVC. They can be reused in another project by simply writing a new controller for them.

My question, then, is-- doesn't this kind of system-- where the Controller becomes an observer of its View-- just make a lot more sense? I mean, the View still communicates to the Controller, it just does it by dispatching events (instead of just passing them directly). I don't see the downside, and I wonder why so many sources advocate passing an event to a Controller that just doesn't have the right references in place to handle it.

Studying PureMVC has made me aware of this. I love the way it decouples everything. In PureMVC the Mediator classes observe their view component much like my hypothetical controller above.

Any thoughts?
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: October 13, 2011, 05:28:08 »

My question, then, is-- doesn't this kind of system-- where the Controller becomes an observer of its View-- just make a lot more sense? I mean, the View still communicates to the Controller, it just does it by dispatching events (instead of just passing them directly). I don't see the downside, and I wonder why so many sources advocate passing an event to a Controller that just doesn't have the right references in place to handle it.

The Controller in PureMVC is something that instantiates Commands as needed. Commands are short-lived; they go away when done.

In your case, your component containing the buttons should encapsulate behaviors like enabling or disabling them based on available data in the component. You don't want the framework to be responsible for any more than it has to. View components remain portable that way.

Mediators are meant to listen for critical events that bubble out of a components that need further communication back into the framework - to perform business logic or fetch data.

HTH,
-=Cliff>
Logged
Mazoonist
Newbie
*
Posts: 3


View Profile Email
« Reply #2 on: October 13, 2011, 07:11:52 »

Thanks for the reply, Cliff.

What I meant was that studying pureMVC was helping to shed some light for me in my own thinking about ordinary, plain vanilla MVC (without the pureMVC framework), which always seemed to me to be an odd fit for Flash and AS3, mostly for the reason outlined above, that is, the idea that the controller should be passed an event rather than adding the event listener for it itself.

I intend to keep rolling with pureMVC, it's just that I had already been very close to implementing ordinary MVC into my programming projects. I could see the value of using a model, but I would always get hung up over the issue of passing events to the controller, in addition to just general confusion over what code should go where.

I love PureMVC, it's just that after all this time of studying design patterns in general, I have this inner need to understand how the MVC pattern itself might work with Flash, and the various sources out there all seem to see it differently, and sometimes even contradict each other.

EDIT: I guess I should kind of apologize, as my question wasn't about pureMVC itself, more like MVC in general. I'll try to stay more focused on pureMVC questions in future posts. But with your knowledge of patterns, I guess I was kind of expecting an answer like, "Yeah, it's okay to let the Controller observe the View that way and add event listeners to it... perfectly fine" --OR-- "No, you wouldn't want to do that, as that would (for whatever reason) go against the Strategy pattern that the View uses to delegate events to the Controller."

Mr. Jody Hall
"Mazoonist"
« Last Edit: October 13, 2011, 07:26:33 by Mazoonist » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: October 14, 2011, 07:08:16 »

always seemed to me to be an odd fit for Flash and AS3, mostly for the reason outlined above, that is, the idea that the controller should be passed an event rather than adding the event listener for it itself.
From recent experience, I can tell you categorically that a Command (or any other conceivable denizen of the Controller tier) setting a listener on a View Component is bad thing.

My current client has a huge codebase that started with a media creation tool, then sprung several viewers - one for the desktop, one for the web, and now we're working on the iPad version. So there is plenty of shared code in a huge library and thus far it hasn't been that difficult to manage.

Enter Flex Mobile and the monkey wrenches start flying. Why? Flex Mobile is not tolerant of MX (Halo) controls. You can only use Spark controls in a Flex Mobile project.

Fine, fine. We knew we'd be rebuilding the front end with a more appropriate UI. But when we started trying to reuse the Controller tier code (and there is lots of it), we discovered that we had all sorts of places where Commands were manipulating view components. Even doing an Alert.show() presents a problem because that's a Halo control not a Spark control.

So we've spent several weeks refactoring all of this code to eliminate such references so that we can reuse the Controller tier code.

Therefore, I can say without reservation: decouple your Controller (and certainly your Model) from your View in the highest degree possible. You will not regret it. Let the Mediator translate events coming from the View Component into notifications to be processed by Commands. This also has the benefit of isolating knowledge of the View Component to a single actor (its Mediator), which means if the Component and its communication patterns have to be majorly refactored, you've limited the impact to the application. You don't have to go off refactoring a bunch of actors that 'know' that component.

View Components: Encapsulate their behavior and implementation. Don't make them lifeless puppets that require other classes in order to be useful.

Mediators: Don't make them puppeteers. Don't make them 'smart'. Don't make them stateful. Keep it simple and use them to Mediate communications between the View Components and the rest of the application. Switchboard operators at best.

Commands: They house logic. Don't force them to deal with actual components. This isn't always possible, but if you must try to handle an interface rather than a concrete component.

Proxies: Don't allow them to reference anything in the Controller or View tiers. For an app of any size, its actually best if you create a separate library project for your Model tier, and don't allow it to reference the app at all. This forces it to be self contained. The one non-Model tier class you might put into that library is a PrepareModelCommand that is responsible for registering all the Proxies, thus making it easy to reuse the entire Model in another app without having to duplicate the registrations.

Also, to address the question in the title of this thread: the Controller can observe the Model. A Command can be registered to respond to a notification from a Proxy.
-=Cliff>
« Last Edit: October 14, 2011, 07:25:30 by puremvc » Logged
Mazoonist
Newbie
*
Posts: 3


View Profile Email
« Reply #4 on: October 14, 2011, 10:03:01 »

Cliff,

Thanks for your insightful answer. I'll keep in mind everything you said in your post, as I venture forward and get going with pureMVC. The warning about not making mediators too "smart" was especially helpful. Thanks for not letting me jump to a wrong conclusion about MVC itself. As I look at the Head First Design Patterns book again, I see that even though the controller creates the view, it didn't necessarily add event listeners to it (they didn't show that part of the code).

I really, really appreciate you taking the time to write that.
Logged
Pages: [1]
Print