以前 iOS Clean Architecture という記事を書きました。Clean Architectureとは何か?とかClean Architectureの実装例などが見たい方はまずそちらをご覧ください。今回は開発の中で感じたモヤモヤを書きます。はっきりした主張がなくて論旨がわかりにくいのですが、ご承知の上で読み進めていただければ幸いです。
Clean Architecture が前提にしている「安定性」
前回も述べたように、Clean Architectureの重要なコンセプトとして「依存ルール」があります。依存関係は円の内側に向かうようにする必要があります。なぜならば、アプリケーションフレームワークやDBやWebサーバなどの外部の変更に対してアプリケーションのビジネスロジックが影響を受けないようにしたいからです。言い換えれば、「コードが変更された時の影響範囲を出来る限り狭めたい」という意図があります。これはいわゆる安定依存の法則であり、特にClean Architectureが起源のアイディアではありません。安定依存の法則に従うことによりソフトウェアの動作を安定させる効果もありますし、副次的に差分ビルドにかかる時間を短くし、素早いイテレーションを実現するといった効果もあるかと思います。
この依存ルールの裏には、「ビジネスロジックは比較的安定である」という前提があります。つまり、画面の見た目が変わったり、DBなどの保存先が変わることはあっても、ビジネスのルールが変わることは比較的少ないよね、という前提です。たぶん経験則によるものです。
ビジネスロジックは常に安定か?
「ビジネスロジックが安定」という前提は、「ソフトウェアが既存の業務を置き換える」という状況においては(業種にもよりますが)そこそこ正しいのではないかという感じがします。スケジューラやTODOのような汎用的なツールについてもそうなんじゃないでしょうか。
しかし、近年のWebアプリやスマホアプリなどのサービス開発においてその前提はどこまで成り立つのでしょうか?SNS系のサービスは現実の作業を置き換えるものではなく、新たな体験と提供しているといえます。このような類のサービスにおけるビジネスロジックと、業務アプリケーションなど現実の作業を効率化する類のソフトウェアのビジネスロジックはどちらも同じく安定と言えるんでしょうか。
根拠に乏しい私感になりますが、このへんを全く同列に扱うのは少し乱暴だなあと何となく感じています。業務アプリケーションでないソフトウェアに対してビジネスロジックという言葉を使うのにも少し違和感を感じます。
もちろん共通的な部分もたくさんあるし、アプリケーションレイヤは全部不安定だろってわけではなくて「このへんは安定してるな」と思ったりもするんですが、Domainというよりは各層のコアな機能とか、Utility的なところだったりすることが多いなーと思うんですよね。例えば、HttpClientってデータ取得だからDomainというよりData的な外部の層におけるコア機能って感じで考えられるのかなって思うんですが、そんな頻繁に変えませんよね。まあそういう部分は基本的に「使われるもの」なので、安定依存の法則に違反するものではないんですが、Domainじゃないけど安定してるやんっていうか。
よくある変更に対する変更箇所が多すぎる問題
新規でイチから開発してるからかもしれませんが、決して特殊ではない変更に対して変更箇所が非常に多くなってしまうことがあり、安定依存って言ったじゃんヤダヤダとなることが理想と現実のギャップとしてあります。
例えば「ビューに追加で情報を表示したいからサーバから受け取るデータを変更する」という状況はクライアントの開発でよくある場面かと思いますが、この場合にCleanArchitectureを採用しているとどうなるかというと、Dataの変更をPresentationに伝えるため必然的にDomain(UseCase)も変更することになります。それぞれの層で使っているデータ構造をすべて書き換え、変換処理も書き換える必要があります。作業時間がボトルネックになるというほどではないですが、変更が機械的で退屈なことが多いです。
このあたりに関しては感覚的にはワーストケースに合わせているという感じがしています。なのでどうしてもシンプルな部分における変換層の単純作業感や記述の重複感があり、どうなのかなあと思うところです。
結局どこに依存すれば良いのか?
安定依存というコンセプト自体は間違っていないと思うのですが、結局安定な場所ってどこなんでしょうか?
Clean Architectureというより安定依存の話なのですが、これって要は「たくさん変更される場所」や「ほとんど変更されない場所」をあらかじめ予測せよってことなのかなって思ってます。で、アーキテクチャでそれをルール化してチーム内で強制するようなアプローチってなると、やっぱりClean Architectureみたいな、統一的にこのへんに依存せよ的な構成になっちゃうのかなあと思いつつ、現実的には安定的な部分ってアプリごとにもっとバラけてるんじゃないかな、と思ったりもしています。
だから、そこそこうまくいくけど最適なアプローチってわけでもないのかなって思うんですよね。
おわりに
お前は何が言いたいのかって感じですが、Clean Architectureの利点としてよく言われる「ファットコントローラを防げる」とか「テストが容易になる」とかって単にモデルをきちんと分離して疎結合な構成でルール化すればLayered Architectureで良くて、Clean Architectureならではな部分って「円の中心に向かって依存する」っていう依存ルールとか、Interface Adapterの存在とかかなて思うんです。で、安定してるところに依存するのが良いというのはわかるんですが、その円の中心って本当にそんないつも安定してるか?もっといい切り口があるのでは?みたいな話でした。
まあ多様な集合に対して統一的なルールを決めるのって大抵例外的なものがあるから100%うまくいくってことはなくて、大枠の方向性として70%ぐらいでそこそこうまくいけばいいかみたいな感じになりがちですよね。もしくは、結局ビジネスロジックが安定してるっていうのもあくまでも「比較的」っていうだけで期待するほどは安定していないものなのかもしれないですね。そういうのって何かしらの実験で数値化されてたりするんですかね?
あと、Onion ArchitectureとかはClean Architectureの元になってるっぽくて、情報が少し多いのでこの辺も合わせて読むとより理解が深まるかもしれないなあとちょっと思ってます。パッと見で違いがわからないぐらい似ているのですが。そのうち読みたいです。
→ 2016.12.31 追記: Onion Architectureについて書きました
ダラダラ書いてすいません。最後まで読んでいただいてありがとうございます。僕が感じてるモヤモヤを汲み取って「この本読むといいよ」とか教えてもらえたらとてもうれしいです。