コンテンツにスキップ

判断ガイド: クラスを分けるべきか

判断フロー

Q1. そのクラスの「変更理由」(誰のどんな都合で変わるか)を列挙せよ
    → 1つしかない ──> 分けない(行数が多くても分けない)
    → 2つ以上ある ──> Q2へ
Q2. その複数の理由で、実際に変更が起きているか?(履歴・直近の予定)
    → 起きていない(理屈上の分類だけ)──> 保留(分割候補としてメモのみ)
    → 起きている ──> Q3へ
Q3. 分けた後の2つは、独立して変更・テストできるか?
    → できる ──> 分ける(1責務ずつ、段階的に)
    → 密結合のまま(常に両方一緒に変更される)──> 分け方が間違い。境界を引き直す

根拠: SRP責務凝集度

判断材料

  • 分けるシグナル: 変更履歴に別種の理由が混在/UI・保存・通信の都合がロジックに混入/テストのセットアップが巨大/「このクラスのこの辺だけ触る」という会話が頻発
  • 分けないシグナル: 変更理由が1つ(数学ベクトル、純アルゴリズム)/一緒にしか変更されない/分けるとgetter/setterの橋だらけになる

例外

  • 行数だけを理由に分けない: 3000行でも変更理由が1つなら(稀だが)分割は不要。逆に200行でも理由が3つなら分ける
  • プロトタイプ・ジャム: 分けない。捨てるコードに分割投資は無意味
  • チーム分担の都合: 責務が1つでも「2人が同時に触ってコンフリクトする」なら物理分割(ファイル分割)の価値はある——設計上の分割とファイル分割は別の判断

トレードオフ

  • 得: 変更の局所化、テスト容易性、並行作業
  • 失: クラス間の受け渡しコード、追跡の手数(1画面で読めなくなる)、分けすぎるとショットガン手術(1変更で多ファイル修正)——分割の失敗は「大きすぎ」と「細かすぎ」の両方向にある

実践のコツ

  • 分割は1責務ずつ・動かしたまま(リファクタリングの手順: 抽出→委譲で旧API維持→呼び出し側移行→旧API削除)
  • 最初の一手は「クラス分割」ではなく関数の抽出でよいことが多い(SRPの単位はクラスとは限らない → SRPの自由関数の例)

理解度チェック

  1. 分割の判断基準が「行数」ではない理由を説明できますか。
  2. 「分け方が間違っている」ことを示すQ3のシグナルは?
  3. 設計上の分割とファイル分割が別の判断である例は?

前: カテゴリ目次 | 次: インターフェースを作るべきか