Setting up a Clojure project in 2017
The challenge
After at least two year of Clojure abstince, I explored libraries for an application exposing REST services. The system design is trival, a database and a couple of REST services exposing the data in various forms.
The surprise
The Clojure world seems to undergo a phase of library consolidation. After years of heavily exploring new approaches, some libraries are successful while many projects are actually dead.
This is not something bad. In my option it is a consequence of developers with background in other languages carried over concepts just to find out that it is actually not needed.
SQL
I explored libraries to interact with relation databases and I found that Korma, which I used in the past, is getting little community attention. So I explored available options
- https://github.com/korma/Korma
- https://github.com/jkk/honeysql
- https://github.com/r0man/sqlingvo
- https://github.com/friemen/aggregate
- https://github.com/krisajenkins/yesql
- https://github.com/metabase/toucan
- https://github.com/layerware/hugsql
None of those felt like the perfect choice. After reading http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html and http://peterstratton.com/posts-output/2017-01-28-postgres-and-clojure-using-clojure-java-jdbc the need for a library was actually questioned at all. Clojure JDBC has a light abstraction for inserts and updates. In addition it provides options to convert column names when reading and writing. It took 1 hour to write a small abstraction to convert our camelcase to nicer Clojure keywords. Consequently, there is a good chance that a library is not needed at all. We will see if we stay with core Clojure on the long term but currently it is a simple way to interact with a DB.
To have slightly better support for dynamic queries, we are exploring Honeysql as an addition. Many of the named libraries are much more powerful than HoneySQL, but as long as there is no need for more advanced stuff, why add complexity
REST
Exploring REST libraries is trivial as there are many good options. I looked at
- Yada
- Pedestal with Rook
- Liberator
- Compojure only
Compojure is still an option but I found that the REST libraries are mature and simple. For this time, I went with Liberator as it works nicely with Compojure which I have some experience with.
Module system
A module system allows to define modules and dependencies between them. You can start your system and all modules are started depending on their relation and order. A module might read configuration files, another one connect to the DB, start scheduler for cron jobs etc. I liked tolituis/mount. Integrant is a new candidate with nice concepts but it relies on a very fresh Clojure version. For know I postponed using a module system at all, because currently the complexity is not needed. If you are interested, here are some options
- https://github.com/stuartsierra/component
- https://github.com/weavejester/integrant
- https://github.com/tolitius/mount
Testing
I used Midje in the past and had a look at alternatives.
- Plain clojure test with aviso pretty to nicely show test results.
- Expectations with lein-test-refresh to execute tests automatically
- Midje in combination with lein midje
First, all solutions are good solutions. Test failures are very clear and precise. Java please have a look. ;-)
I compared the test runners. Basically, they execute the tests if a test or code is modified. After saving your file, you can see the results in fractions of a second. If you are into TDD this is a productiviy turbo boost.
Expectations
Tests written in Java are verbose, tests written in Clojure are way more conside and small, but this library pushes it to an extreme that is very impressive. If too much code is an issue, have a look at it. The latest versions integrate nicely with standard Clojure test runners as well. It is really worth looking at it.
Aviso
Use it to improve test output with standard clojure test significantly
Midje
- Nice and powerful assertions
- Good support for mocks and pre/post executed code
- Asserts do not look like very “Clojure style”
- Very efficient execution of only relevant tests on code change
The impressive thing of the lein midje :autotest is that it only executes, depending on what you change, the modified test or all tests refering the modified code. This is amazing.
In this case the test execution was the argument to prefer Midje over the other options.
Other stuff
I stumbled upon libraries while looking for security and scheduler. I did not explore them in detail, but the first impression was nice, so I decided to note them here.
Security: https://funcool.github.io/buddy-auth/latest
Scheduler (Later): http://docs.caudate.me/hara/hara-io-scheduler.html
Summary
The first version of the software is ready by now and there is one thing I appreciate a lot using Clojure: simplicity
Here is what we achieved
- Read configuration file from Tomcat data directory or fall back to a configuration in the classpath based on an environment test or development
- Logger integration using an external configuration or as fall back a configuration in the classpath
- Scheduler integration
- Connection pools
- No connection pool for import job
- Tests for REST services, database and unit tests
In other projects, I use technologies like Java, JEE, Spring, Java Persistence/Hibernate. If you have experience setting up a customized Spring configuration, you probably have an idea what complexity is. It requires days of dedication to have a Spring application with mixed security for legacy and REST services nicely in place. But still at the point it works, you do not understand all pieces. Java libraries have a strong tendency to support old approaches they offered once. The downside is if you solve a problem, you find documentation using one approach, another or a mixture of many.
Given my basic Clojure experience, I was impressed how quick everything was in place.
When it comes to simplicity, Clojure rocks.
Best Regards / Viele Grüße
Sebastian Hennebrueder