2. Every application, ever*
● Subsystem lifecycle
● Long running processes
● Connections pools
● Caches
* almost
3. The Clojure Curse*
* http://www.winestockwebdesign.com/Essays/Lisp_Curse.html
● Clojure can do anything
● No official app framework
● NIH is a risk
● We went there...
4. Take #1 ~ Atoms ?
(def ^:dynamic server (atom nil))
(defn start [config]
(reset! server
(make-server config)))
(defn stop []
(.stop @server))
5. Take #1 ~ Atoms ✘
● Easy :)
● Shared state :(
● All over the place :(
● Reload unfriendly :(
● No dependencies :(
7. Take #2 ~ Maps ✘
● Pure functions :)
● Reload friendly :)
● All in one place :)
● Ad-hoc lifecycle :(
● No dependencies :(
8. Take #3 ~ Components ?
(defrecord Server [server config]
component/Lifecycle
(start [this]
(if server ; already started
this
(assoc this :server (make-server config))))
(stop [this]
(if-not server ; already stopped
this
(do
(.stop server)
(assoc this :server nil)))))
9. Take #3 ~ Components ✔
● Pure functions :)
● Reload friendly :)
● All in one place :)
● Lifecycle API :)
● Dependencies :)
10. Caveat emptor
● Invasive
● All fns that reify the module's behaviour
●
Wish clj had Erlang's parameterized modules*
● Records can be weird
● lein clean is your friend
* experimental feature, now removed :(