TL;DR For all that people think of Clojure as a “hard” “propeller-head” language, it’s actually designed right from the start not for intellectual purity, but developer productivity.
I thought I’d share my recent experiences of developing a commercial Clojure application. It’s currently racking in about 800 lines of Clojure and 2000 lines of CoffeeScript. I avoided ClojureScript for the simple reason that I had no experience in it, so I’m afraid I have no great insights there. I guess it’s worth pointing out that although this is the first time I’ve really used Clojure in anger, I’ve been studying it for two years and have spent weeks of time practicing. I can recommend pretty much all of the main teaching tools, labrepl, Clojure koans and 4clojure.
So, what does the application do? It’s a web tool for calculating and analysing various costs my bank incurs. The calculation itself and the UI is pretty much entirely in CoffeeScript using Backbone and jQuery. The 800 lines of Clojure perform the following functions:
- A REST back end for the data.
- Windows authentication
- Serving the front page, which is the entire application.
- User permissioning
- A quick asset pipeline that compiles the CoffeeScript on demand.
Adding Excel export shouldn’t make the code base much larger, maybe another 100 lines. I should add that most of those 800 lines aren’t long and a fair number of them are blank. To give you an idea of just how expressive this is, I had an earlier back end written in C#. 800 lines wouldn’t get you to the end of the entity definitions and NHibernate mappings.
More Than Just Concise
I suspect even Clojure’s greatest detractors would agree that it’s terse. However, the real win is just quite how productive it is. The more I’ve worked with it, the more surprised I’ve been and just how effective it can be. Whilst certain languages on the functional side such as OCaml, Racket and Haskell have communities that have many competing priorities, of which developer productivity is only one, Clojure has a laser focus on beating the averages. The first and most significant of the productivity features is its status as a JVM language. This gives you access to a huge number of libraries straight out of the box:
- JTDS (which I used for SQL Server and Sybase connectivity)
Without POI, Excel export would be just a CSV file. Without Waffle, Windows Authentication would be impossible: that is to say, there’s no way I could justify the expense of getting it to work and I’d have been left with implementing my own authentication system. JFreeChart wasn’t absolutely essential: I could probably have got away with drawing the images myself, but still my productivity was raised by having it there. Finally, JTDS is rock solid and fast. The database connectivity story of Java is light years ahead of anything you’ll see in Node,* never mind Haskell.
There is a catch to all of this: you have to read and work with Java. This isn’t particularly hard, but it means you become very familiar with the wall of inanity. (I keep thinking “seriously, how many layers of abstraction do you need?”.) However, there are thoughtful features that enhance the Java experience. .. gives you the ability to chain method calls with less ceremony than Java. “doto” gives a the advantages of jQuery style chain syntax without any need to change the underlying methods. Finally, the REPL is a real help. Getting the exactly correct chart settings is much easier when you can adjust it on the fly. (You’ll note that this is a scenario that TDD doesn’t help you with at all.)
Better Than A Better Java
After the ability to just use Java libraries, there comes the excellent Clojure libraries. Leiningen is an excellent build tool. clj-webdriver takes the pain out of Selenium programming. Andrew Brehaut has already written a pretty definitive guide to the Clojure web stack. I’ve had the ability to edit any file in my server and have the changes reflected immediately (providing the file compiled).** It’s amazing how few web frameworks can actually do this. For instance, ASP.NET can do it for views, but not models or controllers.
More than just the fact that they’re good is the sheer pleasure of interoperability. A lot of this comes from the basic philosophy of composability. When everything’s a function, sequence or a hashmap, connecting one module to another is pretty easy with very few dependencies. It’s also eminently testable. However, Clojure goes deeper than that with extremely thoughtful features. For instance, I’m using incanter to generate charts. They return JFreeChart objects. Compojure defines a protocol called Renderable that allows you to specify how return types get converted into Ring responses. Now, you could apply an adapter pattern in most languages to link these two up. In Clojure, you can declare that a type implements a protocol and it just works. You don’t need to extend the type; you don’t need to monkey patch it; you don’t need to introduce a proxy object under your control.
There are other features that make developing easier as well, such as macros, dynamic binding, software transaction memory and multimethods, that I haven’t even needed to use. I’m left with a very readable code base that is sensibly structured and easily expandable. Surprising as it may seem, I’ve actually found it even faster to use than node.js.
*Although Brian Carlson’s node-postgres is quite superb.
**Some of this I wrote myself, but frankly, it only took few hours, and that included figuring out how to integrate with Leiningen.