Perl で DI することについて夢想していた. というのも,DI 使ってないな〜ということで,それが良いとか悪いとかではなくたんに漠然とそう思っていた.
しかしながら,Perl で DI のコンテナは当然あるだろうけど, その仕組みについて思いを馳せてみると結構いろいろなことを知る必要があるなと思った. 以下,妄想
他言語
まず,他言語で DI をどうやっていたか,というのを自分の経験の範囲で思い出すと,
Android (Java, Kotlin) のときは Dagger
を使っていた.Dagger は依存関係をモジュールで定義して,実際に使いたいところでアノテーションを @Inject
のように指定しておけば,謎の技術でプリプロセスされたコードが出来上がって DI されるという仕組み.ポピュラーだが難解なことで有名:
他にも Koin
とか Kotlin の流儀にのっとったものがあり,そちらは Property Delegate とか Kotlin の言語機能を使って注入したりしているようだった (使ったことはない):
PHP のときは Ray.DI
というのを使っていた.これも Guice というライブラリにインスパイアされているので,ほぼ Dagger と同じ概念で,アノテーションとプリプロセスで頑張る仕組みになっていて,PHP にしては面白いものになっている:
そして かの有名フレームワーク Laravel
にも DI の機能がある.これはアノテーションこそ使っていないが,依存関係をセットアップで明示しておいたら,特定の条件下で注入してくれるものだ:
基本的に
基本的にアノテーションを使っているのは,本来の処理とは関係のない依存性の注入を透過的にしたいという目的がありそうで,コンテナから取ってくるとか,そういうものを前提にしないようになっている.
プリプロセスしているのは実行時のコストを押さえたいとか,静的に解決できるようになっていればビルドの段階で足りない依存の結合が見つかったりとか,そういうものも期待されていそうである.
手段として
Perl ならどういうことができるだろう,と考える.
アノテーション
アノテーションは使えるのだろうか.Perl でアノテーションはあるだろうか.PHP はアノテーションはないが Doc コメントを取得してきて実現している.
見ていると Perl にも静的解析のライブラリがありそうな気がしてきた.中身がそういうものなのかどうかは確かめていない:
https://metacpan.org/pod/PPI::Document
仮にアノテーション的にコメントに # @Inject
とかやりたいなのなら,こういうライブラリでパースして事前にビルドするとか,そういうものになるだろうかと思った.
が,Perl 好きにはオーバーエンジニアリング的であまり好まれなさそうだな〜と思った.ビルドのオーバーヘッドも嫌われそう.
Attributes
Perl には Attributes というものがあるそうなので,これを使えないかと思った:
そもそも自分は Attributes がよくわかっていない.が,Kotlin の Property Delegate 的なことに対応するのなら面白そうだとおもった.
Smart::Args
的な手段
Smart::Args
的に引数の属性を表明する手段はどうかと思った:
sub fn { args my $var1 => 'Int', my $var2 => { isa => 'Int', optional => 1 }; }
つまり,この Smart::Args
の記述を:
sub fn { args my $var1 => { isa => 'Int', injected => 1, named => 'config.var1' }, my $var2 => { isa => 'Int', optional => 1, injected => 1 }; }
みたいに表明しておけば,DI されたいというもの. なんとなく素直な気がする.
結局
多分調べてないので調べたら Perl の DI のノウハウが結構出てきそうな気がする. 要・不要かはおいといて,こういうのを調べてみるのも面白そうだと思った次第.