When I don’t recommend Clojure

Considerations for founders and CTOs

To put it bluntly, Clojure is the best general-purpose language, period.

Few times one witnesses languages with close to zero design mistakes — no gotchas, no complexity, no bloat, plus an eye for performance.

A language healthily stable when you need it -no breaking changes, version after version-, while remaining sharply innovative, fostering a fertile ground for futuristic programming throughout the whole community.

A language which you can learn once and apply to the full stack — which is not realistical to say of interesting challengers like Elm, Swift, Elixir etc.

Its emphasis on interoperability turned out to be its ‘killer app’. It is priceless to be able to leverage the existing, ever-evolving Java and JavaScript ecosystems, job markets and so on.

However that doesn’t mean that as of today, it is recommendable for every project to be written in (or rewritten to) Clojure/ClojureScript.

What should we keep in mind?

Easy can be good enough

Simple Made Easy is hardcoded into the mind of every great Clojure developer. It cannot be overstated how valuable it is to be able to discuss with peers having a common, more-or-less objective framework of thought.

However, this notion of simplicity is not the only consideration to take when planning for success.

One can trade simplicity for easiness, only at the cost of very delimited complexity.

Clojure has been around for 10 years (and with acceptable success / no signs of stalling). And do we finally have…

A go-to web framework?

A go-to type system?

A rock-solid means of developing Android/mobile applications?

I am aware that choice is good, and that in fact Clojure fosters a composition-centric (‘frameworkless’) mindset. But compare the three bullet points with:

Elixir, which since day one had Phoenix as its accompanying web framework.

Elm, which provides an expressive, static, apt-for-frontend type system and is achieving remarkable success.

Kotlin, which achieved in a few years what Clojure (arguably) didn’t in 10: real-world adoption for Android, in all kind of dev shops (as opposed to ones that happened to use Clojure already).

Meanwhile, in the Clojure world we are in a constant quest for ever better things. Such mindset is healthy, but in fact, ironically the excess of choice can result in subpar quality.

Take clojure.spec for example.

Undoubtedly, it is an original idea which is well-suited for dynamic languages. It offers advantages well beyond of acting like a type system (generative testing, etc).

But in fact, many people will use it with ‘typing’ as the primary goal. And they’ll find out that one needs to augment clojure.spec with custom facilities. Many real-world teams have developed their own little libraries, their own ad-hoc conventions for how to use clojure.spec in a good way.

That, in practice, means that one is developing his own island - his own type system, and not a statically checked one. So one is given less safety, at a higher cost.

Wouldn’t be just better off with the easier alternative — a language with a existing, single, static type system?

(note that there’s life beyond Haskell, Java or Scala. Types can be enjoyable for a broad audience!)

Our handcrafted solutions may be simpler, but also costlier and occasionally weaker (custom frameworks are easy to be left incomplete).

Same story goes for web frameworks, test frameworks, Android, React Native, React SPAs, and whatnot.

Clojure is a jack of all trades, yet a master of none.

Macros, simplicity, and FP aren’t a recipe for success. Diligent constant work is.

This is not to bash Clojure and its vibrant ecosystem in any way. Rather, what I intend to transmit is — Clojure has a cost, and in the wrong hangs it will be a source of pain.

Demanding requirements

Clojure is not built around easiness. For comparison, you can give a seasoned programmer a language like ES6 or TypeScript, plus a ‘framework’ (like Create React App) and he’ll be productive and up-to-date with the whole ecosystem in a matter of days.

(Sadly), easy is the way how generally the state-of-the-art in the industry progresses. Syntax sugar and handy tooling have been a constant in every language that has directly beaten Clojure (resulting in 10x more jobs, AFAICT): Scala, Elixir, Ruby, Elm, Kotlin…

It is particularly illustrative the fact that ES6 is generally always used under a transpiler. So if you compare the ES6 and ClojureScript development experiences, both are quite similar, suffering from similar pains (no native debugger with access to the environment).

And yet, non-Clojure people go with transpiled ES6, or compiled TypeScript, Elm, etc far before considering ClojureScript. The reason, as mentioned, is the lack of focus on easiness — which includes things like IDE support, linters, compilation times, npm interoperability, healthily more limited choices, a complete story for testing, etc.

All of this results in that if insufficient care is given, a given Clojure team can lag behind with suboptimal tooling, techniques and practices. It happens.

For better or worse, Clojure takes years to master.

This means that real-world projects -subject to budgets, deadlines- can be overly dependent in individual team members.

Good developers come and go. What will you do when your strongest Clojure experts leave?

Lack of de-facto standards in the Clojure world can mean that disagreements within your team can get tangled. Who to believe?

For these reasons, I don’t recommend Clojure to non-technical solo founders, or CTOs who aren’t already strong in Clojure (or very close technologies) and can’t closely oversee the development of a Clojure project.

If contrariwise, you know your Clojure well and can sustainanly develop/deliver a project through most of its lifecycle, then yes, of course I cannot discourage you.

Clojure is a sharp tool. I find it honest to only recommend it to the right hands, avoiding incorrect claims and hopes.

Lastly, I cannot but encourage enthusiasts to contribute to Clojurists Together. Some of the mentioned pain points can be addressed by funding key projects. I believe that this funding can have a compounding effect, resulting in more real-world projects, more jobs, more libraries… a virtuous feedback loop.

Happy hacking!