なぜSwiftでDIが流行っているのか

結論としてはテストを簡単にするためです。 DIでなくても簡単にする方法はあります。 この記事では、DIすることによってテストが簡単になる理由を説明します。

偽物によるテストの容易性の向上

 あるアプリを手動で正しく動いていることをチェックするとしよう。多くのアプリは外部の状態に依存しています。サーバーや時間、ユーザーの操作などです。アプリがちゃんと動いていることをチェックするために、それぞれがちゃんと動いていることを確かめたり、状態を確認しながらチェックをする必要があります。チェックを行うために、外側の環境の不安定で一向にアプリのチェックが進まない事は良くある話です。

 実際の開発を行うときは、手動でのチェックは極力避けていると思います。テストコードを書いてCIで自動テストを実行しています。1日のうちで何度も自動テストを行うのに外側の不安定な環境に依存していてはテストが失敗し、自動テストの効果が十分に発揮できません。

 本物の代わりに偽物を使って、テストを行えば安定したテストを行うことができます。例えば、必ず決まった値を返すサーバーのようなものや、同じ時間を返す時計、ユーザーのような操作をするロボットを使うことです。

テストダブルによるオブジェクトの置き換え

 話を小さくして、オブジェクト単位の話です。

 オブジェクトもアプリと同じように別のオブジェクトに依存しています。別のオブジェクトもさらに別のオブジェクトに依存しています。自動テストを行うときに、本物のオブジェクトを使ってテストをすると数十のオブジェクトを状態をセットアップしなければいけない時があります。テストのための準備するコードが実際にテストを行なっているコードより圧倒的に長くなるのは本末転倒です。テストしたい対象に焦点を当てたコードの方が良いテストです。

 偽物のオブジェクトを使うことによって、本物より早くセットアップできれば、テストしたい対象に焦点を当てたテストコードを書くことができます。この偽物のオブジェクトをテストダブルと言います。

Swiftによる型チェック

 偽物のオブジェクトに置き換えればテストが簡単になるという話をしてきましたが、Swiftでは少し面倒な問題があります。

 Swiftは強い型付き言語であり、最適化をしなければ実行時の型チェックも行われる言語です。変数の型が構造体の場合はその構造体のオブジェクトの必要になり、クラスに依存している場合はそのクラスかそのクラスを継承しているクラスのオブジェクトの必要がありです。無理矢理に型を誤魔化しても変数に代入しても実行時エラーになります。つまり、普通にコードを書くとテストダブルは使えず、常に本物のオブジェクトを使うしかありません。これは、テストを行うときに巨大なセットアップが必要なオブジェクトが存在し、テストを困難にさせます。

プロトコルによるテストの容易性の向上と実体の喪失

 変数の型をプロトコルにすることで、プロトコルを実装しているオブジェクトなら何でも代入することができます。テストダブルが使えるため、意図した動作をテストが用意になります。その代わりに、変数の依存をプロトコルにすることによって、本物の型がわからなくなってしまいます。テストしやすくするためには仕方ないことだったとは言え、このままではアプリを為すことができません。

オブジェクトの注入(DI)

 アプリとしての形を為すためにプロトコルでの依存している本物のオブジェクトを解決する必要があります。本物のオブジェクトを解決するためのパターンがDIなのです。DIによって、アプリとしての形を保ちつつ、テストしやすいコードを書くことができるのです。

 DIの実装方法はいくつかあり、DICやCakeパターンなどがあります。実装方法については自分で調べてください。