経緯
以前とある席で偶然シニアエンジニアの方と設計について議論することがありました。
その時に特に耳に残っていたのは以下の様な内容です。
- クリーンアーキテクチャってテストしやすくする為のですよね?
- 設計はコード書ける人が他のコードを書ける人に威張るための道具なのではないか?
- 設計を学習するならブロックチェーンとかを勉強して技術力を高めるべきなのではないか?
- リーダブルコードさえ読んでいれば設計は必要ないのではないか?
- 設計なんて不要でしょ
その方はかなり詳しく設計の歴史をしっていて尤もな事を言っていましたが、平成も終わる頃においてはその限りではないです。
なので平成最後の日にそれら全てに対して最終的に解答できる形で設計の有用性を説明し、気持ちよく令和を迎えます。
注意: 一応ここで説明する内容や要素も一面だけです。
よくある誤解
クリーンアーキテクチャといえばこの有名なリングですよね。
このリングに登場するようにコードを分解して実装し、データを単方向に流れるようにもしたらさぞかし美しい工芸品が出来上がるのではないか?
これはクリーンアーキテクチャの説明を正しくできていませんし、設計とはそういうものではありません。
しかし、初めて設計・クリーンアーキテクチャに触れた方々はよくこのような誤解をしてしまうのを見受けますが、それも以前であれば致し方ない事だと思います。
クリーンアーキテクチャの要素の解説
Controller
コントローラーはリクエストに届いた値のバリデーションをし、結果に応じたインタラクションをするだけです。
成功時は基本Usecaseを実行するでしょう。
Usecase
Usecaseはアプリケーションの目的を果たすためにインタラクションをするだけです。
Usecaseが使うのはRepositoryとEntityです。
Usecase内ではあまりバリデーションはしないようにするのが自分は好きです。
理由としては、AのUsecaseでバリデーションをして整合性を保った際に、BのUsecaseではそのバリデーションの考慮漏れがあったとします。または、メンテする際にAだけ改善してBを改善し忘れたなどしてしまう可能性があります。
なので、そういったのは、下手にバリデーションだけをするよりかは、Entity内のロジックにしっかりと閉じ込めておいて、単一データにおいて
、不整合な状態が起こりえないようなプログラミングをするべきだと思います。ちなみにこの辺のノウハウはDDDの戦術的設計に書かれています。
Entity
Entityには何物にも依存しないロジックだけが入っています。
Repository
Repositoryは外部とのやりとりを担当します。
大抵の場合はDBです。
Repositoryの影響はインパクトが大きめです。
もしRepositoryを直接classで実装すればコードはシンプルになりますが、テストするのにDBを起動する必要のあるレイヤードアーキテクチャになりますし、もしJava等のインターフェースを利用して実装した場合、テスト時はスタブを使う事により、DBに依存しない高速で柔軟性の高いテストができます。しかし、Repositoryをインターフェースで実装した場合は大抵の場合は全面的にDI機構が必要になります。
もしテストする際に別にDB起動するのに問題がないし、バグトレースにも支障がなければ別にインターフェースをかませる必要はないでしょう。
レイヤを超える際の原則
クリーンアーキテクチャでは、「レイヤーを超える際はインターフェースを通しましょう。」と言っています。
どういうことかというと、ControllerからUsecase、UsecaseからRepositoryに繋ぐ際に、テストがしやすくなるからです。
Controllerを例にすると、Usecaseをスタブに置き換えたら、確実なControllerのテストができますし、また、異常ケースのテストも専用のエラーを一瞬で投げるスタブを使えばすぐにテストできます。
しかもController周辺のコードは凄くシンプルになります。
しかし、別にこの恩恵が欲しくない場合は適用しなくていいでしょう。
クリーンアーキテクチャとは
クリーンアーキテクチャはSOLID原則を丁寧に適用したらできる設計パターンの1つであるとも捉えられます。
ゴリゴリの速度重視のフレームワーク依存のコードと比べた場合にクリーンアーキテクチャを上手く使った事により得られるメリットは、主に以下の4個でしょう
- テスタビリティ
- 拡張性
- 変更性
- 役割に応じてコードが分解されることにより、1要素辺りのコードの複雑生の軽減
- 「クリーンアーキテクチャです。」と言えばクリーンアーキテクチャを知っていた場合は共有コストが凄く低いし、共有されれば財産になる
クリーンアーキテクチャまとめ
我々は工芸家ではないので、工芸的な要素の為に書いているコードは一つもありません。
プロダクトを成功させるためにコードを書いています。
なので、どの要素も既存の開発で抱えていた問題、または抱えるであろう問題を一般的な人間が解決しやすい単位に分解し、予防・解消・発見しやすくする為にあります。
もし、その要素を適用する必要がそもそもないならそれは省いたり、独自のスタイルに変更します。
もちろんMVCやMVPなどのアーキテクチャもその限りです。
しかも設計の必要性や要素は全て言語化して説明できるものです。
でも設計って学ぶの大変でしょ?
私が設計に興味を持ったのは2018年からなので、それ以前の設計の事はよく知りません。
しかし、平成も終わる頃となっては以前と比べると設計を学ぶハードルは大分低くなっています。
なぜなら今は設計の優良本が沢山でていますし、設計のコミュニティも活発で簡単に質疑応答ができたり、イベントもあったりする時代になっているからです。
前は10年やってもよくわからなかった設計が今なら数ヶ月で大分わかるようになりますし、1年学習しながら実践も繰り返せば戦術から戦略レベルまでかなり詳しくなれるでしょう。
確かにブロックチェーンやその他新たな面白そうな技術が登場する度にキャッチアップするのはとても大切な事です。しかし、設計は全てのコードの品質と開発速度のコントロールをします。しかもたった数ヶ月のボリュームである程度までやれますし、フロントやサーバー問わずに良い影響を与えます。もし自分の仕事がブロックチェーン事業の仕事でないのなら、ブロックチェーンは一旦置いといて、少しだけでも設計の本を読むべきではないでしょうか。
まとめ
**経験からくると〜って言葉ほど胡散臭くて議論の余地がないものはないです。**その一言で全ての話が終わってしまいますからね。この業界にいると、もし2人のシニアエンジニアが、違うことを経験からくると〜って言った際に、採用されなかった方の人がチームから離れていく所なんてよく見る光景です。
リーダブルコードさえ読んでおけば、ある程度コードを書いたらなんとなくみんな同じようなコードになる。
そういった不確実な物にチームとプロダクトの未来を預けるわけには行きません。
我々はエンジニアなのでこの要件のプロダクトにはどのような開発が向いていて、どうコードを書いて、速度を落とさずに成功に導けるのかをチーム全体で考える必要がありますし、いつでも言語化できる必要があります。
その能力を前と比べると簡単に得られる現在においては、重い腰を上げて少しの学習コストを払って今一度キャッチアップするべきではないでしょうか。この設計の技術は少なくともリーダブルコードをさえ読めばなんとなくできるでしょって言う類のものではないです。