I recently launched a little side-project web app, School Seating Charts, which makes it easier (and faster!) for teachers to build seating charts for their classrooms. The site is built entirely in Clojure and ClojureScript, which have been a pleasure to work with.
While writing this post, I realized that, for better or worse, I have a lot to say about Clojure and ClojureScript development. So, to make my life easier I’ll be splitting my thoughts into several posts. In this first post, I will give a general overview of my development experience, and in future posts I will dive more deeply into the details.
To build the app, manage dependencies, and generally keep myself from setting my hair on fire, I use Leiningen. There’s not much that needs to be said here — if you’re using Clojure without Leiningen, you are doing it wrong!
I develop Clojure with Vim, which puts me in the (slight) minority versus Emacs users. Overall, while the LISP-editing tools in Emacs are probably more refined, editing Clojure in Vim is not bad at all. Between VimClojure and Paredit.vim, I’m not left wanting. If you go down the VimClojure route, be sure to use the lein-tarsier Leiningen plugin, which makes it much easier to get Vim talking to an instance of your app.
Finally, of course, I use the lein-cljsbuild Leiningen plugin for compiling and testing my ClojureScript code (as the author of the plugin, it would be a bit weird if I didn’t). School Seating Charts is the reason that lein-cljsbuild exists in the first place — it’s a classic example of an open source project scratching its author’s itch.
The app runs on Google App Engine (GAE). Now, I work for Google, so I’m probably biased (although I began working for Google well after I chose to target GAE), but I have been really happy with it so far as a Clojure deployment target.
GAE supports Clojure by virtue of the fact that it supports Java. There’s a lot of interop required to work with the GAE APIs, but luckily the appengine-magic library has already taken care of almost all of this by wrapping the Java APIs in an idiomatic Clojure API. With this in place, it really feels like there’s native support for Clojure.
Like many other cloud providers, GAE takes care of a ton of the fundamentals for a web app: the database, memcache, server infrastructure, load balancing, logging, metrics, and a lot more. This convenience comes with many restrictions, though, such as limited access to local files and outgoing network connections. However, my app’s requirements happened to mesh nicely with the features and limitations of GAE, which I think is a large part of the reason I’ve been so happy with it.
Deployment to GAE is simple. The lein appengine-prepare command gets things ready and then the GAE SDK takes it from there and uploads and starts the new version of the app.
ClojureScript: The Good
What kinds of code does School Seating Charts share between Clojure and ClojureScript? Well, my favorite thing is all of the HTML IDs and CSS selectors. The HTML generated by the server and the DOM lookups made on the client always agree because the IDs and selectors are defined in one spot. This helps to prevent a whole class of errors from those things being mismatched.
The app’s config API is shared between the client and server. So, things like “is debug mode on” or “what’s the price of the app” come from a central place and are handled by the same code, so the client and server always agree on their values. Other shared code includes various geometry utilities that are required in both places.
ClojureScript: The Bad
So, what are ClojureScript’s rough edges? Well, there are a few things. For one, with so few people using the language, you are more likely to run into edge-cases that haven’t had the bugs beaten out of them. For instance, I used ClojureScript’s pr-str function to serialize data structures to send to the server. Apparently, not many other people had tried using pr-str with a large data structure on IE8. Performance was unusably bad, and I ended up having to patch the compiler to get acceptable performance.
With all of that said, please don’t take my criticisms of ClojureScript too seriously. In reality, it’s inspiring that the language is scarcely 14 months old and yet is totally usable for production systems. The community around the language is aware of all rough edges that I highlighted, and there’s work being done to address them all.
This is just a survey of all of the app’s direct dependencies, taken from its project.clj config file. Some of these libraries are pretty specific to the way the app is built (stripe-java), and others are likely to be found in every Clojure web app out there (compojure).
Makes it much easier to write a Google App Engine app in Clojure. clj-stacktrace
Handy for printing out nicely formatted (and colored) stacktraces. clj-time
An idiomatic Clojure wrapper around Java’s Joda Time library. com.cemerick/friend
Makes authentication and authorization straightforward for Compojure apps. com.stripe/stripe-java
With this, the server-side billing code took maybe an hour to write and test. compojure
A simple and beautiful HTTP routing layer on top of Ring. crate
Provides the same HTML DSL as Hiccup, but for ClojureScript. hiccup
Provides a simple DSL for building well-formed HTML. jayq
A little ClojureScript wrapper around common jQuery features. midje
A test framework for Clojure with very powerful mocking capabilities. prism
A tiny library to help share code between Clojure and ClojureScript. slingshot
A nice little improvement on the built-in exception features in Clojure.
If this post was interesting, you might want to tune in for the next post in the series. I haven’t written it yet, but I promise it’s coming soon!