この記事では実際の大規模なSNSアプリをVIPERで開発した経験のある著者が、Clean ArchitectureとVIPERをClean Architectureの円の図解の円の内側(Entity)から順番に、実践で使えるコードを使い解説する。
と思ったのだがClean Architectureの解説だけで結構な量の記事になってしまったので実際のコードでの解説は次回以降の【実践編】で解説する。
実践編の最初の記事はこちら。
【実践編: 内側の2つの円】iOSでVIPERとClean Architecture 円の内側から作る
VIPER? CleanArchitecture???
あなたはClean ArchitectureやVIPERと聞いて何を思い浮かべるだろうか?
- 実際の実装方法がわからない
- 難しそう
- 実装コストが他のアーキテクチャと比べて高そう
しかし、一度覚えてしまえば実装は難しくはなく、長期的なメンテナンス性を考えると初期の実装コストの高さ(実際はさほど高くもない)も吸収できる。
VIPERとClean Architectureの関係
まずVIPERとClean Architectureが関係のあるものだと等認識が無かった人が多いのではないだろうか。
Clean Architectureは特定のプラットフォームの開発にフォーカスしたアーキテクチャではない。対照的にVIPERはClean ArchitectureのiOSプロジェクト用の組み方である。
Clean Architecture
The Clean Architecture by Robert C. Martin (Uncle Bob)
VIPER - Clean Architectureの関連
より具体化されたVIPER
VIPERはClean ArchitectureをiOSで実装するためにより具体的な概念に落とし込み、それらの組み方を定めたものである。
Clean Architectureは各層で実際にどこような命名のクラス等を使いどのような組み方をするかの詳細は定義されていないが、VIPERでは5つの具体的なコンポーネントが定義されている。
- View
- Interactor
- Presenter
- Entity
- Router
ちなみにVIPERという名称はこれら5つのコンポーネントの頭文字から来ている。
VIPERに無いもの
Clean ArchitectureにあってVIPERに無いものがある。
それはデータの取得に関する概念だ。
これはClean Architectureの図解では真ん中のから3つ目の円のゲートウェイの部分に相当する部分である。
すなわちVIPERではEntityに関する定義はされているが、そのEntityをどのように取ってくるかの定義はされていない。ほとんどのiOSアプリでサーバーやDBからの情報取得は実装必須である。そのためVIPERでこの部分も綺麗に実装するにはClean Architectureの方法論に沿って行うことが大事である。
また、これがこの記事がVIPERだけの解説でなくClean Architectureも一緒に扱っている大きな理由でもある。
レイヤーの解説
VIPERのコンポーネントがClean Architectureでどの部分に相当するのかを含めて解説する。
Entity
最重要のジビネスルール がここに入る。円の中心。他の部分が変更されてもここが変更される可能性は低い。
では最重要なビジネスルールとは何だろうか?大きく分けると以下の2つになる。
- 電子化されたアプリケーションが存在しなくても存在するルール
- もっとも重要なビジネスルール
ビジネスルール例
例えば銀行の利子を計算するロジックは、銀行業務が電子化されていなくても存在する。そもそもコンピューターが登場する以前から銀行はこのロジックを業務で使っていた。これが電子化されたアプリケーションが存在しなくても存在するルールである。
Webサービスのビジネスルール
ではWebサービスなどアプリケーション無しにそのビジネスが存在しない場合は何がEntityに入るのだろうか?
この場合は最重要のビジネスロジックがここに入る。それはプロジェクト全体で変更される可能性が一番低く、もっとも中心にあるビジネスルールなどがあげられる。
例えばプラットフォームが移ったとしても同様に必要となるロジックなどが想定される。
iOSでは?
iOSプロジェクトにおいては、多くの場合Client - Serverモデルで実装されるので、Entityはロジックは持たずにデータだけが入っているケースがほとんどである。
ただし忘れてはいけないのは、iOSアプリだけで完結するようなプロジェクトの場合はEntityにもしっかりビジネスロジックが入るということだ。
Use Case
アプリケーション固有のロジック が入る。VIPERのInteractor はUseCaseに入る or 相当する。
この層で実際によくある実装はサーバーからデータを取ってきて、一つ上の層のpresenterへ取ってきた結果を渡す等である。
iOSでは?
iOSプロジェクトではEntityへロジックを書くことが少ない。そのためiOSプロジェクトの場合はここが実際にもっともコアのロジックを実装する場所になる。
Interface Adopter
Interface Adopterとはその名の通り、Use Caseとインターフェースの調整役 である。
VIPERではPresenter がこの部分に相当する。
ではインターフェースとは何だろうか?これは一つ外側の円に記載されているものであり、それらの詳細は一つ外側の円である"Frameworks & Drivers"で解説する。
非常に重要 なことだが、円の図に書かれている3つのコンポーネントはお互いには関連しておらず、基本お互いに参照もしない。
- 直接関係の無い3つのコンポーネント
- Presenter
- Gateway
- Controller
Presenter
Interface Adopter層に属するコンポーネント。
VIPERではUIからのイベントを受け取り、イベントに応じた命令をUse Case層のInteractorに送る。その後Interactorから帰ってきた結果を、UIが表示しやすい形へ変換してUIへ渡す。
例えばIntで帰ってきた金額の情報をStringに変換して"¥"をつけてUIでそのまま即座に表示できるようにしたものである。
iOSでは?
実際のiOSプロジェクトではInteractorから帰ってきた情報をView Modelへ変換してUIへ渡す等の実装をする。ここでいうView ModelはRx等を使って実装するMVVMのようなロジックの入ったView Modelではなく、単純な表示用にフォーマットされたデータ等のみが入ったものである。
Gateway
Interface Adopter層に属するコンポーネント。PresenterがUIという外部のインターフェースとやりとりをするのに対して、GatewayはDBやサーバーという外部のインターフェースとやりとりを行う。
iOSでは?
iOSのプロジェクトではGatewayはUse Case層のInteractorからEntityを取得する指示を受け、DBやサーバーからEntityを取得しそれらをInteractorへ渡す。
Frameworks & Drivers
GatewayやPresenterがやりとりする外部の概念。DBやUIなどがわかりやすい例。
この円には多数の概念が書かれているが、例によってClean Architectureの円の図解は円の内側とその側の依存関係のみを表していて、同じ円の中にある概念同士は基本的にお互いを知らず、参照もしない点に注意。
iOSでは?
iOSにおいてはUI(UIKit)やアプリ外部のサーバー等(Web)がこの部分に該当。
DDD Layered Architectureとの最大の違い
Clean Architectureはざっくり見るとLayered Architectureと似たような構造を持っている。しかし1点非常に重要かつ大きな違いがあり、Clean Architectureの本質を理解する上でそれが重要なので、それに関しても解説を行う。
Clean ArchitectureとDDD紹介のLayered Architectureの重要な違いはインフラストラクチャ層(Clean ArchitectureでのGateway)だ。Layered Architectureでは他の全ての部分(Entity, App Logic, UI等)がインフラストラクチャ層に最終的に依存するような構造になっている。
しかしClean Architectureではインフラストラクチャに相当する部分のGatewayはEntityはもとよりアプリケーションロジックであるUse Caseよりさらに外側にある。
インフラストラクチャに表現されたデータは、EntityはUse Caseを表現するために作られた実態であり、表現するための本質へ、実態としての情報は依存すべきというのがClean Architectureの考え方である。
ちなみに余談だが、DDDで紹介されているLayered ArchitectureがDDDと一体のものと認識している人が多いが、実はDDDを実践するのに本質的に重要なのはドメインと隔離することでありそれが実現できればどのようなアーキテクチャを使っても良いと”ドメイン駆動設計”の書籍に記載されている。Clean ArchitectureやはたまたMVCでもDDDを実践することは可能ということだ。
最後に
今回はClean ArchitectureとVIPERの解説のみの記事となった。次回の記事
【実践編: 内側の2つの円】iOSでVIPERとClean Architecture 円の内側から作るで実際にコードで実装を進めるので是非こちらも見てもらいたい。