Recently I’ve been reading the excellent Web Development with Clojure. As I’m following along, I found myself constantly restarting the REPL because of either a new module or a new function is introduced. The time it takes for the REPL to restart is long enough that it breaks my flow. I don’t know why the REPL restart time did not bother me as much when I was working on my recent projects, Shows and Bitpub.

In any case, a tight feedback loop is essential to REPL-driven development. I understand there is a famous blog post by Stuart Sierra regarding his workflow, and a few other projects that help with Clojure workflow. Ultimately, I decided to use Stuart’s idea and tools.namespace to create a quick and dirty solution that helps me as I follow along the book.

Following Stuart’s idea, I have a constructor for the app. It returns a map, that contains an atom which then holds an instance of the application server, jetty. But notice that it is private.

(defn- create-app []
  {:server (atom nil)})

The way to start the app is to use the start function. One way I make it more convenient for myself, but less portable is the use of intern. I use intern to create a Var in the user namespace called app. The value of the user/app is the return value of create-app, the constructor.

(defn start [& [port]]
  (let [app (var-get (intern 'user 'app (create-app)))
        port (if port (Integer/parseInt port) 8080)]
    (reset! (:server app)
            (serve (get-handler)
                   {:port port
                    :init init
                    :auto-reload? true
                    :destroy destroy
                    :join true}))
      (println (str "You can view the site at http://localhost:" port))))

Reloading is very similar to how it is described in the README of tools.namespace. Everytime restart is called, it will stop the current application server, refresh all the namespaces that are changed and start a new application server. one

(defn restart [app]
  (stop app)
  ;; gallery.repl is the module where
  ;; start and restart are defined
  (refresh :after 'gallery.repl/start))

Now my work flow becomes quite compact and fast. No more restarting the REPL. Plus, I can experiment in the REPL against the running application.

user=> (start)
;; editing...
;; The start function intern's app into the user namespace.
;; So, I can pass it into restart.
user=> (restart app)
;; more editing...
user=> (restart app)

There are quite a few drawbacks to my approach, but, so far, it works quite well for my use case. If you are developing a proper application from scratch, I would suggest using either compojure, or jig.