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

About Integrant

ayato
March 13, 2017

About Integrant

ayato

March 13, 2017
Tweet

More Decks by ayato

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

  3. Integrant概要

    View Slide

  4. Integrantとは
    •Jamesオジサンが作った新しいデータ駆動

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

    View Slide

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

    View Slide

  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))))

    View Slide

  7. 一時停止と再開のサポート
    •再起動が遅くなるのを回避できる
    •suspend-key!とresume-keyがポイント
    •初期化処理にも多少影響がある

    View Slide

  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))))

    View Slide

  9. Componentと比較して⚔

    View Slide

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

    View Slide

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

    View Slide

  12. 変わらなかったこと
    •あるコンポーネントに依存したいならば

    それ自身をコンポーネントとして定義する必要がある

    View Slide

  13. Integrantはこう使う

    (と良いかも)

    View Slide

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

    ロードするようなbootstrap機能を実装する

    View Slide

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

    設定ファイルに書けない
    •refに対して子のキーワードを明示

    View Slide

  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)}}

    View Slide

  17. テストでコンポーネントを差し替える
    •deriveでok

    View Slide

  18. baumと組み合わせる
    •baumは設定ファイルを素敵にする拡張可能な

    DSLライブラリ
    •環境変数などを取得できる
    •baumのカスタムリーダーとして

    integrant.core/refをラップする

    View Slide

  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}}

    View Slide

  20. まとめ
    •Componentにあった心理的な負担が減った
    •これが1番いいかと言われると疑問
    •Arachne的なアプローチにも期待したい

    View Slide