Perl で DI することを考えていた

Perl で DI することについて夢想していた. というのも,DI 使ってないな〜ということで,それが良いとか悪いとかではなくたんに漠然とそう思っていた.

しかしながら,Perl で DI のコンテナは当然あるだろうけど, その仕組みについて思いを馳せてみると結構いろいろなことを知る必要があるなと思った. 以下,妄想

他言語

まず,他言語で DI をどうやっていたか,というのを自分の経験の範囲で思い出すと,

Android (Java, Kotlin) のときは Dagger を使っていた.Dagger は依存関係をモジュールで定義して,実際に使いたいところでアノテーション@Inject のように指定しておけば,謎の技術でプリプロセスされたコードが出来上がって DI されるという仕組み.ポピュラーだが難解なことで有名:

dagger.dev

他にも Koin とか Kotlin の流儀にのっとったものがあり,そちらは Property Delegate とか Kotlin の言語機能を使って注入したりしているようだった (使ったことはない):

qiita.com


PHP のときは Ray.DI というのを使っていた.これも Guice というライブラリにインスパイアされているので,ほぼ Dagger と同じ概念で,アノテーションプリプロセスで頑張る仕組みになっていて,PHP にしては面白いものになっている:

tech.quartetcom.co.jp

そして かの有名フレームワーク Laravel にも DI の機能がある.これはアノテーションこそ使っていないが,依存関係をセットアップで明示しておいたら,特定の条件下で注入してくれるものだ:

qiita.com

基本的に

基本的にアノテーションを使っているのは,本来の処理とは関係のない依存性の注入を透過的にしたいという目的がありそうで,コンテナから取ってくるとか,そういうものを前提にしないようになっている.

プリプロセスしているのは実行時のコストを押さえたいとか,静的に解決できるようになっていればビルドの段階で足りない依存の結合が見つかったりとか,そういうものも期待されていそうである.

手段として

Perl ならどういうことができるだろう,と考える.

アノテーション

アノテーションは使えるのだろうか.Perlアノテーションはあるだろうか.PHPアノテーションはないが Doc コメントを取得してきて実現している.

見ていると Perl にも静的解析のライブラリがありそうな気がしてきた.中身がそういうものなのかどうかは確かめていない:

https://metacpan.org/pod/PPI::Document

www.himajin2001.com

仮にアノテーション的にコメントに # @Inject とかやりたいなのなら,こういうライブラリでパースして事前にビルドするとか,そういうものになるだろうかと思った. が,Perl 好きにはオーバーエンジニアリング的であまり好まれなさそうだな〜と思った.ビルドのオーバーヘッドも嫌われそう.

Attributes

Perl には Attributes というものがあるそうなので,これを使えないかと思った:

perldoc.jp

そもそも自分は Attributes がよくわかっていない.が,Kotlin の Property Delegate 的なことに対応するのなら面白そうだとおもった.

Smart::Args 的な手段

Smart::Args 的に引数の属性を表明する手段はどうかと思った:

metacpan.org

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 のノウハウが結構出てきそうな気がする. 要・不要かはおいといて,こういうのを調べてみるのも面白そうだと思った次第.