見出し | OOP
クラス設計
クラスとは
データとロジックを1つのプログラミング単位にまとめる仕組み。
良いクラス設計とは
本記事は把握しやすく変更に強いクラスを 良いクラス と考える。
- 各クラスの役割が明確(関心ごとを分離、単一責任の原則)
- 各クラスの依存関係が適切(本記事の主題)
依存関係とは
クラス A がクラス B のメンバーを呼び出しているとき、クラス A はクラス B に依存していると呼ぶ。
graph LR
A(A) --> B(B)
(A→Bの)依存関係の原則
- クラス B の変更はクラス A に影響する
- クラス A の変更はクラス B に影響しない(クラス Bはクラス A を知らなくてよい
良くない依存関係
影響範囲が広く・複雑な依存関係。
- 多すぎる依存
- 循環依存
良い依存関係
依存関係が安定している。
不安定な依存とは
- 変更を受けやすいクラスへの依存
- 自分でコントロールできないクラスへの依存
上記の例はアプリケーションの入出力に近いクラス( UI, DB, WEB API )。
- 詳細への依存
依存関係をコントロール
制御の流れと(安定した)良い依存関係が一致しない場合がある。
良い依存関係を実現するために依存をコントロールする必要がある。
おもに 依存性逆転の原則 を使う。
依存関係逆転の原則
例:改善前
制御:UIから始まり、データの取得、永続化へと続く一連の処理フローを示 UI → Fetcher → API Client → Domain(Account/Costs) → DB Writer
- UI (ユーザーインターフェース)
- Fetcher がデータを取得する役割を担う(ユースケース)
- API Client が外部のAPIと通信(外部の影響を受ける不安定なクラス)
- Account や Costs といったデータモデル
- DB Writer がデータベースへの書き込み(永続化)
上記の制御の流れではアプリケーションのユースケース Fetcher がコントールが難しい外部 API と通信するクラス API Client に依存している。 依存関係逆転の法則を使用して依存の向きをコントーロール(逆転)する
改善後
Fetcher(上位モジュール)が API Client(下位で不安定なモジュール)に依存するのではなく、間にインターフェースを挟むことで、依存関係の方向を逆転させている。これにより、API Client のような不安定な部分の変更が Fetcher に影響を与えにくくなり、システム全体が安定する。
逆転とは API Client インターフェースの所有者を API Client ではなく方針をしめしている Fetcher と考えることで API Client が Fetcher(が提供しているインターレース)に依存していると考えることができる。
依存性の逆転は現代のフレームワークでは DI( Symfony のサービスコンテナの機能の一つ)で実現。