Building Noughts-and-Crosses in ClojureScript
I've been experimenting with
front-end development to avoid the hype and chaos attendant to
Om, from David Nolen (whose blog,
webinars, and conference talks are incidentally fabulous and highly
recommended). Om has practical upsides like good documentation and an
active community. It also enunciates a coherent picture of how to do
front end development with immutable data structures, a virtual DOM,
and the power of Clojure's
NAC is a simple noughts-and-crosses (or tic-tac-toe) game implemented
in about 200 lines of nicely formatted and commented ClojureScript
(and another ~100 lines of HTML and CSS). Adopting some of the tricks
in David Nolen's
core.async webinar, I
settled on a design where the leaves of my DOM tree generated events
when clicked which were propagated through
towards the app's top-level until they reached a scope where they
could be effectively handled.
For example, clicking on a filled space in the board generates an event which is immediately squashed. A filled cell knows that nothing will come of that action, even with its narrow perspective.
By contrast, a click in an empty cell needs to propagate to the top level (where we track whose turn it is) in order to move the game to its next state.
This sort of architecture certainly has pitfalls, and I expect having to deal with more kinds of event and a more complicated app-state will require more careful design. ClojureScript provides lots of facilities for working with this kind of hierarchy; I used none of them, but it's comforting knowing they're there for when I want to build something less trivial. The broad strokes of the architecture felt suitably de-complected and scalable.
The ClojureScript build process and ecosystem is (I hear)
much-improved from the bad old days, but it's still by no means a
straightforward and smooth process. The documentation for the
cljsbuild Leiningen plugin is wanting,
Hopefully Chestnut, (a collection of best-practices and solid tools for interactively building and compiling front-ends with ClojureScript) will alleviate some of these problems. It's been very promising to work with, and I hope it goes some way to alleviating the worst headaches of developing interactive front-ends with ClojureScript.
The Virtuous Learning Curve
The extra work put in to get from zero-to-sixty with ClojureScript isn't arduous, and it feels like laying good groundwork for further acceleration.