Sunday, May 24, 2009

Birth and Death of M-V-VM Triads

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?

I find three candidates in Fowler’s pattern book: Front Controller (344), Page Controller (333),and Application Controller (379) all of them expressed in web-specific terms. Can we re-purpose them?

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 …

15 comments:

Rob said...

Ward, excellent post. The WPF/Silverlight community is constantly droning MVVM, but almost no one goes beyond stating their use of the pattern and giving an overly general description of it. But we both know, that if we are going to talk about real-world UI architectures, we can seldom describe our architecutres by simply saying, "I'm using MVVM." I have a lot I want to say about this on my blog soon, and I am glad that another Silverlight guy is "getting down into the nitty gritty" of actual MVVM implementation issues. In reading your description, I have to admit that your coordinator sounds a lot like a Supervising Controller. If you recall from Fowler, the Model of an MVP does not have to be a Domain Model, it can be a Presentation Model. I'd be inclined to say this is exactly what you have. On the other hand, it does take on the role of a micro-Application Controller. In my experinece as a UI architect, I've been inclined to call your coordinator a Presenter (in the Supervising Controller vain), differentiating it from a View Model on the fundamental difference that it hanldes lifecycle issues, such as initialization and shutdown. Almost every WPF/SL application that we have built, has been constructed of hierarchies (composite structures) of these Supervising Controllers, many of which have a ViewModel attached to them, whose lifecycle they control. It's proven to be a very effective strategy and simplifies building even extremely complex UI. After building the boiler plate code for this several times, I finally decided to push a general implementation into Caliburn. One other thing, I wouldn't say the GoF has nothing to say about these issues. Consider how your coordinator displays aspects of Factory, State, Strategy and Composite...

Ward Bell said...

Thanks for the thoughts, Rob. I'm running out the door so I'll be brief for now.

Presenter and Coordinator couldn't be the same thing. Maybe I was unclear.

A Presenter (or ViewModel) is a close collaborator with the View. The view calls upon the ViewModel; that's how it knows what to display and how to forward user input and gestures.

The Coordinator has zero role in presenting the view. It doesn't interact with the view nor does the view interact with the Coordinator.

The Coordinator creates the MVVM triad(s). It may also tear them down.

Sometimes it coordinates interactions among triads or between triads and external components; if it does so, it will talk to the ViewModel, never to the View.

In any case, getting responsibilities right is more important than getting the pattern names right. Sounds like you have a handle on the fundamentals. Best of luck to you.

Wish I could elaborate but must run.

Daniel said...

I spent an awful amount of time trying to fit the MVVM pattern into my real-world applications. Of course, everything works like a charm when you put together a toy app for various presentations but real life is not that easy.
I even started to believe maybe I'm missing something here since the WPF/SL community embraced this pattern as the swiss army knife, the long lost silver bullet. Didn't help too much to go back and forth between Fowler, GoF and Josh Smith, thus I ended up "bending" the rules and the result was to squize the VM inside the MVP pattern (or at least something close to that) :)
Seeing your post Ward makes me happy, because it seems I'm not the only one swimming against the flow. But to keep things short:
A ViewModel is in the end a Model, and I'm usually associating models with logic. By convention I use Model for encapsulating business logic and the ViewModel for encapsulating presentation logic. So I pushed my kind of a EntityViewModel towards your controller, by integrating some specific UI features like a collection of open pages, a commanding mechanism, and all related stuff. Of course, the "controller" part of it controls the lifecycle of all attached pages and also allows the pages to communicate with each other.
Where does the Presenter fit, you may ask. Well, each page loaded in the Pages collection of the EntityViewModel is in fact a Presenter. Why Presenter and not another ViewModel? Quite simple: I keep Presenters just presenting data to be consumed by the actual views. And at the same time, my presenters are proxies for any presentation logic exposed by the master entityviewmodel. Of course, I addes several types of presenters (supporting CRUD operations) but at the same time they can be extended to add any flavor. The link between a presenter and a view is done in a resource dictionary, by defining views as datatemplates for presenters.
Happy MVPVM!

Ward Bell said...

@Daniel and @Rob - Back from Galapagos and reviewing your thoughtful comments. There sure is a lot of unfinished business with MVVM.

My sense is that the community is struggling to find the appropriate responsibilities of VM/Presenter.

I believe we are agreed that whatever you call it - VM or Presenter - the actor in question tackles the essential problem of presenting V and coordinating V with M.

In this post I'm focusing on a distinct and cohesive set of responsibilities: the creation, destruction, and potential coordination of multiple triads.

These responsibilities stand apart from ... and are unrelated to ... the business of putting model data on the screen and responding to user gestures - the bread and butter of MVVM or MVP.

I am positing that these responsibilites belong in a separate kind of dedicated class. I called it "Coordinator" but "Conductor" and "Director" are tempting alternative names.

Rob would call it the "Supervising Controller", leaving the ViewModel to handle the duties of V<-->M management.

The name is apt. Unfortunately, that name is also taken; Fowler coined it to describe one of two flavors of the MVP pattern: Supervising Controller and Passive View.

As I read him, Fowler's Supervising Controller is dedicated to presenting the view and plays no role in "lifecycle issues, such as initialization and shutdown".

It was this terminological confusion that lead to my earlier comment of May 28 when I hectored Rob about the difference between life-cycle and presentation responsibilities ... a difference Rob plainly appreciated.

But you see why I'm reluctant to call it "Supervising Controller" despite that being a good description of its responsibilities. That appellation is simply no longer available. I am curious to see how Rob responds to this problem.

Daniel talks about squeezing VM into MVP. That's pretty much what Fowler claimed to be doing when he described "Presentation Model".

There is a genuine difference between MVP and Presentation Model (aka, ViewModel).

Fowler: "The alternative style [to MVP] is Presentation Model which creates a form of model that captures all the data and behavior so that the view only needs a simple synchronization."

Daniel: "A ViewModel is in the end a Model, and I'm usually associating models with logic."

Seems to me they are saying the same thing.

Daniel seems to agree that triad "life-cycle management" responsibilities belong to some class outside the triad ... but I couldn't discern where or what he called that thing. Chime in, Daniel, if you're up to it.
Thanks both for your contributions!

Ward Bell said...

In my last comment I began a thought without finishing it: "There is a genuine difference between MVP and Presentation Model (aka, ViewModel)".

The essential difference is that the VM effectively encapsulates the M so that the V can synchronize with ONE THING ... the VM. The V is connected to one thing ... the VM.

This may seem too subtle to merit talking about. In practice, it greatly simplifies development because you have two moving parts (V and VM) rather than three (M,V,C or M,V,P).

In the other Separated Presentation patterns the V is connected in some fashion to two things, e.g., M and P.

The simplification is only available as a practical matter when the client technology has strong bi-directional binding support. That is why, in my mind, MVP and MVC remain the preferred patterns for Windows Forms and ASP.

Aside: as implemented the V may actually bind to M object(s) wrapped by the VM. But that would be so as an implementation convenience and, in any event, the V does not "know" that it is "talking" to anything other than the VM.

ToddSnyder said...

Ward, thanks for the excellent discussion.

Your description of the coordinator class sounds an awful lot like the work item class in the Microsoft SCSF/CAB framework. In CAB the work item class acts as a Dependency Injection Container and manages the lifetime of the components loaded through CAB. I believe Prism offers similar features using the Microsoft P&P Unity DI Framework.

Derek Greer said...

What you are describing is handed within the Prism RI by a combination of a module level Application Controller and the Presenter. The Controller takes on the responsibility of responding to requests to show the View, while the Presenter takes on the responsibility of wiring the View to its ViewModel. The View and ViewModel are created through Dependency Injection, but the responsibility could be said to have been inverted from the Presenter.

It sounds like the only difference in this approach and the one you are using is that you are moving the View/ViewModel wiring into the Controller. Are there other differences?

Ward Bell said...

@Todd: The WorkItem often provided the scoping for a collection of interrelated MVP triads ... just as you say. Unity (favored by Prism) does support nested containers which could be used for similar scoping purposes. I'm not sure I'd do that ... I've been trying not to resurrect WorkItem as it seems to have caused as much trouble as it spared; so far ... I've been living without it just fine.

@Derek: I believe the short answer to your question is "yes."

Please refer to my Screen Factory post to see the next step in my thinking on this topic.

That's where I try to address many of the points you folks are raising.

Thanks all for your interest and trenchant comments. See you again over in that successor post :-)

Glenn Block said...

In the StockTrader RI, I believe there are several instances of this pattern. For example, the OrdersController in the positions module for example is responsible for creating, and showing Buy/Sell orders based on the clicks.

Controller however is a very general and overloaded term, I think Conductor really sends the right implications.

DrFooMod2 said...

You could call it the Madam I'm Adam pattern too.

Anonymous said...

This sounds not so much like CAB's WorkItem, but the TController from SmartClient's (SCSF) ControlledWorkItem < TController > class.

123 123 said...

Cool story you got here. It would be great to read more concerning this topic.
BTW check the design I've made myself Young escorts

Daniel Rose said...

One more open MVVM question:

Is the VM allowed to expose UI-specific properties?

For example, in my Model I have a list of recent file names which the View should display in its menu somewhere. Is the VM allowed to expose List (i.e. it is a ValueConverter on steroids), or must I expose List and through some (additional) ValueConverters the View transforms those to MenuItems.

Ward Bell said...

Daniel - Most of us agree that the ViewModel API should "never" expose a type that is view-specific.

It's ok (I believe) to expose a type that is client technology aware (e.g., a property that returns an ObservableCollection which is WPF/SL-specific).

It's NOT ok to return a type that is only meaningful to a particular control (e.g., a "MenuItem" type).
I'm rarely tempted to do so anyway.

When stuck having to provide a value that a control wants, a ValueConverter is one option among many that I would classify (pace Jeremy Miller) as "MicroController" options.

A "MicroController" is a component that connects UI widgets to VMs (in this case). Its API has two faces: one face toward widgets (e.g., Menus) and another "neutral" face toward VMs. Its VM face is abstract (e.g., interface or abstract class); its widget face may be concrete (a subtype of the widget) or abstract.

A Microcontroller is defined outside the view and therefore is reusable by other views. It's defined outside the VM and therefore is reusable by other VMs.

ValueConverters fit this definition as do behaviors.

S931Coder said...

Just starting with MVVM, but I see no need yet for a "Coordinator" beyond what can be done through DI in app.xaml.cs. If a user wants to a different view, they get there through a navigation link. Within a view, different viewmodels can be shown by the views main bound viewmodel; e.g. a CustomersViewModel holding a collection of CustomerViewModels, to which view controls bind. As far as I see it, everything the view needs can be in its master ViewModel. If you wizard-like functionality within a particular view, regions can be collapsed based on ViewModel properties, and so forth.