- I sing the praises of frameworks like Ember.js,
- explain why they don’t work so well for games, and
not) around MVC for cleaner code.
I recently decided to improve the Solitr game
(GitHub) I had hacked together in a
one-day hackathon (blogged about
The code had turned out rather messy, so I went for a rewrite with better
design, only copying bits and pieces from the first implementation.
Ember, Batman, and
Serenade come to mind. I had used Backbone
before, but I had heard interesting things about Ember, so I decided to give
that a spin. I am rather enthused:
Why Ember.js Rocks
Probably the most important feature in Ember is attribute binding. It
allows attribute changes to automatically propagate through all layers of your
application. For example, say you change
firstName on your model, then the
firstName attributes on your controller and view class are updated (because
they are “bound” to
model.firstName), and the
fullName helper attribute on
your view class gets recalculated as well, because it in turn is “bound” to
This is the awesomest thing since sliced bread. It means that when your
controller responds to an event, it only needs to update the model and every
piece of your app that (directly on indirectly) depends on it is notified.
Ember’s in-place template updating deserves special attention too, and
coming from server-side templating languages, the significance of this feature
wasn’t obvious to me at first: When the
fullName attribute in the previous
example is updated, Ember’s template engine will change the attribute inside
the template live in the DOM, and not just re-render the entire template.
That’s important because otherwise you lose all GUI state (such as collapsible
elements, or cursors in text fields) whenever a single attribute inside a
template changes. I learned this the hard way with a Backbone application I
worked on: Having to re-render views just because a counter increases is
bothersome for small page elements, but once you get to reloading an entire
pane, it becomes a usability issue, and one that’s rather hard to fix.
templating engines to be more intelligent than just spitting out a chunk of
So attribute binding and template updating are the two things I recommend you
pay attention to when choosing an MVC framework.
Enter Games: On States and State Transitions
So I started to rewrite Solitr with Ember.js. A day or so into the rewrite
however, I was beginning to question whether Ember’s attribute-binding approach
was right for a game. Let me explain why.
When a card moves to a new place, it needs to be animated. So you can’t just
top CSS properties when the game state (and hence the
location of a card) changes. My first instict was to simply slide the
cards into place whenever the position changes, either by catching the
changes to the position attribute and wrapping it in a call to
jQuery’s .animate(), or using the CSS
However, this doesn’t quite work: The type of animation you need depends on
the last action: For instance, turning over three cards on the stock, playing a
card you double-clicked, or snapping a card into place after it has been
drag-and-dropped, all require different sliding speeds and easing functions.
Of course you can hack the animation code so that it infers the right type of
animation from the difference between the current and the previous game state.
This might works most of the time, but besides being ugly, there are cases
where it’s not possible to know whether a given state change came about
through, say, double-click, drag-and-drop, or undo (all of which are animated
In this situation, compromising on the quality of the animations is a
no-brainer for a regular web application. But for a game, animations should
be first-class citizens. Since they are so ubiquitous in a game (even a
simple one like solitaire), treating them as less than first-class citizen will
yield hundreds of lines of unmaintainable animation spaghetti code.
So how do you make animations first-class citizens? Easy enough: You do not
update the game state and then ask the controller to update the GUI according
to the new state. Instead, you send a Command object (as described in
GoF’s Design Patterns) to the game
state so that it can update itself, and then send the same Command object to
the animation method so it can update the GUI based on the type of command.
In other words, the application is now fundamentally structured around state
transitions (commands, that is) rather than states.
This approach is probably untypical for “regular” web apps, and frameworks like
Ember.js discourage it by exposing state and hiding state transitions behind
the auto-updating mechanism for object attributes. Besides animations, the only use case I can
think of is when you absolutely need to build an undo stack: With your code
structured around state transitions, you can easily use Command objects for the
undo stack, rather than ad-hoc closures (or clones of the model object). Other
than that, I am not sure if for a non-game app that doesn’t require
sophisticated animations, this is worth the effort.
However, for game code, I have found that this pattern works very well, and it
has turned out to be very maintainable so far.
As I structured my app around Commands, my reliance on Ember’s features
started to disappear, and eventually I was left with Ember’s slightly
cumbersome attribute accessor syntax (
card.get('rank') instead of
card.rank) with no benefit from it, as all my attributes had become
independent, and no auto-updating between objects (“binding” in Ember
parlance) was going on anymore.
The only thing Ember was doing for me was templating with Handlebars, but since
all I render are cards (essentially
<div class="card" id="..."></div>), I
So I removed the dependence on the Ember.js library. What was left was an
application handsomely structured around the MVC pattern, and compared to the
initial version I hacked together, the logical separation into model and
presentation code is the biggest single design improvement.
A Look at the Code
I haven’t found it necessary to derive either models or controllers from a
common base class.
The models hold the game state and implement the game (domain) logic. I
deliberatedly kept the models isolated from the rest of the application, so the
code doesn’t know about the controllers or views, and also doesn’t need a DOM.
This has made the code much more maintainable. I’m also hoping that it will
help me when I write tests, perhaps with Mocha.
The Card model is very simple. It only holds three attributes –
id – and no logic at all. Whether it is face-up or face-down is
inferable from its place in the game (stock cards are always face-down, waste
cards are always face-up, etc.), so that is something that is determined by the
controller that renders it, not stored by the model.
1 2 3 4 5
Game State Model
The game state model, on the other hand, is rather more complicated. It holds
several arrays of cards (stock, waste, tableau piles, foundations), and encodes
the rules of the game (the domain logic, that is). Here is a slightly
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
While the model implements rule logic (with methods like
it does not enforce it. The controller has to check whether a given action is
legal in order to give proper user feedback. It then seemed redundant to
implement another such check in the game state model.
For simplicity’s sake, I decided not to let model classes proliferate: The piles
that make up the game state model (stock, waste, etc.) are dumb arrays, not
models on their own. Any logic that might conceivably be attached to those
piles is moved up into the all-knowing game state model.
Paralleling the models, there is a simple Card controller performing basic rendering
duties, and a game controller (App.Controllers.KlondikeTurnThree) ordering the
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
To be honest, I’m finding that my game controller is becoming a sprawling
assortment of semi-related methods. I think this in part due to GUIs being
messy business, and in part due to suboptimal design. Eventually I will have
to split it into more classes, but for now it actually works quite well.
Views and Templates
The view classes and templates that most frameworks expect you to create have
been folded into the Controller classes. There is the occasional
$('<div, and the cards are rendered by programmatically
by creating DOM nodes:
1 2 3 4 5 6 7
So far I haven’t needed to separate these from the controllers because they are
so miniscule. (I am sure that this will not scale though, and if you are using
an MVC framework that comes with templating functionality, you should
definitely use it from the get-go.)
Ember.js rocks because it can propagate (bind) attributes between objects,
and it auto-updates templates live without rerendering.
But attribute propagation is suboptimal for games, since animation requires
that you know about state transitions, not just state.
For any app, it greatly helps the design to follow MVC:
- Create isolated model classes storing application state and implementing
- Create controller classes that talk to the models and the DOM,
implementing the GUI logic.
- Factor templates out of the controllers.
- Factor helper methods for the templates into view classes.
- Create isolated model classes storing application state and implementing
Read more at the source