クリーンアーキテクチャは銀の弾丸か?
https://3.bp.blogspot.com/-1TdKzs2PvX8/WQvvDPSOQgI/AAAAAAABEEI/bglWMgfxqnkM1Gvx2O7NbKvrj03u1F1PACLcB/s400/gin_dangan_silver_bullet.png
まず 「個人的にはクリーンアーキテクチャは銀の弾丸ではない」という認識であることを明言しておきます。
余談ですが、時代によってトレンドや最適解は移ろうのでこの世に銀の弾丸(未来永劫に渡って利用可能な完全な正解)は存在しないんじゃないんだろうかと個人的に思っています。
アプリケーションの開発手法はコレまで歴史において様々なアプローチによって提案がされてきましたが、クリーンアーキテクチャもそのうちの1つでしかありません。ほかにもヘキサゴナルアーキテクチャやDDDなどがありますね。 ここではそんなクリーンアーキテクチャの個人的な理解や使い所を「俗っぽく」ざっとまとめておくことにします。
クリーンアーキテクチャはどこで手に入れられる?
一言で「思考フレームワーク」の1つと理解しています。実体を持つアプリケーションのライブラリやフレームワークではなく、アプリケーションを設計、開発するシーンに置いて役立つ指標の1つです。コードではなく「脳」にインストールします。
また、クリーンアーキテクチャやヘキサゴナルアーキテクチャをベースに設計を取り入れたオールインワンフレームワークもありますが、厳密にはライブラリやフレームワークは抽象化と隔離の対象になるので、少し変則的な扱いをする必要があります。
クリーンアーキテクチャは何を解決している?
端的にはアプリケーションの実装に関心による境界を定義し、境界ごとにコンポーネント(クラスや構造体、関数)を分離することで、各処理における責務や処理を単一にすることで、取り回しがよく長期的に運用しやすいと考えられる構造にするための考え方を提供しています。
クリーンアーキテクチャは難しい?
クリーンアーキテクチャは使えるようになれば便利と言われることもある一方、学習コストが高いという指摘を受けることがあります。
例えば、Ruby on Rails や Laravel、Zend Framework などのオールインワンフレームワークと呼ばれるタイプのライブラリを利用する場合においては、MVC2 をベースとした考えのもと、予めディレクトリ構造が決まっています。データベース構造とほぼほぼ合致したりしなかったりする Model や、Webアプリケーションのレスポンスを定義づける View、URL構造と対応する Controller というような粒度で分割されており、機能を実装する上でそれぞれに対応する処理を分割して実装していけばある程度形になるようになっています。 これは、Ruby on Rails や Laravel、Zend Framework がアプリケーションのライブラリであることと同時に、思考フレームワークの一端を提供しているからと理解しています。また、基本的な使い方を示した公式ドキュメントが存在し使い手に理解を促すようになっています。
対してクリーンアーキテクチャは、特定のライブラリに依存しない、実体を持たない思考フレームワークです。そのため、使用している言語やライブラリ、アプリケーションの種別によらず適用することが可能です。よく見る下記のような同心円状の図に大体合う用に実装を分割してディレクトリを適切に切り必要な実装を、単一責務の原則に従って実装していくことになります。この図はよくリファレンスとして提示されますが、大枠のコンセプトを示すもので各プロジェクトに応じて層が増減して2層になったりであるとか、呼び名が変化することもあります。
https://blog.cleancoder.com/uncle-bob/images/2012-08-13-the-clean-architecture/CleanArchitecture.jpg
一方で、何かのライブラリにあるような「公式のドキュメント」は存在しません。そのため、色んな所でクリーンアーキテクチャを使った実装についてのブログエントリや技術資料が提供されているのでそれを参考にすると良いでしょう。原典となるものは Clean Coders Blog と言われていますが具体的な手法というよりは、考え方について解説されています。とはいえ、わかりやすいマニュアルや決まった使い方や実装方法が無いので、クリーンアーキテクチャが難しい、わからないと言われることにつながっているように身の回りの意見を通じて感じています。逆を言うと決まった形のない思考フレームワークだからこそ、実装においてはある程度の裁量や方言が許容されているのだと思っています。 クリーンアーキテクチャは冗長?
他のエントリでも何度か言及している通り、外部ライブラリなどの依存を抽象化したり隔離したりするために定義する interface やクラスなどを用意するため、素直に書くコードに比較すると1.5倍程度に増える傾向があります。コードの短さを単純に比較するとコードゴルフになったり、記載量やタイプ量での優位性の話になってしまうのでここでは取り扱いません。
この点を単独で見ると、単純にコードが冗長で管理がしづらそうに感じると思いますが、増えたコードで抽象化と隔離が行われていることで、単体テストしやすい実装にしたり、能動的か受動的かによらずライブラリの切り替えを行うシーンにおいて変更するコード量を抑えて実現することができます。また重要なのは「実際に交換することではなく交換できるように維持することが大事」であるということを抑えておく必要があります。これは長期的に運用するアプリケーションの実装において有効に作用します。
クリーンアーキテクチャは複雑?
クリーンアーキテクチャの解説には同心円状のコンセプト図がよく用いられますが、やるべきことは「関心の分離」と「詳細の隔離」が基本になります。実装しようとしている機能要件を機能を構成するコンポーネントに分割して考え、適切に小さな単位でアプリケーションを構築していくことが大事になります。また、どのライブラリを使うかなどの決定は、アプリケーションのビジネスロジックを実現する上では「詳細」という扱いになり、基本的に隔離することになります。詳細の隔離は一部運用上の例外を設けて限定的に実施しないこともあります。諸説ありますがそのほかはオプションと考えて良いでしょう。
しかしながら、素直に書いたコードに比較すると、interface や抽象化の実装が含まれている分、実装が複雑で理解がしづらいという主張がなされる場合もあります。これは素直に書いたコードに比較するとそのとおりでありますが、関心の分離をきちんと行えているコードに於いてはアプリケーションの実現するビジネスロジックは基本4層のうちUsecaseに集約されているので大枠を理解したいならここを見ることでほぼ解決するように構成されています。それ以外のどのライブラリを呼び出しているかなどはそれよりも外側の層を見ることで解決します。
クリーンアーキテクチャは学習コストが高い?
特にチーム開発においてはアプリケーションのコード変更する場合、コーディングスタンダードなどで共通理解を予め育んでいることがほとんどだと思います。素直に書いたコードは、開発者人数が少ない時点においてはさほど問題になりませんが、長期に渡って複数人数で開発するうちに無秩序に実装が膨れ上がりスパゲティコードとなってしまう場合もあります。
長期的に多人数による開発を行う場合には、ある程度決まり事を用意しておくとより安定的に開発を行うことができます。
クリーンアーキテクチャによる設計や考え方は、この決め事をする際のベースモデルとして置いておき、そこからチーム独自の例外や運用を決めていくことで、共通理解を早期に構築し、新規参入メンバーへの共有に役立てることができるのではないかと考えています。