ヽ(´・肉・`)ノログ

How do we fighting without fighting?

Botフレームワークによるプラグイン読み込みと初期化を調べた

Ruboty(Ruby), Hubot(JavaScript), Hobot(Elixir) の Bot フレームワークでどのようにプラグインの読み込みと初期化を実装しているかをここに記す. 2017 Elixir アドベントカレンダー用の記事を書いているときに用意したのだが,詳細に立ち入りすぎているので記事からは消した. 誰かの役に立つかもしれないので,この日記にメモしておく.

Bot フレームワークに限らず,プラグインを利用したフレームワークを作ると避けられない課題に「フレームワークによるプラグイン読み込みと初期化」がある. 各種Bot フレームワークではどのようにプラグインを読み込み,初期化しているだろうか.

Ruboty

Ruboty ではベースになるようなクラス (Ruboty::Adapters::Base) を準備し, Class#inherited を利用して, プラグインのクラスを読み込む 時にベースとなるクラスを継承したプラグインクラスを Adapter 一覧へ加えている

その後 Bot を動かす Robot#run 時に Adapter 一覧の中で最後に追加されたクラスを new で初期化して Adapter として利用している (Rubot#adapter -> Rubot::AdapterBuilder#adapter_class).

フレームワークがプラグイン製作者やBot起動者に課していること

Hubot

Hubot では Robot オブジェクトの初期化 (Robot#constructor) の時に利用したい Adapter の名前を require へ渡す.

すると require がクラスパスの中から該当の Adapter が記述されたファイルを探し出し,読み込み,評価している (Robot#loadAdapter).

Hubot ではプラグイン実装者にクラスが use 関数を持つことを課しており require("xxx").use という形で初期化を行っている.

フレームワークがプラグイン製作者やBot起動者に課していること.

Hobot

Hobot では, 個別の Bot プロセスツリーを作る 時に,利用したい Adapter の名前を渡す(Hobot.create/4).

するとコンパイル済モジュールの中から該当するモジュールを探し出す.

フレームワークでは Adapter プラグインとして利用可能なモジュールは gen_server のビヘイビア(規定の関数呼び出しを実装している = 規定のインターフェースを持つ) を持つモジュールであることをプラグイン実装者に課している.

そこでフレームワークは見つけたモジュールを gen_server プロセスとして起動,初期化している(Hobot.Bot.Supervisor.init/1).

フレームワークがプラグイン製作者やBot起動者に課していること.

まとめ

フレームワークは何かの前提を元にプラグインを読みだしているので, フレームワーク製作者は,プラグイン製作者やBot起動者に対してその条件を明示してあげるとよい.

このエントリーをはてなブックマークに追加