Java | オブジェクト指向:神クラス(God Object)

Java Java
スポンサーリンク
スポンサーリンク

神クラス(God Object)とは何か

神クラス(God Object)は
「システムのあらゆることを“何でも知っていて、何でもやろうとする”巨大なクラス」
のことです。

画面の制御もやる。
ビジネスロジックも全部持つ。
DB からの読み書きもやる。
外部 API も叩く。
ログも出す。
設定も持つ。

とにかく「全部このクラスから始まる」みたいな存在です。

最初は「ここを見れば全部分かるから便利」に見えるんですが、
成長すればするほど、変更が怖くなり、バグが埋もれ、誰も触れない“ボスキャラ”になります。


典型例:神クラス臭のする OrderSystemManager

何でもやるクラスのイメージコード

イメージしやすい神クラスの例を、ざっくり Java で書くとこんな感じです。

public class OrderSystemManager {

    // 全ドメインを握るフィールドたち
    private final UserRepository userRepository;
    private final OrderRepository orderRepository;
    private final ProductRepository productRepository;
    private final MailSender mailSender;
    private final PaymentGateway paymentGateway;
    private final Logger logger;

    public void registerUser(UserRequest request) {
        // 入力チェック
        // パスワードハッシュ
        // User エンティティ生成
        // DB 保存
        // メール送信
        // ログ出力
    }

    public void placeOrder(OrderRequest request) {
        // ユーザ取得
        // 商品取得
        // 在庫チェック
        // 合計金額計算
        // 割引計算
        // 決済実行
        // 注文保存
        // メール送信
        // ログ出力
    }

    public void cancelOrder(long orderId) {
        // 注文取得
        // 状態チェック
        // 返金処理
        // 在庫戻し
        // 状態更新
        // メール送信
        // ログ出力
    }

    public void exportOrdersToCsv(LocalDate from, LocalDate to) {
        // 注文一覧取得
        // CSV 生成
        // ファイル出力
        // ログ出力
    }

    // さらに 20 個ぐらいメソッドが続く…
}
Java

OrderSystemManager という名前ですが、
ユーザ登録、注文、決済、メール送信、CSV 出力、ログ…何でもやっています。

このクラス一つが、システムのあらゆるドメイン(ユーザ・注文・商品・決済)にべったり依存し、
「中心どころか全部を握っている」状態です。


なぜ神クラスがヤバいのか(重要なポイント)

変更の影響範囲が読めない

例えば、「注文時の割引ルールを変えたい」とします。

本来なら「割引を担当しているクラス」を開いて直したいところですが、
神クラスだと、割引ロジックが placeOrder メソッドの中に直接書かれているかもしれません。

しかも、同じ割引ロジックが別メソッドにもコピペされていたりします。

割引ロジックを変えたいだけなのに、

placeOrder の中
recalculateOrderAmount の中
exportOrdersToCsv の中

など、複数のメソッドを探して全部修正しないといけない。

そして、「どこか 1 か所の修正を忘れてバグになる」というのが、神クラスあるあるです。

テストがほぼ不可能に近づいていく

神クラスは、たいてい依存オブジェクトが大量です。

UserRepository
OrderRepository
ProductRepository
MailSender
PaymentGateway
Logger
…

ユニットテストを書こうとすると、

全部をモックするセットアップ
あるいは本物の DB やメール送信を動かす羽目

になります。

「この小さなロジックだけテストしたい」のに、
クラスが巨大すぎて、その小さなロジックだけを切り離せない。

結果、「まともなテストを書く気が失せて、結局手動テストに頼る」という流れになります。
テストがないから怖くてリファクタリングできず、さらに神クラスが太る、という悪循環です。

責務がごちゃ混ぜになり、誰も全体を理解できなくなる

神クラスは、「やっていることの種類」が多すぎます。

ビジネスルール
DB アクセス
外部 API 呼び出し
トランザクション管理
入力チェック
ログ
メール送信
ファイル出力

これらが一つのメソッド内で入り乱れます。

コードを読んでいると、「今どの層の話をしているのか」が分からなくなってきます。

ビジネス的に重要なロジックを見たいのに、
SQL やメール文面の組み立て、ログ出力などに視線が奪われる。

結果、システムの肝心なルールがコードの中に埋もれていきます。


神クラスになりかけている兆候を見抜く(深掘り)

兆候1: クラスを開くとスクロールバーが豆粒

単純ですが効きます。

クラスファイルを開いてみて、

画面のスクロールバーがほぼ一番上に張り付いていて、小さな点に見える
メソッド一覧(IDE のアウトライン)を開くと、スクロールしないと全部見えない

といった状態なら、そのクラスはかなり危険ゾーンです。

特に 〜Service や 〜Manager、〜Controller などがそうなっていたら、「神化」が進行しています。

兆候2: 「とりあえずここにメソッド足しとくか」が口癖になっている

新しい仕様が来たときに、

「まあ今回もとりあえず OrderSystemManager にメソッドを1個足して…」

と、毎回同じクラスにメソッドを追加していないかどうか。

これを繰り返していると、そのクラスはあっという間に「全部持ってるクラス」になります。
「この処理、名前的にここしかないよね」と安易に突っ込む前に、「本当にこのクラスの責務か?」を一度立ち止まって考える必要があります。

兆候3: フィールドとコンストラクタ引数がやたら多い

神クラスは、たいてい依存する相手も多いです。

UserRepository
OrderRepository
ProductRepository
MailSender
PaymentGateway
ReportGenerator
CsvExporter
NotificationService
…

フィールドの数、コンストラクタ引数の数が増えれば増えるほど、
そのクラスが担当している領域の広さも増えています。

コンストラクタ引数が 5 個を超え始めたら、「そろそろ責務を分けるべきじゃないか?」と疑うサインです。


本来あるべき姿:神クラスが“分解された世界”

責務ごとにクラスを分けるイメージ

さきほどの OrderSystemManager を、責務ごとにスパッと分けると、
だいたいこんな方向になります。

ユーザ登録関連 → UserRegistrationService
注文受付 → PlaceOrderService
注文キャンセル → CancelOrderService
レポート作成 → OrderReportService
メール送信 → OrderMailService or ドメインイベント+リスナー

さらに、ドメインモデル側にも責務を移します。

注文の状態遷移ルール → Order エンティティのメソッド(cancel(), ship() など)
金額計算 → Order や OrderLine、Money のメソッド
在庫引当 → InventoryService

こうして、「全部1クラス」ではなく「役割ごとに複数クラス」が協調する構造にすると、
一つ一つのクラスはだいぶ小さくなります。

「こいつは神クラスじゃないか?」と気づいたときの思考

神クラス候補を見つけたら、こう自問してみてください。

このクラスがやっていることを、ざっくりグルーピングしたら何種類ある?
そのグループごとに、クラスを分けられないか?
ビジネスルールは本来ドメインモデル側に寄せられないか?

たとえば placeOrder メソッドを眺めて、

入力検証
ドメインオブジェクトの生成
ビジネスルール(割引、在庫チェック)
DB 永続化
メール送信

という感じで色分けして考えると、
「これとこれは別クラスに切り出せるな」というイメージが湧きやすくなります。


神クラスを避けるための、日々の小さな習慣

ここからは、具体的なテクニックというより「癖」の話です。

新しいメソッドを書くときに、「このメソッドはどのクラスに書くのが一番自然か?」を考える
「〜Service」や「〜Manager」に何でも集めない
「この if/switch は、本当は別のクラス(状態・種別)の責務じゃないか?」と疑う
ドメインモデル(User, Order, Money など)に積極的に振る舞いを持たせる

こういう感覚を少しずつ育てていくと、
「神クラスを作りたくても作れない体質」になっていきます。


まとめ:神クラスは“便利屋”の顔をした「負債の貯蔵庫」

神クラス(God Object)は、一言で言うと

最初は便利そうに見える
でも長期的には、変更しづらさ・テストしづらさ・バグの温床を生む

という存在です。

クラスを見て、

何でもかんでもそのクラスが知っていて、何でもかんでもやっていないか
責務がごちゃ混ぜになっていないか
そのクラスを触るのがチームの中で“罰ゲーム”になっていないか

と感じたら、それはもう神クラス化が始まっています。

タイトルとURLをコピーしました