REPL Driven Development
REPL driven development is the foundation of working with Clojure.
The REPL is an instant feedback workflow that continually runs your code without the need of a separate compile-build-run cycle. The REPL contains your live application to which you interact with by calling(evaluating) code.
Always run a REPL
Coding with a REPL provides fast feedback as design decisions are encoded, giving every opportunity to testing assumptions driving those design choices.
Evaluating source code
A REPL is typically used from an editor with files that compose the project code base. A Clojure aware editor can evaluate code from the source code files to and display the results inline.
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.
Add example journal
Viewing data structures
Use Pretty Print to view data structures that are the result of evaluating your code. This makes those data structures easier to parse as a developer and more likely to notice incorrect results.
Data inspectors (cider-inspect, REBL) provide effective ways to navigate through a nested data structures and large data sets.
Code Style and idiomatic Clojure
Your editor should automatically apply formatting that follows the Clojure Style guide.
Continuous linting with clj-kondo significantly reduces a wide range of bugs and syntax errors as they happen, speeding up the development process.
Additional code analysis tools
Eastwood also provides linting and is typically used as a batch process before a code commit or as part of continuous integration.
Kibit provides suggestions to help ensure idiomatic Clojure.
Test Driven Development and REPL Driven Development
Test Driven Development (TDD) and REPL Driven Development (RDD) complement each other as they both encourage incremental changes and continuous feedback.
RDD supports rapid design as different approaches can easily be explored and evaluated. and tests focus the results of those experiments to guide delivery of the correct outcomes.
Tests provide an simple tool to define and test your assumptions from the evolving design and give you feedback when changes break that design.
Unit tests should support the public API of each namespace in a project to help prevent regressions in the code. Its far more efficient in terms of thinking time to define unit tests as the design starts to stabilize that as an after thought.
clojure.test library is part of the Clojure standard library that provides a simple way to start writing unit tests.
Clojure has a number of test runners available.
Continuous Integration and Deployment
Wire up a continuous integration service that runs tests and builds code on every shared commit (or every commit if you run a CI server locally).
CircleCI provides a simple to use service that supports Clojure projects.
Defining a deployment pipeline provides an efficient way to deploy applications and also get fast feedback from a wider range of stakeholders and users, especially when spin up testable deployments of your application based on commits (i.e. push to shared develop or feature branch).
Ideally the deployment should run via continuous integration service to ensure all tests pass before deployment.