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() など)
金額計算 → OrderOrderLineMoney のメソッド
在庫引当 → InventoryService

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

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

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

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

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

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

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


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

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

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

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


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

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

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

という存在です。

クラスを見て、

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

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

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