First of all, the choice of Clojure for the types of problems Runa is set out to solve is beyond the doubt is the right one. For any data centric projects, Clojure seems to be the best suited language out there for now. However, the aim of my post is not to convince what has already been pretty well known about Clojure. Rather, I would like to share few things about Runa's Clojure projects. Since I started with Runa, I found following about a project that I was assigned to work:
- TDD is done right. As stated in Amit's excellent book, Clojure in action, Runa really does stick with and encourage developer to use TDD. The project is very well tested and working with it has been a joy so far. In case if you have not read the book yet, the usual TDD flow is: Write failing test -> Make it pass -> Refactor and repeat. For example, if you are testing for existence of a particular information in a log file, which in turn comes from some configuration file, here is how you would put TDD in practice (Will post concrete examples in my next blog post):
- Put the information in the config file and make the test pass
- Refactor such as separate out config file creation and deletion using high order function.
- Small core. What I am very excited about the project is that there is no frameworks or huge external library dependencies in it. It has minimal external libraries and has a very small and well tested core. Usage of fast and small library is always preferred to keep its foot print small. This has also added benefit of much portability in terms of deployment and being used as a module for other projects. The project is a high performance web service and it does not even use ring or compojure. It just uses jetty library.
- Clojure can be fast, I mean really fast. There are many ways to speed up clojure projects such as type hinting, using memoziation and using performant data structures such as chuncked sequence. But there are cases that one can utilize plain old java to speed it up even more. The project has very strict response time (a request response time has to be under 3 millisecond). Since we are all stateless, we end up using number of single java thread processes for logging, monitoring,instrumentation and also java queues from java.util.concurrent package. Now we are able to serve 40 thousand requests per second under 15% load capacity of per app instance.(The app is deployed on over a dozen nodes with a load balancer routing requests). I will blog with more details such as performance charts and overall big picture design in my future blog posts.