Rich Comments for REPL Driven Development

The (comment ,,,) form is commonly used to contain living experimental code, so it is often referred to as a rich comment as its purpose is more than just commenting out code.

Experimental design

Whilst iterating through designs, much experimental code can be created which is not (yet) ready to be part of the main namespace.

Experimental code can be written in a (comment ,,,) form to keep it separate from more finalised implementations.

When a namespace is evaluted, code within the (comment ,,,) form is not automatically loaded.

Most editors support evaluation of Clojure code within the (comment ,,,) form, allowing a range of design implementations to be evaluated against each other.

Rich comment blocks are very useful for rapidly iterating over different design decisions by including the same function but with different implementations. Hide clj-kondo linter warnings for redefined vars (def, defn) when using this approach.

;; Rich comment block with redefined vars ignored
#_{:clj-kondo/ignore [:redefined-var]}

  (def data-model {:nested {:hash "map" :design "choice"}})
  (def data-model [{:collection "of" :hash "maps" :design "choice"}
                   {:collection "of" :hash "maps" :design "choice"}])

  (defn value-added-tax []
    ;; algorithm - initial design)

  (defn value-added-tax []
    ;; algorithm - alternate design)

  ) ;; End of rich comment block

Design Journal

When the problem domain or libraries selected are relatively unknown, a significant amount of learning and experimentation may be required. This learning can be captured in a separate namespace, often referred to as a design journal.

Creating a journal of the decisions made as code is designed makes the project easier to understand and maintain. Journals avoid the need for long hand-over or painful developer on-boarding processes as the journey through design decisions are already documented.

A design journal can be added as a (comment ,,,) section at the bottom of each namespace, or more typically in its own namespace.

A journal should cover the following aspects

  • Relevant expressions use to test assumptions about design options.
  • Examples of design choices not taken and discussions why (saves repeating the same design discussions)
  • Expressions that can be evaluated to explain how a function or parts of a function work

The design journal can be used to create meaningful documentation for the project very easily and should prevent time spent on repeating the same conversations.


clojure-lsp contains a number of snippets to create variations of a comment form.

  • rich-comment a basic comment form
  • rich-comment-rdd comment form that informs clj-kondo to ignore duplicate function definitions, avoids warnings when testing multiple implementations of the same function
  • rich-comment-hotload - comment form with Clojure CLI library dependency hotloading via add-libs

Migrating design to tests

Code within rich comment blocks is often a good source of code that can be put into formal unit tests, using clojure.test

REPL Driven Development and Test Driven Development

Live examples

A rich comment at the end of a namespace can include code that demonstrates how to use the key aspects of the namespace API.

Rich Comments - living documentation of a namespace

results matching ""

    No results matching ""