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

About Integrant

5335315769ef28d5b1b2ddbd776cef2d?s=47 ayato
March 13, 2017

About Integrant

5335315769ef28d5b1b2ddbd776cef2d?s=128

ayato

March 13, 2017
Tweet

Transcript

  1. *OUFHSBOU ʹ͍ͭͯ !@BZBUP@Q$ZCP[V4UBSUVQT JOD

  2. 自己紹介 •あやぴー •朝ジムを倒しまくってる •普段はComponentベースでシステム開発

  3. Integrant概要

  4. Integrantとは •Jamesオジサンが作った新しいデータ駆動
 アーキテクチャなマイクロフレームワーク •つまり、ライフサイクルを管理するライブラリ •Componentで指摘された課題を解決しようとしたもの •システムがデータから組み立てられる •各コンポーネントは必ずしもマップやレコードである 必要はない

  5. データによるシステム定義 •ednでシステムを定義できる {:adapter/jetty {:port 8080, :handler #ref :handler/greet} :handler/greet {:name

    "Alice"}}
  6. Multimethodによるコンポーネント定義 •レコードやマップに限らず関数やただの数値などもコン ポーネントにすることが可能 (require '[ring.jetty.adapter :as jetty] '[ring.util.response :as resp])

    (defmethod ig/init-key :adapter/jetty [_ {:keys [handler] :as opts}] (jetty/run-jetty handler (-> opts (dissoc :handler) (assoc :join? false)))) (defmethod ig/init-key :handler/greet [_ {:keys [name]}] (fn [_] (resp/response (str "Hello " name))))
  7. 一時停止と再開のサポート •再起動が遅くなるのを回避できる •suspend-key!とresume-keyがポイント •初期化処理にも多少影響がある

  8. 一時停止と再開のサポート (defmethod ig/init-key :adapter/jetty [_ opts] (let [handler (atom (delay

    (:handler opts))) options (-> opts (dissoc :handler) (assoc :join? false))] {:handler handler :server (jetty/run-jetty (fn [req] (@@handler req)) options)})) (defmethod ig/halt-key! :adapter/jetty [_ {:keys [server]}] (.stop server)) (defmethod ig/suspend-key! :adapter/jetty [_ {:keys [handler]}] (reset! handler (promise))) (defmethod ig/resume-key :adapter/jetty [key opts old-opts old-impl] (if (= (dissoc opts :handler) (dissoc old-opts :handler)) (do (deliver @(:handler old-impl) (:handler opts)) old-impl) (do (ig/halt-key! key old-impl) (ig/init-key key opts))))
  9. Componentと比較して⚔

  10. 良いところ •データでシステムを記述できる •どんなモノでもコンポーネントにできる •心理的な負担が減る

  11. 悪いところ •明示的にコンポーネントの名前空間を読み込む必要性

  12. 変わらなかったこと •あるコンポーネントに依存したいならば
 それ自身をコンポーネントとして定義する必要がある

  13. Integrantはこう使う
 (と良いかも)

  14. 独自のns loaderを作る •デフォルトでついてくるのは使い勝手が悪い •完全修飾されたキーワードは設定ファイルに書き難い •開発時にシステムからコンポーネントを取り出すのも苦 •例えばbultitudeを利用して任意のprefix付きnsを
 ロードするようなbootstrap機能を実装する

  15. 同じコンポーネントを複数作る •マルチメソッドを大量に用意する? •No •任意の親を持つ子のキーワードを複数deriveしておく •注意点 •複数の子で設定を書く場合は親のキーワードを
 設定ファイルに書けない •refに対して子のキーワードを明示

  16. 同じコンポーネントを複数作る (derive :demo/master-db :demo/db) (derive :demo/read-db-1 :demo/db) (derive :demo/read-db-2 :demo/db)

    (defmethod ig/init-key :demo/db [_ opts] ...) (ig/init {:demo/read-db-1 {...} :demo/read-db-2 {...} :demo/master-db {...} :demo/get-user-handler 
 {:db (ig/ref :demo/read-db-1)} :demo/get-company-handler {:db (ig/ref :demo/read-db-2)} :demo/update-user-handler {:db (ig/ref :demo/master-db)}}
  17. テストでコンポーネントを差し替える •deriveでok

  18. baumと組み合わせる •baumは設定ファイルを素敵にする拡張可能な
 DSLライブラリ •環境変数などを取得できる •baumのカスタムリーダーとして
 integrant.core/refをラップする

  19. baumと組み合わせる {$override* "dev-resources/config-local.edn" :demo/server {:port 3000 :handler #igref :demo/endpoint} :demo/database

    {:dbtype "postgresql" :dbname "my_blog" :user #env :db-user :password #env :db-password} :demo/endpoint {:db #igref :demo/database}}
  20. まとめ •Componentにあった心理的な負担が減った •これが1番いいかと言われると疑問 •Arachne的なアプローチにも期待したい