A specter has been haunting my code of late. I’ve been calling it the “coordinator” although I’m not wedded to the name. I just know I need it. I need it because I need something to build my Model-View-ViewModel triads. I need something to coordinate them when they are closely related. And I need something to tear them down and dispose of them when they are no longer needed.
That’s my coordinator.
Some friends tell me they don’t see the need for such a thing. I’m not sure how they do without it. Maybe this post can initiate a clarifying discussion.
But first, a little throat clearing.
The Model-View-ViewModel (MVVM) pattern is on the lips of many a Silverlight and WPF developer. It’s ungainly name garners many jokes - the patty-cake pattern, the mumble pattern – but it survives them all. It is the predominant presentation pattern for these technologies and I can’t recall seeing serious discussion of any alternative; it is as close to a consensus heuristic as we get in this business.
There remains plenty to fight about under the MVVM tent.
- Is there any substantive difference between MVVM and Martin Fowler’s “Presentation Model”? If not, why coin a new (and uglier) term?
- How much code-behind in a View is “too much” and what makes it too much?
- When does the XAML devolve into a morass of fetid, untested, crypto-imperative code?
- Does the View (V) come first or the ViewModel (VM) ?
- Should VM have a reference to the V (via its interface of course) or should the VM be ignorant of the view in every way?
- How does the Model enter the picture?
- Is the Model (M) confined to the network of “business objects” presented in the view or does it encompass the mechanisms (e.g., persistence) which create, retrieve, and save those objects?
- Is the VM allowed to offer the V an unwrapped M-object (e.g., the raw Employee) ? Or must the M-object’s properties (if it is even permitted to have properties!) be exposed exclusively through the surface of a VM wrapper?
To pose such questions invites a fist-fight. Small wonder that many developers keep their distance from MVVM; whatever you do you’re doing it wrong.
Perhaps we could all grow up just a little. I’m not diminishing the importance of these differences; I am suggesting a change in conduct.
Sermon over … on to today’s topic: where do you create an MVVM triad and how do you get rid of it when the view is no longer wanted?
The triad doesn’t create itself. Something creates it and puts it in motion.
This isn’t much of an issue in simple applications. It becomes serious when you contemplate
- a screen or page constructed dynamically, perhaps in response to user action
- a composite page consisting of regions holding views, perhaps nested views, each implemented as MVVP triads
- a wizard
- closing a collection of views with a single click
There is significant logic here. Where does it go?
Permit me to indulge an example near to my heart. I have a sample Silverlight application that demonstrates how my company’s DevForce product plays well with Prism. It’s called “Prism Explorer” and you can check it out here. You can run it … and download the source later if you’re interested. Here’s what happens when you run it:
Prism Explorer presents a tab displaying a grid, some buttons, and a ComboBox with queries you can try. Some queries return Customers; some return Employees or Orders or a projection over Customers. There is a second tab that does the same thing … for reasons I won’t go into.
Now if you query for anything except Customers, the application’s responses are confined to the current tab. If you query for Customers, a new tab appears called “Customer Orders”. Click on that tab and, after a trip to the server, you’ll see a master/detail display of the current customer and its orders.
What’s happening? When the application launches, it starts up two modules. One drives the two querying tabs (the “Model Explorer View” module) and the other drives the “Customer Orders” tab.
This second module instantiates a CustomerOrdersCoordinator which just listens (via Event Aggregator) for a “Customer notification event”. It doesn’t display anything. When it finally hears such an event, it create the MVVM triad to display a CustomerOrders master/detail view.
As it happens, the ViewModel takes over the listening chores and updates itself whenever the selected customer changes. The ViewModel doesn’t waste time fetching customer information if it’s view isn’t visible … which is why there is a visible delay when you activate it’s hosting tab.
Thank you if you’ve stuck with me this far and for going along with my scenario. You will notice that the CustomerOrders view and its host tab are not immediately created. They appear only as a consequence of some application logic.
Clearly a ViewModel that doesn’t exist can’t be listening for events. I could have put the coordinator’s logic inside the module class itself. This teaches me nothing. All I get is a module class with an unusual section and unexpected responsibilities … which is why I factored out the Coordinator in the first place.
Confronted with this scenario, what would you do? Is there a need for a coordinator or is there some pattern I’m overlooking?
This is a blog post, not a master’s thesis, but a little literature review seems in order. Gang of Four is silent on these subjects. Martin Fowler’s Patterns of Enterprise Architectures is the next stop on the “Pattern Legends” tour. A landmark effort first published “way back” in 2003 it remains “venerable” in the best sense.
Fowler’s initial thinking was confined to HTML web presentation problems. He expanded the inventory in subsequent years through a series of posts that can be reached from here. The combined corpus of patterns still resonate for WPF and Silverlight developers even if the details aren’t a perfect fit for these more recent technologies.
Most of this material concerns ways to separate logic from the view - Model View Controller (MVC), Model View Presenter (MVP) in its two flavors – Supervising Controller and Passive View - , and Presentation Model (which I am unable to distinguish from MVVM).
As I read him, the collaborator in control (C in MVC, P in MVP, PM in Presentation Model, VM in MVVM) is not responsible for creation or destruction of the collaborating group (aka, the “triad”). Something outside of the triad has these responsibilities. What does that thing look like and, more importantly, what do we call it?
None of them deal with disposing of views because that is simply not an issue in the HTML web world. That shouldn’t stop us from augmenting one of them if it is a good match in other respects.
Front Controller is out immediately. It is a single server-side controller that maps incoming requests to commands which, when invoked, result ultimately in pages shown to the user. It has no role in composing the pages. It’s a traffic cop.
Page Controller is more promising once stripped of its obligation to interpret HTTP requests. It acquires the parts we want – Model, View (and, implicitly, the Controller behind the view) – puts them together, and let’s them go on their way. However, as Fowler describes it, this class is mostly about request routing; it’s essentially a simplified combination of Front Controller - which does no page composition at all – and Application Controller.
The Application Controller (379) seems to me to be the most apt pattern. An application controller takes input from an “input controller” and determines the matching “domain logic” and “view”. Fowler has a Front Controller in mind when he speaks of “input controller”; in a RIA application the input could be an event raised in response to a gesture. The application controller then chooses the right recipe and cooks the view to show the user.
My misgiving about this pattern is the sheer scope of its ambitions. In Fowler’s epigram it is a “centralized point for handling screen navigation and the flow of an application”. That’s a big job, especially in a large WPF or Silverlight application. I’m not convinced we should have a “centralized point” for the application as a whole. Perhaps it makes more sense to think this way at the module level which is where I see the most need for “the thing that composes views”.
And yet I remain uneasy. I’m thinking we need something a bit more focused on a smaller set of concerns. I just want something to build and tear down one or more closely related MVVM triads.
Jeremy Miller hints at this in his artful analysis of composite applications, the excellent (albeit unfinished) “Build Your Own CAB” series. I direct your attention to his last completed entry, “The Main Players”, where he talks about Application Controller.
The ApplicationController controls the screen activate lifecycle and the lifecycle of the main form. In most of my systems other screens are activated by calling methods on the ApplicationController. In smaller systems the ApplicationController would also control screen workflow. In larger systems I would break some of that responsibility out into separate collaborating classes.
This reasoning leads him to describe three kinds of subsytem collaborators, one of which, the “Screen Conductor”, captures my intention almost exactly:
[Screen Conductor] controls the activation and deactivation lifecycle of the screens within the application. Depending on the application, the conductor may be synchronizing the menu state of the shell, attaching views in the main panel or otherwise, and calling hook methods on the Presenters [read ViewModels] to bootstrap the screen. It may also be just as important to deactivate a screen when it's made the inactive tab to stop timers.
My applications tend to be modularized with the help of something like Prism. I wouldn’t have one Application Controller with one Conductor. I would tend to have one “Conductor” per module and I would launch it from within my module class.
I’m not a stickler for one-per-module either; let the circumstances guide you. On the other hand, a profusion of Conductors should give you pause; it suggests that your ViewModels are anemic and underperforming.
But Ward, you called your version a “Coordinator”? Shouldn’t it be called “Conductor”.
Maybe it should. It was a toss up when I was thinking about it and I had forgotten Jeremy’s taxonomy until I started this post. John Papa and I had a blast dreaming up names that keep the avalanche of M’s and V’s going. “ViewMotivator” had possibilities: MVVMVM
A rose by any other name …