Clojure is a powerful, fun and highly productive language for developing applications and services. The clear language design is supported by a powerful development environment known as the REPL (read, evaluate, print, loop). The REPL gives you instant feedback on what your code does and enables you to test either a single expression or run the whole application (including tests).
The approach I take is called REPL driven development and I’ll explain that here in detail.
As soon as I open a Clojure file I will start the REPL. Coding without a REPL feels like tying my hands behind my back. I want to get fast feedback from my code as I design it, testing my assumptions and design choices.
I use Spacemacs as my editor which allows me to evaluate code and display the results of individual expressions in-line.
As I am designing my code, I evaluate expressions and print the result under the expression as a comment. Adding results as comments is a great way to demonstrate the design of your code in a journal.
It is highly recommended to journal your design process to make your code easier to understand and maintain. Journals avoid the need for long hand-over or developer on-boarding processes as the journey through design decisions are already documented.
It is recommended to create a Design Journal section at the bottom of each namespace. This journal should cover
- All the important REPL experiments used to create the resulting namespace code.
- Discussions of design choices, including those not taken and why.
- Expressions that can be evaluated to explain how a function or parts of a function works
The design journal can be used to create meaningful documentation for the project very easily and should prevent time spent on repeating exactly the same conversations.
To create code of high quality and in a consistent style with the rest of the Clojure community, I use linting tools that also give fast feedback as I am writing the code.
Joker and Eastwood are linter tools that will highlight code that doesnt follow style and can be configured to do this as you type. This makes it quick to fix little errors before they turn into an anoying bug.
Kibit is a static code analyzer for Clojure, ClojureScript and Clojure common. It uses core.logic to search for patterns of code that could be rewritten with a more idiomatic function or macro. This helps make the finished code more elegant and of course idiomatic Clojure.
You can use Test Driven Development and REPL Driven Development together. There is a very natural merging of these approaches as they both encourage incremental changes and continuous feedback. Test Driven Development also works well with Hammock Time, as you should spend more time thinking about what you want to do than typing code. Tests provide an easy way to define and test your assumptions of your well considered design
With the power of the REPL, it is easy to get feedback on exactly how your code works. Tests provide the codification of your evolving design and give you feedback when you break that design.
At some point before production you should have unit tests around the public API of each namespace in your project to catch regressions before committed. It is much more efficient in terms of thinking time to create these tests as you stabilise the design that as an after thought. So it makes sense to write these tests as part of the design process.
Set up an automated test runner that will run on each file save
Wire up a continuous integration server that runs tests and builds code on every shared commit (or every commit if you run a CI server locally).
Spin up testable deployments of your application or service based on pre-defined branch commits or every commit if you do not share branches (i.e. push to shared master or develop branch), eg. Heroku Pipelines.
REPL Driven Development gives you a powerful and fun way to design software, giving you fast feedback on multiple aspects of your code design.
The only risk with REPL Driven Development is you may never want to code without a REPL ever again.
This work is licensed under a Creative Commons Attribution 4.0 ShareAlike License, including custom images & stylesheets. Permissions beyond the scope of this license may be available at @jr0cket