MVC is a phenomenal idea. You have models, which are nice self-contained bits of
state, views which are nice self-contained bits of UI, and controllers which are nice
self-contained bits of …
I’m certainly not the first person to notice this, but the problem with MVC as given is
that you end up stuffing too much code into your controllers, because you don’t know where
else to put it.
To fix this I’ve been using a new pattern: MOVE. Models, Operations,
Views, and Events.
I’ll define the details in a minute, but this diagram shows the basic structure of a MOVE
- Models encapsulate everything that your application knows.
- Operations encapsulate everything that your application does.
- Views mediate between your application and the user.
- Events are used to join all these components together safely.
In order to avoid spaghetti code, it’s also worth noting that there are recommendations
for what objects of each type are allowed to do. I’ve represented these as arrows on the
diagram. For example, views are allowed to listen to events emitted by models, and
operations are allowed to change models, but models should not refer to either views or
The archetypal model is a “user” object. It has at the very least an email address, and
probably also a name and a phone number.
In a MOVE application models only wrap knowledge. That means that, in addition to getters
and setters, they might contain functions that let you check “is this the user’s
password?”, but they don’t contain functions that let you save them to a database or
upload them to an external API. That would be the job of an operation.
A common operation for applications is logging a user in. It’s actually two sub-operations
composed together: first get the email address and password from the user, second load the
“user” model from the database and check whether the password matches.
Operations are the doers of the MOVE world. They are responsible for making changes to
your models, for showing the right views at the right time, and for responding to events
triggered by user interactions. In a well factored application, each sub-operation can be
run independently of its parent; which is why in the diagram events flow upwards, and
changes are pushed downwards.
What’s exciting about using operations in this way is that your entire application can
itself be treated as an operation that starts when the program boots. It spawns as many
sub-operations as it needs, where each concurrently existing sub-operation is run in
parallel, and exits the program when they are all complete.
The login screen is a view which is responsible for showing a few text boxes to the user.
When the user clicks the “login” button the view will yield a “loginAttempt” event which
contains the username and password that the user typed.
Everything the user can see or interact with should be powered by a view. They not only
display the state of your application in an understandable way, but also simplify the
stream of incoming user interactions into meaningful events. Importantly views don’t
change models directly, they simply emit events to operations, and wait for changes by
listening to events emitted by the models.
The “loginAttempt” event is emitted by the view when the user clicks login. Additionally,
when the login operation completes, the “currentUser” model will emit an event to notify
your application that it has changed.
Listening on events is what gives MOVE (and MVC) the inversion of control that you need to
allow models to update views without the models being directly aware of which views they
are updating. This is a powerful abstraction technique, allowing components to be coupled
together without interfering with each other.
I don’t wish to be misunderstood as implying that MVC is bad; it truly has been an
incredibly successful way to structure large applications for the last few decades. Since
it was invented however, new programming techniques have become popular. Without closures
(or anonymous blocks) event binding can be very tedious; and without deferrables (also
known as deferreds or promises) the idea of treating individual operations as objects in
their own right doesn’t make much sense.
To re-iterate: MVC is awesome, but it’s designed with decades old technologies. MOVE is
just a update to make better use of the new tools we have.