ComponentとIntegrantの違い
ComponentとIntegrantはどちらもライフサイクルを管理するフレームワークだが、それぞれ微妙に異なるので、その違いを簡単に書いておく。Mount?知らない子ですね。
Component
システムを構築するための設定をコード上に書く必要がある
これはIntegrantから指摘されている欠点のひとつ
Component単体で解決することはできないが、ednファイルからシステムを構築するDSLを用意すれば解決する
実際、cstapではこのやり方を取っている
詳しくは説明しないけど、いつか公開するかもしれない
すべてのコンポーネントはLifeCycleプロトコルを実装する
明示的に実装しない場合、Objectに対する実装が利用される
何かしらコンポーネントに依存する場合は以下の条件を満たすこと
それ自身もLifeCycleプロトコルを実装している
associativeであること
他のコンポーネントから依存されるだけの場合、これを満たす必要はない
任意のコンポーネントを差し替えたい場合は、単にsystem-mapの任意のキーに対応するコンポーネントを変更するだけでよい
Integrant
システムを構築するための設定はednファイルに記述することができる
これはComponentに対する優位な特徴としてあげられる
すべてのコンポーネントはinit-keyとhalt-key!マルチメソッドにメソッドを追加することで、初期化処理と破棄する処理を決定することができる
またComponentと違いデフォルトでsuspend!とresumeが提供されており、より高速にシステムをリセットすることができるとしている
何かしらコンポーネントに依存したい場合は、init-keyにメソッドを追加する必要がある
任意のコンポーネントを差し替えたい場合、ふたつの選択肢がある
init-keyに利用したキーをderiveして新しい実装を追加して、設定に利用するキーをderiveしたキーにするという方法 (https://github.com/weavejester/integrant/tree/2cb49fab47278017401493cdecfbd8c8b54c8055#derived-keywords)
deriveをせずに設定ファイル上でキーワードのベクターを使うことで、上のderiveと同じような効果を得る方法 (https://github.com/weavejester/integrant/tree/2cb49fab47278017401493cdecfbd8c8b54c8055#composite-keys)
結局のところ大きな違いは以下の点であって、それ以外は些末な実装上の違いである。
table:differencies
Component Integnrat
何からシステムを構築するか プログラム 設定ファイル
何かに依存するコンポーネントは レコードやマップ 何でもよいl
どちらを利用していたとしても、DIフレームワークの側面がありそのように利用することができるし、依存関係の解決に関してもStuart Sierraのdependency(本当にぐぐらびりてぃが低い)を内部的に使っているため対した違いはない。
羃等性を担保する上での面倒について
athosathos.iconさんから指摘を受けたので追記。
https://twitter.com/athos0220/status/931003506638458882
リローダブルにする上で羃等性という観点がある。
Componentの場合
コンポーネントが別で作られた上で、システムに管理されるため、「そのコンポーネントが起動済みかどうか」はコンポーネント自身しか知ることができない
Integrantの場合
init-keyはコンポーネントの作成と初期化を同時にやってしまうため、「そのコンポーネントが起動済みかどうか」を気にする必要はない
起動されていればシステムの中に存在し、halt-key!に値が渡ってくれば初期化されていると判断できる
なのでComponentは羃等性を担保しようとするとボイラープレートが増えてしまい面倒だ、という話になる。
#Clojure #Integrant #Component