Thad,
I'll try to answer your questions as well as I can. We're pretty
excited that there's some discussion starting on this topic. Pardon
the length of what I've written here. I wanted to preserve for
posterity a decent explanation of these ideas for anybody who might
come across this.
First, let me clarify some things regarding MVP. The ideas associated
with it are fairly simple. However, there's a variety of
interpretations on how to use it and what the fine details of each
component are. The following is how we use it in a simplified form.
In MVP, the Model encapsulates the business logic and system state
segregated from the user interface (it "models" the system the UI
gives access to). We agree it's a bit generic of a term. We used it
in MHC because of the precedent of the language associated with Model
View Controller and Model View Presenter.
In MVP, the View is the thin wrapper around the GUI widgets and
forms. It contains as little logic as possible. For sake of testing,
this allows the widgets to be mocked or simulated so that the
presentation and business logic can be tested without widgets on screen.
In MVP, the Presenter, as opposed to the Model, encapsulates the
presentation logic. The Model is the system's business logic. The
Presenter is the GUI logic. That is, the Presenter receives events
from the View and makes decisions about what actions to initiate on
the View and Model in response. That a button press saves a file and
disables the save button is the Presenter's responsibility. It
receives the button click event and then tells the View to gray out
the save button and tells the Model to save the open file.
So, Model-View-Presenter translates to 'Business Logic'-'GUI
Widgets'-'GUI Logic'. Separating business logic and presentation
logic makes for cleaner, more flexible design and good testing.
Things get a bit more complicated when you start assembling a system
of multiple MVP triplets. Sometimes you need translators between
layers and in anything but the simplest of systems you must start
tying together models. But the above description captures the
essentials.
We've found that in Agile fashion, stories map very, very well to
Presenters. A customer usually talks about their actions in terms of
a user interface. So, in GUI or Web applications, we start with
Presenters to build the app a little bit at a time. The presentation
logic (stories) within the Presenter demonstrates what needs to
happen in the View and Model. Starting with Presenter tests first,
the Model and View can be mocked out and then implemented later as
more tests and more of the system are fleshed out. We refer to this
approach as Presenter First. It helped form our thoughts on Model-
Conductor-Hardware to a degree.
For more on Presenter First, see the following. The first is our
repository for Presenter First resources. The second is an excellent
webcast video by Brian Marick on the topic. Brian has been working
with us on a Presenter First article to appear in Better Software in
February 2007.
http://www.atomicobject.com/pages/Presenter+First
http://www.testing.com/cgi-bin/blog/2007/01/05#wireframe2
We tried something clever that may have been a bad move in naming
Model-Conductor-Hardware. The Conductor corresponds to the Presenter.
Because we've found the Presenter to be central to the TDD process
(Presenter First), we felt its corresponding component, the
Conductor, really should be at the center of the triad name. Hence
the naming order. In hindsight this may not have been a good move as
it's confused people.
Model == Model
Conductor == Presenter
Hardware == View
So, to answer your central question, the value of the Conductor in
Model-Conductor-Hardware is that it allows the hardware control logic
to be segregated from the business logic. By testing the Conductor,
hardware conditions and event handling (interrupts, etc.) can be
tested apart from the data handling and number crunching logic of the
Model. This yields better design and easier testing.
Let me give you an example. Imagine an embedded system that processes
temperature. The Hardware layer wraps the temperature sensor and the
timer that triggers temperature reading (the wrapping is to make unit
testing possible in the first place, of course). The Conductor
handles timer events and asks the hardware for raw temperature
values. The Conductor then hands that raw data off to the Model to
calculate a temperature. A subsequent, similar process for displaying
the temperature can be imagined. The logic for handling the hardware
can be tested apart from the math that processes the temperature.
This is far better than verifying temperature processing code with
heat guns and compressed air cans. While it's true you could possibly
eliminate the Conductor, we've consistently found that isolating
functionality always yields unexpected gains because of the
decoupling it provides. So, we offer that segregating hardware
handling logic (Conductor) from business logic (Model) is the best
way to go.
We've been talking all about unit testing thus far. An added benefit
of the MHC pattern is that it can make system testing much easier. By
testing the hardware and business logic separately, test fixtures can
be created and hooks made into the Hardware layer that allow hardware
related problems (either programming misunderstandings or board
design issues) to be found and solved much more quickly than in
traditional firmware development.