Migrating PHP to Clojure

I have been developing a large database driven website for a University project, which involves a user accounts system, a search engine frontend and a data analysis backend. Having never written such a system before, I opted to use PHP to create the first prototypes, due in large part to the seemingly endless demand for PHP experience in job postings, combined with the quick “pick up and go” start time offered by Apache with mod_php.

Knowing full well up the front the problems and grudges that many people have with PHP, I thought I’d document my experiences here where, after 3 months of development, I kicked the bucket and reimplemented the entire stack in Clojure.

Why PHP?

In no uncertain terms, PHP is a broken language. I knew this from the outset. My first exposure to the language was in reading Eevee’s excellent deconstruction of some of its many flaws, which I read long before I had even written my first echo "Hello world!";.

Despite this, the undeniable truth is that PHP has been used to write many successful projects, and continues to this day to be an in-demand skill, even if the rumours of its waning popularity are to be believed. However, for a long term solo project, the amount of effort that was being expended working around the caveats of the language started to drain at my enthusiasm for it, so it was time to look a superior alternative.

Why Clojure?

Of the languages which I considered (including the usual suspects of Ruby, Python & Node), Clojure stood out as being the choice that would present the most interesting challenge to work with. Some notable differences:

  • Purely functional programming paradigm.
  • Fresh, and fast paced development of the language.
  • A wonderful dependency management system provided by leiningen.
  • Lower level: there’s no lumbering Apache stack to get you started.
  • The possibility for simple and powerful concurrency.
  • The standard data structures are all immutable.
  • Recursion, Recursion, Recursion, Recursion…

What really appealed to me though is the elegance of LISP dialects. I once spent a rainy weekend working through the first few chapters of SICP, and quickly found myself engrossed in the purity of the language. While the C family of languages feel like an extension of machine code, LISP dialects feel like an extension of mathematics and abstract logic.

Porting the codebase

The rewrite took just over 3 days, and while my experiences with Scheme meant that I was fairly comfortable with the syntax of LISPs, it took a good few weeks afterwards to truly start to get to grip with the paradigm and working with higher order functions. If interested, the git tree before and after the rewrite look like: PHP 8ae6043a9a, Clojure cb8e4caddd. A quick comparison:

PHPClojure
Lines of code42741086
Feature complete-ness75%80%
Test coverage0%5%
DOM Content Loaded1.45 s1.42 s

Advantages:

  • Massively reduced code size. LISP can be an incredibly concise language.
  • Support for simple unit testing built into the core language.
  • Simple plugin and library management.
  • Increased programmer happiness!

Disadvantages:

  • Unstable APIs and changing language spec.
  • Not very much documentation or examples available.
  • Almost all documentation (where found) is out of date.
10 Feb 2014