Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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. (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)))
  2. (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))
  3. (ns playitloud.ho.player) (defn play [blarefn songgetterfn randomize] (let [songs (songgetterfn)

    songs (if randomize (shuffle songs) songs)] (map (fn [song] (blarefn song)) songs)))
  4. (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)))
  5. (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))))
  6. (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)))
  7. (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*)))
  8. (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)))
  9. (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))
  10. (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)))
  11. (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)))
  12. (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)) ;[...]
  13. (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)))
  14. (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))
  15. (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))
  16. (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))
  17. (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))))
  18. (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)))
  19. (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)))
  20. (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))
  21. (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]))))
  22. (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))
  23. (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)))
  24. (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 " ; ...