Locked History Actions

Diff for "scala/DI"

Differences between revisions 3 and 4
Deletions are marked like this. Additions are marked like this.
Line 16: Line 16:
== ScalaでのDI == == DIはどうあるべきか ==

[[http://eed3si9n.com/ja/real-world-scala-dependency-injection-di|実戦での Scala: Cake パターンを用いた Dependency Injection (DI) ]]という文書があるが、(私の定義では)これは全くDIになっていない(もちろんGuice以外の方法)。特に、Cake Patternはインターフェースと実装の分離ができているとはとても言えない。

上記を踏まえて、DIがどうあるべきかを考えてみると、私の意見としては以下である。

 * テストされるコードとは無関係の場所でインターフェースと実装を結びつけることができること。
 * 本番環境ではデフォルトの実装が、特別な捜査無しに暗黙的に選択されていること(GuiceのImplementedByのようなもの)。
 * インジェクションされるかサービスロケータとして実現されるかはどちらでも構わない。
 * しかしむしろ、サービスロケータの方が理解しやすく、制限も緩いので望ましい。
 * DIするときの記述はできるだけ簡単であること。「new コンストラクタ(引数)」と同様の短い記述で済ませられるのが望ましい。
 * 特に注入されることを意図していないクラスの取得(生成)でも同じ記述ができること。
 * DIはユニットテストのためなのだから、モックが簡単にできること。

ScalaでDI

参考

なぜDIが必要か

DIする理由にも記述したが、これはユニットテストのためであると断言してよい。 DIすれば他にも様々な恩恵が得られるが、それらはむしろ副次的なものである。

いわく、「DIすればアスペクト指向によって、処理をはさみこむことができる」という。デバッグトレースには有効かと思うが、トランザクション管理に使うのは全く賛成できない。トランザクションを意図したコードであれば、それは明示的に記述されるべきであり、そのような意図の無いコードに後付するのは危険性が伴う。

「(本番の)実行時に処理を変更できるからだ」という人もいる。これも同じで、そもそもそのような意図のコードであるなら、明示的にそれが記述されるべきである。そのような理由でインターフェースと実装を切り離す必要があるのなら、そもそもインターフェースを明示的に引数として渡すようなコードになっていなければならない。

DIはどうあるべきか

実戦での Scala: Cake パターンを用いた Dependency Injection (DI)という文書があるが、(私の定義では)これは全くDIになっていない(もちろんGuice以外の方法)。特に、Cake Patternはインターフェースと実装の分離ができているとはとても言えない。

上記を踏まえて、DIがどうあるべきかを考えてみると、私の意見としては以下である。

  • テストされるコードとは無関係の場所でインターフェースと実装を結びつけることができること。
  • 本番環境ではデフォルトの実装が、特別な捜査無しに暗黙的に選択されていること(GuiceのImplementedByのようなもの)。

  • インジェクションされるかサービスロケータとして実現されるかはどちらでも構わない。
  • しかしむしろ、サービスロケータの方が理解しやすく、制限も緩いので望ましい。
  • DIするときの記述はできるだけ簡単であること。「new コンストラクタ(引数)」と同様の短い記述で済ませられるのが望ましい。
  • 特に注入されることを意図していないクラスの取得(生成)でも同じ記述ができること。
  • DIはユニットテストのためなのだから、モックが簡単にできること。