Today I got an email from Sandro Aloisio asking an important question about the connection of one MVP triad to another. When introducing the basics of Presenter First, one usually runs out of breath before getting to the topic of connecting triads using Managers (or Coordinators, whatever you call them), which is a technique that has grown up a little and proven to have some merit. So here’s a little more discussion on that front:
Q: There should be at least one MVP triad per user story, is that correct?
Yes, at least one triad for a user story is a good way to go, especially at the outset of a project. It’s worth pointing this out, as I have seen code written by folks who interpret Model-View-Controller patterns to mean your application should consist of exactly 3 gigantic classes.
One user story usually involves one or more like-minded statements that start with “when the user clicks Save” and “when the user clicks Cancel”. A subsequent user story might augment a feature by saying “when the user clicks Apply, save changes but don’t dismiss the dialog” which might involve going back to the old Presenter for that feature.
And it could happen that a small handful of innocent, related phrases from the same story are technically separated enough to make you want to compose more than one triad to answer the story. There’s nothing in the pattern (or our experience) that says this is a problem. At worst, you’ve added a little extra interface code. At least you’ve introduced that much more domain language into your code.
That second case comes up often when the actual verbiage from the customer covers a lot of ground, such as “I can double-click the user name in the list, change that user’s password, then save.” This implies a collection of smaller stories, such as an interactive user list, a password editor, etc. Decomposing the larger story into several related smaller stories gets you several related MVP triads which will need to interact according to the overall user story.
Q: What if a model from one MVP needs to know the state of a foreign model (in another MVP)?
The model-to-model communication you’re asking about is something we answer with the loosely-named “manager” pattern (naming of these objects varies from project to project, I’ll discuss that below). A Manager is structurally identical to a Presenter: it acts as an observer on two objects, and channels data and intentions from one to the other. The Manager exists only to do these things, and has no public API (same as Presenter) and nobody holds a direct reference to this object.
Managers come into existence when you recognize that a user story describes the interaction between two other story-level application features. You’ve already got a triad for each feature, and you’ve decided that the models from these features need to talk to each other. Responsibility and testability issues pop up quickly if you simply let the models reference one another directly, and even if you try to wire one model up to observe the other. (We’ve found that subscribing for, reacting to and processing input is indeed too much to do cleanly all in one class… Presenters lift a lot of this burden from our backs.)
A Presenter’s basic event-and-data brokering habits have freed you up to write much simplified View and Model code. Objects get to “wish” for things to make their testing easier, like “I wish someone would send this data to me, instead of my having to retrieve it, and knowing when”. if you take two models and put a Presenter-ish object between them (creating a new triad) you get to connect your models without overloading them too much. Additionally, you’ve got a specific place to transcribe the user story that connects these two features in the first place.
If you still feel like your models in this triad are starting to get somewhat heavy in their dual responsibilities, do not hesitate to elaborate on the relationship between the models by introducing more models, and perhaps more Managers to connect them. Don’t be frightened of the additional classes… if a problem has become complex enough to make you ask yourself if you need another class to get the job done, you probably do.
In several large projects, we found that we wanted to reserve the word Presenter for that specific type of object that connects Models to Views (or Adapters, but that’s a different topic). Verbal design sessions are easier when the words always mean the same thing. In our seach for terms that mean “Presenter-like object that connects models to models” we’ve used Manager, Conductor and Coordinator. We tend to refer to this aspect of Presenter First as the “coordinator pattern” or “manager pattern.”
When choosing a specific name for a Manager object, try naming it directly for the feature the object will enabled. Eg, you might connect the UserListModel and PasswordEditorModel via the UserPasswordEditorCoordinator.