$30 off During Our Annual Pro Sale. View Details »

Dependency management in Clojure -- long version

schaueho
February 20, 2016

Dependency management in Clojure -- long version

A longer version of the presentation about dependency management in Clojure that I gave at :clojureD 2016, Berlin, which has most of the comments on separate slides and adds discussion of mount.

schaueho

February 20, 2016
Tweet

More Decks by schaueho

Other Decks in Programming

Transcript

  1. None
  2. None
  3. None
  4. None
  5. None
  6. None
  7. defn :refer :refer :all

  8. None
  9. None
  10. None
  11. None
  12. None
  13. None
  14. (ns playitloud.ui-player (:require [playitloud.simple-player :refer [play]])) (defn play-pressed [randomize] (println

    "User pressed play") (play randomize))
  15. (ns playitloud.ui-player (:require [playitloud.simple-player :refer [play]])) (defn play-pressed [randomize] (println

    "User pressed play") (play randomize)) (ns playitloud.simple-player (:require [playitloud.speaker :refer [blare]] [playitloud.musiccoll :refer [get-songs]])) (defn play [randomize] (let [songs (get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (blare song)) songs)))
  16. (ns playitloud.ui-player (:require [playitloud.simple-player :refer [play]])) (defn play-pressed [randomize] (println

    "User pressed play") (play randomize)) (ns playitloud.simple-player (:require [playitloud.speaker :refer [blare]] [playitloud.musiccoll :refer [get-songs]])) (defn play [randomize] (let [songs (get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (blare song)) songs))) (ns playitloud.speaker) (defn blare [song] (let [result (str "Speaker plays " song)] (println result) result))
  17. speaker musiccoll

  18. None
  19. (ns playitloud.ho.player) (defn play [blarefn songgetterfn randomize] (let [songs (songgetterfn)

    songs (if randomize (shuffle songs) songs)] (map (fn [song] (blarefn song)) songs)))
  20. (ns playitloud.ho.player) (defn play [blarefn songgetterfn randomize] (let [songs (songgetterfn)

    songs (if randomize (shuffle songs) songs)] (map (fn [song] (blarefn song)) songs))) ; --------------------------------------------------- (ns playitloud.ho.ui-player (:require [playitloud.ho.player :as ho :refer [play]] [playitloud.speaker :as speaker] [playitloud.headphone :as headphone] [playitloud.blue-streamer :as streamer] [playitloud.musiccoll :refer [get-songs]])) (defn play-pressed [speaker randomize] (println "User pressed play") (condp = speaker :speaker (play speaker/blare get-songs randomize) :headphone (play headphone/blare get-songs randomize) :stream (play streamer/blare get-songs randomize)))
  21. None
  22. (defn make-playfn "Returns a function that will play all songs"

    [blarefn songgetterfn] (fn ; Plays all songs, potentially randomized [randomize] (let [songs (songgetterfn) songs (if randomize (shuffle songs) songs)] (map (fn [song] (blarefn song)) songs))))
  23. None
  24. (ns playitloud.ho.play-config [...] (def speaker-play (make-playfn speaker/blare get-songs)) (def headphone-play

    (make-playfn headphone/blare get-songs)) (def stream-play (make-playfn streamer/blare get-songs)) (defn select-playfn [speaker] (condp = speaker :speaker speaker-play :headphone headphone-play :stream stream-play)) (ns playitloud.ho.clos-ui-player (:require [playitloud.ho.play-config :refer [select-playfn]])) (defn play-pressed [output randomize] (let [playfn (select-playfn output)] (playfn randomize)))
  25. None
  26. (ns playitloud.services.config) (def ^:dynamic *services* {:blare playitloud.speaker/blare :get-songs playitloud.musiccoll/get-songs})

  27. (ns playitloud.services.config) (def ^:dynamic *services* {:blare playitloud.speaker/blare :get-songs playitloud.musiccoll/get-songs}) (ns

    playitloud.services.player (:require [playitloud.services.config :refer [*services*]])) (defn- blare [sound] ((:blare *services*) sound)) (defn- get-songs [] ((:get-songs *services*)))
  28. (ns playitloud.services.config) (def ^:dynamic *services* {:blare playitloud.speaker/blare :get-songs playitloud.musiccoll/get-songs}) (ns

    playitloud.services.player (:require [playitloud.services.config :refer [*services*]])) (defn- blare [sound] ((:blare *services*) sound)) (defn- get-songs [] ((:get-songs *services*))) (defn play [randomize] (let [songs (get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (blare song)) songs)))
  29. *services*

  30. (ns playitloud.sig.output-device (:require [de.find-method.funsig :refer [defsig]])) (defsig blare "Play sound

    loudly!" [sound])
  31. (ns playitloud.sig.output-device (:require [de.find-method.funsig :refer [defsig]])) (defsig blare "Play sound

    loudly!" [sound]) (ns playitloud.sig.speaker (:require [de.find-method.funsig :refer [defimpl]] [playitloud.sig.output-device :refer [blare]])) (defimpl blare [sound] (let [result (str "Speaker plays " sound)] (println result) result))
  32. (ns playitloud.sig.output-device (:require [de.find-method.funsig :refer [defsig]])) (defsig blare "Play sound

    loudly!" [sound]) (ns playitloud.sig.speaker (:require [de.find-method.funsig :refer [defimpl]] [playitloud.sig.output-device :refer [blare]])) (defimpl blare [sound] (let [result (str "Speaker plays " sound)] (println result) result)) (ns playitloud.sig.player (:require [playitloud.sig.output-device :refer [blare]] [playitloud.musiccoll :as mc :refer [get-songs]])) (defn play [randomize] (let [songs (get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (blare song)) songs)))
  33. None
  34. (ns playitloud.di.config (:require [clj-di.core :refer [register!]] [playitloud.speaker :as speaker :refer

    [blare]])) (register! :blare blare) ; --------------------------------------------------- (ns playitloud.di.player (:require [clj-di.core :refer [get-dep]] [playitloud.musiccoll :refer [get-songs]])) (defn play [randomize] (let [blarefn (get-dep :blare) ; <-- get dependency songs (get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (blarefn song)) songs)))
  35. with-registered

  36. (ns playitloud.proto.output-device) (defprotocol OutputDevice (blare [device sound]) (inc-volume [device]) (dec-volume

    [device])) (ns playitloud.proto.speaker (:require [playitloud.proto.output-device :as output :refer :all])) (defrecord Speaker [volume] OutputDevice (blare [_ sound] (let [result (str "Speaker plays " sound)] (println result) result)) ;[...]
  37. (ns playitloud.proto.player (:require [playitloud.proto.output-device :as output] [playitloud.musiccoll :as mc])) (defn

    play [output-device randomize] (let [songs (mc/get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (output/blare output-device song)) songs)))
  38. None
  39. None
  40. None
  41. (ns playitloud.multi.output-device) (defmulti blare "Play sounds on an output device"

    (fn [device sound] device))
  42. (ns playitloud.multi.output-device) (defmulti blare "Play sounds on an output device"

    (fn [device sound] device)) (ns playitloud.multi.speaker (:require [playitloud.multi.output-device :refer [blare]])) (defmethod blare :speaker [device song] (let [result (str "Speaker plays " song)] (println result) result))
  43. (ns playitloud.multi.output-device) (defmulti blare "Play sounds on an output device"

    (fn [device sound] device)) (ns playitloud.multi.speaker (:require [playitloud.multi.output-device :refer [blare]])) (defmethod blare :speaker [device song] (let [result (str "Speaker plays " song)] (println result) result)) (ns playitloud.multi.headphone (:require [playitloud.multi.output-device :refer [blare]])) (defmethod blare :headphone [device song] (let [result (str "Headphone plays " song)] (println result) result))
  44. (ns playitloud.multi.player (:require [playitloud.multi.output-device :refer [blare]] [playitloud.musiccoll :as mc])) (defn

    play [output-device randomize] (let [songs (mc/get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (blare output-device song)) songs))) (ns playitloud.multi.ui (:require [playitloud.multi.player :as player :refer [play]])) (defn play-pressed [output-selection randomize] (println "User pressed play") (play output-selection randomize))
  45. defmulti

  46. None
  47. None
  48. None
  49. (ns playitloud.closure-streamer) (defn blare [connection-config] (let [connection (connect connection-config "

    closure streamer")] (fn [noise] (let [result (str "Streaming " noise " to " connection)] (println result) (transmit connection noise) result))))
  50. None
  51. (ns playitloud.dynvar.config) (def ^:dynamic *streamer* {:connection ; [...]}) (ns playitloud.dynvar.streamer

    (:require [playitloud.dynvar.config :as config])) (defn blare [noise] (let [result (str "Streaming " noise " to " config/*connection*)] (transmit (:connection config/*streamer* noise) result)))
  52. with-... binding map

  53. None
  54. (ns playitloud.comp.streamer (:require [com.stuartsierra.component :as component] [playitloud.comp.output-device :as output :refer

    :all] [playitloud.comp.remote-connection :as remote])) (defrecord BlueStreamer [connection volume] OutputDevice (blare [streamer sound] ;... normal protocol/record implementation ...) component/Lifecycle (start [streamer] (println "BlueStreamer starting") (connect (:connection streamer) streamer) (assoc streamer :status :connected)) (stop [streamer] (println "BlueStreamer stopping") (disconnect (:connection streamer) streamer) (->> (assoc streamer :status :disconnected) (dissoc :connection)))) (defn new-blue-streamer [config] (->BlueStreamer nil (:default-volume config)))
  55. (ns playitloud.comp.player (:require [com.stuartsierra.component :as component] [playitloud.comp.output-device :as output] [playitloud.musiccoll

    :as mc])) (defrecord Player [output-device] component/Lifecycle (start [player] (println "Player started with " "output-device " (:output-device player)) player) (stop [player] (println "Player stopped") player)) (defn play [player randomize] (let [songs (mc/get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (output/blare (:output-device player) song)) songs))) (defn new-player [] (->Player nil))
  56. (ns playitloud.comp.config (:require [com.stuartsierra.component :as component] [playitloud.comp.blue-connection :as blueconn] [playitloud.comp.streamer

    :as streamer] [playitloud.comp.player :as player])) (def default-config {:bt-conn {:name "Fabuluous-Connectivity" :port "1234"} :default-volume 5}) (defn make-player-system "Setup the player system" ([] (make-player-system default-config)) ([config] (component/system-map :connection (blueconn/new-connection config) :output-device (component/using (streamer/new-blue-streamer config) [:connection]) :player (component/using (player/new-player) [:output-device]))))
  57. fun-a A fun-b fun-a A B B A

  58. None
  59. :require :refer

  60. (ns playitloud.mount.streamer (:require [mount.core :refer [defstate]] [playitloud.mount.connection :refer [conn transmit

    send-command]])) (defn create-streamer [connection] (println "Connecting to connection ..." connection) {:connection connection}) (defstate streamer :start (create-streamer conn)) (defn blare [streamer sound] (let [result (str "Will stream " sound " to " (:connection streamer))] (println result) (transmit conn sound) result))
  61. (ns playitloud.mount.player (:require [mount.core :refer [defstate]] [playitloud.mount.streamer :refer [streamer blare]]

    [playitloud.musiccoll :as mc])) (defn create-player [streamer] (println "Will use streamer " streamer) {:streamer streamer}) (defstate player :start (create-player streamer)) (defn play [randomize] (let [songs (mc/get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (blare (:streamer player) song)) songs)))
  62. (ns playitloud.mount.player (:require [mount.core :refer [defstate]] [playitloud.mount.streamer :refer [streamer blare]]

    [playitloud.musiccoll :as mc])) (defn create-player [streamer] (println "Will use streamer " streamer) {:streamer streamer}) (defstate player :start (create-player streamer)) (defn play [randomize] (let [songs (mc/get-songs) songs (if randomize (shuffle songs) songs)] (map (fn [song] (blare (:streamer player) song)) songs))) (facts "Handling state with mount" (with-state-changes [(before :facts (mount/start)) (after :facts (mount/stop))] (fact "We can play over the configured device" (play false) => (just ["Will stream David Bowie -- Blackstar " ; ...
  63. DeferableState IDeref :started

  64. None
  65. None
  66. None
  67. None
  68. None