「Clean Architectureはファイル数が多くてめんどくさい」という話がよく上がるなと思ったので、簡易化するとしたらどこを省略するべきかなというのを考えてサンプルを作ってみました。
Github - a-beco/SimpleCleanArchitecture
結論としては、Interface Adapterを省略する形で書いています。小~中規模ぐらいのアプリつくるならこれぐらいで書いてもワークするんじゃないかなと思っています。
この記事では、今一度Clean Architectureとは、という話と、勘違いされがちなポイントをまとめつつ、今回のサンプルの構成について簡単に説明します。
Clean Architectureとは
以前、Clean Architectureについての記事を書きました。Clean Architectureとはなんぞやという話についてはそちらのほうが詳しいので合わせて参照してください。ここでは簡単な説明にとどめます。
iOS Clean Architecture - 騒音のない世界 BLOG
Clean ArchitectureはMVCやMVVMなどに代表されるソフトウェアアーキテクチャのひとつです。特徴としては、ビジネスロジックを中心として円形の構造をとり、円の内側に向かって依存するように作る、ということがあります。メリットとしては、
- 疎結合化を促し、テスタビリティを高める
- モデルが整理される
- DBなど外部の存在を置換しやすくする
などがあります。
勘違いされがちなこと
Clean Architecture自体は名前がキャッチーなことで広まっている節もある気がしていて、かつ元の記事が結構短くてサラッと書いてあるのでわりとバラバラな理解が広まっている気がしています。なので僕自身もまだ理解しきれていない所があるのですが、僕なりの見解を書いてみたいと思います。
・iOS Clean Architecture というアーキテクチャがある?
プラットフォームや言語を限定するものではありません。Androidに適用した例もありますし、クライアントかサーバかも関係ないと思います。ただ、どちらかと言うとそれなりに規模の大きい業務用のWebシステムとかのほうが適用しやすいかもしれないです。
・ファットビューコントローラを防ぐもの?
これは結果としては正しいと思います。正しくモデルが分離され、かつPresenterにプレゼンテーションロジックを外出しすればViewControllerはすっきりします。
ただし、処理を外出ししたことでViewControllerがすっきりする、というだけであれば他のアーキテクチャでもいい感じにできるんじゃないかなと思います。「Clean Architectureならでは」な部分って円形の構造とか、内側に依存するという依存ルールだったりすると思うので、Clean Architectureとはファットビューコントローラを防ぐもの、というよりは、結果としてファットビューコントローラを緩和する効果がある、という感じかなーと思っています。
・VIPERとはぜんぜん違うもの?
iOS向けのアーキテクチャとしては最近VIPERも有名ですね。元記事を見ると、「Clean ArchitectureをiOSに応用したもの」と明確に書いてあります。
直接使ったわけではなく元記事も読み込めてないので確かではないのですが、UseCaseとInteracterが同じような役割をしていると考えれば、確かに大体同じような形になりそうです。
私感ですが、Clean Architectureや、Clean Architectureが元にしているOnion ArchitectureがDBなど外部の存在への依存を極力減らすことに注目して「円形にすること」を強調しているのに対し、VIPERは円形の図を使わずにビューを起点にし、ファットビューコントローラの低減を中心に据えているのが特徴的だなと思います。iOSに特化していると言えますね。
シンプルに書いてみる
Github - a-beco/SimpleCleanArchitecture
今回のサンプルですが、前回の記事で作ったサンプルを円形の構成と、中心に向かって依存するというルールを保ちつつInterface Adapterの層を省略したものとなっています。具体的にはPresenterとGatewayを削除しました。つまり依存関係としては以下のようになります。
UIViewController -> UseCase <- Repository
**Presenterを削除するとファットビューコントローラが。。**と心配な場合はそこだけ足せば良いと思います。前述したとおり、Clean Architecture自体はファットビューコントローラを防ぐのが一番の目的というわけでもないだろうということで思い切って省いてみました。あらゆるView Controllerがファットになるわけではないと思うので、必要そうな画面だけ足すとかもありだと思います。
省いた部分の処理がどこに行くかというと、大抵はデータを保持している構造体などに移せると思います。例えばPresenterはUseCaseで使うデータ(Entity)をViewでの表示に適したデータ(ViewData)に変換するのが主な作業となるので、今回はViewDataのイニシャライザにEntityを渡して初期化できるようにしています。あとはデータクラスのメンバ関数にしたり、ヘルパ関数として処理を切り出したりすれば大体なんとかなるんじゃないでしょうか。
前回の記事のサンプルから書き換えてみて面白かったのは、UseCaseは外側のものに依存していないので、全く編集しなくてよかったというところです。つまりそのまま再利用できているということです。このへんは疎結合なことの強みですね。良き。
ちなみにClean Architecture的にInterface Adapterの省略が許される行為なのかどうかはよくわかりません。ただ元記事では層の数は定めていないと明言しているのでケースバイケースで少なくしてもいいと考えています。
おわりに
どういうアーキテクチャを採用するかというのは難しい問題です。プロジェクトの序盤で決定しなければならない上、あとから取り返しがつかないですし、チームに浸透させる負荷なども考えるとできるだけシンプルかつ柔軟なものにしたいですよね。
iOS界隈で最近話題のClean Architectureですが、ファイル数が多くてめんどくさいという話をよく聞くのでファイル数を減らしてシンプルにするアプローチもあるんじゃないかということで書いてみました。ケースバイケースでファイルを増やしたり減らしたりして最適な構成を模索してみてはいかがでしょうか。