search
LoginSignup
4

More than 5 years have passed since last update.

posted at

updated at

Organization

DartでCake PatternによるDI

既にDartにはAngularプロジェクト発のDIライブラリがあるのだけれど、
Webブラウザ上での動作時や公開ライブラリ等において、外部ライブラリに依存したくない場合や、そこまで重厚なDIが必要でない場合がままある。
そこで、Dart標準の言語機能で、DIっぽいことをあれこれ試した結果、implicit interfaceとmix-inを使ってCake Patternっぽいものができた。

すごく単純な例で解説。

class Entity {
  String name;
  Entity(this.name);
  String toString() => "Entity:${this.name}";
}

class Repository {
  List<Entity> getAll() =>
      ["entity1", "entity2"].map((s) => new Entity(s)).toList();
}

class Service {
  Repository get repository => new Repository();
  void execute() => print(repository.getAll());
}

EntityインスタンスをRepositoryインスタンスからgetAllメソッドで引っ張ってきてprintするServiceクラスのexecuteメソッドがある。

Serviceクラスのrepositoryプロパティは、プロダクション環境下では以下のクラスを参照したい。

class AwesomeRepository implements Repository {
  List<Entity> getAll() =>
      ["awesomeEntity1", "awesomeEntity2"].map((s) => new Entity(s)).toList();
}

(まぁ実際は外部DBとかにでもアクセスすると思ってください)

もちろん、repositoryプロパティを可変にすれば自在にRepositoryの実装を変更できるのだろうが、そうするとServiceのインタフェースが汚れる。
Dartのimplicit interfaceは便利なのだけれど、意図せぬインタフェースを外部に提供してしまう場合もあるので、クラスやそのメンバーの可視性やオブジェクトの不変性には特に気をつけておきたい。
この例も同様、Serviceの状態は不変を保ちたいとする。

このような場合は、Mix-inを使用する。
以下のようなAwesomeRepositoryへの依存をサポートするためのMix-inを定義して、

abstract class AwesomeRepositoryMixin {
  Repository get repository => new AwesomeRepository();
}

AwesomeRepositoryMixinとのmix-in applicationによって、AwesomeRepositoryへの依存を持つServiceを定義する。

class AwesomeService = Service with AwesomeRepositoryMixin;

(昔はtypedefキーワードだった。しみじみ)

これで、ServiceとAwesomeServiceそれぞれ同じexecuteメソッドを有するが、repositoryプロパティの参照先が変更されため、標準出力の内容がそれぞれで異なる結果が得られる。

main () {
  new Service().execute();
  new AwesomeService().execute();
}

ただ、この方法には、動的にrepositoryプロパティの参照先を変更できないという問題がある。
動的にしたい場合は、constructor injenctionなりproperty injectionなりを採用すればよいと思う。
それよりも、依存関係が複雑化した際のdart analyzerによる静的チェックの恩恵の方が個人的には大きく、この似非Cake patternの採用の動機になっている。

まとめ

  • DIばりばりやりたい場合は、diパッケージ
  • 動的にやりたい場合は、素直にconstructor injenctionかproperty injection
  • 静的に依存関係を構築したい場合は、当記事のCake Pattern

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4