まとめ: 実務でクラス設計を判断するために
第 1 章の god class から始まり、第 13 章のリファクタリング実践まで、13 章分の判断基準を積み上げてきました。 実際のコードに向き合うとき、13 章分の内容を最初から思い出す必要はありません。 この章では、判断に迷ったときに立ち返れるよう、ここまでの内容をチェックリストの形に整理します。
第1部が積み上げてきたもの
第 1 部(第 1〜7 章)は、フレームワークに依存しないクラス設計の原則を扱いました。 god class(第 1 章)から始まり、カプセル化カプセル化 (Encapsulation)データとそれを操作する手続きをクラスにまとめ、外部から直接触れる範囲を絞ること。内部表現を変えても利用側が壊れない状態を保つ。と tell-don't-ask(第 3 章)、単一責任の原則によるクラスの分割(第 4 章)、継承とコンポジションの使い分け(第 5 章)、インターフェースを介した抽象への依存(第 6 章)と、判断基準を 1 つずつ積み上げました。
第 7 章は、この積み上げを凝集度と結合度という 1 つの物差しに統合しました。 単一責任の原則SRP (単一責任の原則)SOLID の 1 番目。1 つのクラスが変更を求められる理由は 1 つだけであるべきという原則。「1 つの仕事だけをする」という意味ではない。は凝集度凝集度 (Cohesion)1 つのモジュール内の要素が、どれだけ同じ目的に向かっているかの度合い。高いほど良い設計とされる。を高く保つための手段であり、依存性逆転・開放閉鎖・インターフェース分離の各原則は結合度を低く保つための手段です。 リスコフの置換原則LSP (リスコフの置換原則)SOLID の 3 番目。派生型は基底型と入れ替えても、利用側のコードを壊さずに動作しなければならないという原則。は、その結合度結合度 (Coupling)モジュール同士がどれだけ強く依存し合っているかの度合い。低い (疎結合) ほど、片方の変更がもう片方に波及しにくい。を下げる工夫が成り立つための前提条件として位置づけられます。
第2部が積み上げてきたもの
第 2 部の応用パート(第 8〜13 章)では、ここまでの原則を Laravel の実務コードに応用しました。 Fat Controller・Fat Model の診断(第 8 章)から始まり、Eloquent モデルの責務(第 9 章)、サービスクラスへの切り出し(第 10 章)へと進みました。さらに Laravel のコンテナを使った依存性注入(第 11 章)、Form Request とカスタム例外による設計(第 12 章)と判断基準を重ねました。 第 13 章では、その全部を 1 つの Controller に通しで適用しました。
第 13 章の冒頭で述べたとおり、この過程で新しい判断基準は登場していません。 ここまでの 13 章で見た基準を、順番に適用しただけです。
実務で使うためのチェックリスト
自分の書いたクラスやレビュー中のコードを前にして、次の問いに順番に当てはめてみてください。 該当する項目があれば、それが次に手を入れる場所です。
クラス単体を見るとき
- そのクラスが変更される理由は、1 つに絞れるか(第 4 章)
- public なプロパティを外部から直接書き換えられる状態になっていないか(第 3 章)
- 呼び出し側がそのクラスの内部状態を覗いて、判断や計算をしていないか(第 3 章)
クラス同士の関係を見るとき
- 継承の軸が複数になっていないか。増えるほど組み合わせが増えていないか(第 5 章)
- 具象クラスに直接依存していて、実装を差し替えるだけで依存元まで書き換える必要が生じていないか(第 6 章)
- 条件分岐を、既存コードの修正でなく実装の追加で解決できているか(第 7 章)
- 派生クラスが、基底クラスの期待する振る舞いを裏切っていないか(第 7 章)
- 使わないメソッドへの依存を、インターフェースを通じて強制していないか(第 7 章)
Laravelでの実装を見るとき
- Eloquent モデルに書かれている処理は、そのモデル自身のデータの表現・解釈だけで完結しているか(第 9 章)
- Controller に、複数の関心事を調整する処理が残っていないか(第 10 章)
- サービスクラスへ切り出した後も、単一責任は保てているか。ファイルを分けただけになっていないか(第 10 章)
- インターフェースへの依存を、Laravel のコンテナで解決できているか。
bind()の登録漏れがないか(第 11 章) - リクエストの形式チェックは Form Request へ、意図を伝える例外はカスタム例外クラスへ切り出せているか(第 12 章)
次に読む
本ガイドは、クラス設計そのものの範囲にとどめてきました。 DDD 戦術パターン(値オブジェクト・エンティティ・集約・リポジトリパターン)や、クリーンアーキテクチャの層実装(ユースケース層・プレゼンテーション層・トランザクション境界の管理)は、範囲の外に置いています。
- Laravel × DDD × クリーンアーキテクチャ実践ガイド — 本ガイドで扱わなかった DDD・クリーンアーキテクチャの実践編です
- クリーンコードガイド — クラス — TypeScript でのクラス設計を扱います。言語は異なりますが、原則の多くは共通しています
- クリーンコードガイド — SOLID原則 — 第 7 章で扱った SOLID 原則を、TypeScript の例で振り返る内容です