weavejester / integrant

Micro-framework for data-driven architecture

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tips for reloaded workflow

metametadata opened this issue · comments

It would be great to have a section about the reloaded REPL workflow in the README because it's one of the main reasons one would want to use Component-like pattern.

In particular, it would be interesting to see if there's a reliable way of reloading multimethods. I've stumbled upon a problem of old definition of method still working after it was removed from ns and reset-ing. To solve this particular problem I've ended with this in a sample project:

(ns user
  "Namespace to support hacking at the REPL.

  Usage:
  o (reset) - [re]run the app.
  o In case REPL fails after syntax error, call (refresh) and try again.
  "
  (:require [my-app.core :as core]
            [integrant.core :as ig]
            [clojure.tools.namespace.repl :refer [refresh refresh-all]]
            [clojure.repl :refer :all]
            [clojure.pprint :refer :all]))

(println "Hi dev!")

(def system (atom nil))

(defn -start
  []
  (reset! system (ig/init core/config)))

(defn -stop
  []
  (swap! system (fn [s] (when s (ig/halt! s)))))

(defn reset
  []
  (-stop)

  ; this will force reloading of the methods
  (remove-all-methods ig/init-key)
  (remove-all-methods ig/halt-key!)
  ; etc.

  ; refresh-all is used instead of refresh because we've just removed all the methods and want to find all the definitions
  (refresh-all :after 'user/-start))

But I'm not sure if refresh-all is going to be fast enough in bigger projects.

Rather than including it in the README, I was going to write an "integrant-repl" project that mimics my existing "reloaded.repl" project.

With regard to reloading multimethods, it hasn't been something I've thought about a lot, yet. One possibility is to create an improved defmethod that attaches some namespace metadata to the function before attaching it to the multimethod.

I've created an Integrant-REPL project, now.