💭

フィールドに持つべきか?メソッドで判定すべきか?

に公開

「この判定はフィールドに持っておけば効率的だし、メソッド呼び出しも減るはず」

と思い、安易にフラグを定義してみたら「本当に効率的になった?」とモヤっとした。
なぜモヤっとしたのか頭の中を整理してみた。

なぜモヤっとするのか?

1. 状態の重複・冗長性

メソッドで動的に判定できる情報をフィールドとして持つと、同じ情報を二重管理することになる。

// 判定メソッドあり
boolean isIrregular() { ... }

// フィールドも保持
boolean irregularFlag; 

どちらかが更新されないと矛盾が発生し、不具合の原因になりやすい。

2. 保守性の低下

フィールドの値がどこで設定・更新されるか追う必要があり、複雑な処理では理解コストが増えてしまう。
複数箇所で更新されるフィールドは「うっかり更新漏れ」「順序依存のバグ」を引き起こしやすい。

3. テストの複雑化

フィールド依存のロジックは、テスト時に状態を準備する必要がある。
本来なら「メソッドを呼べば結果が返る」だけで済むテストが煩雑になる。

フィールド化の前にできる方法

1. メソッドのオーバーライド

class Employee {
    boolean isIrregular() { return false; }
}

class IrregularEmployee extends Employee {
    @Override
    boolean isIrregular() { return true; }
}

サブクラスで振る舞いを変えつつ、状態の二重管理を避けられる。

2. 計算による判定

軽量な判定は、必要なときにメソッドで計算するだけで十分。

  • フィールドを増やすより保守性が高い
  • 判定ロジックの変更もメソッド内で完結する

3. 戦略の注入(Strategy Pattern)

class Employee {
    private IrregularPolicy policy;

    boolean isIrregular() {
        return policy.isIrregular(this);
    }
}

判定基準が変わる可能性がある場合、状態を持たず柔軟に対応できる。

あえてフィールドを持つ場合

  • 計算コストが高い場合
    一度計算した結果を保持する方が効率的

  • 外部から値が注入される場合
    DIや設定値など、外部から与えられる情報はフィールドとして保持

  • オブジェクトの状態として自然に保持すべき場合
    画面表示のために一時的に必要な状態など

まとめ

  • 原則:計算できるものは状態として持たない
  • 対応方法:メソッドのオーバーライド、計算による判定、戦略の注入
  • 例外:キャッシュが必要な場合、外部値の注入、オブジェクトの状態として保持すべき場合

この考え方を意識すれば、コードはシンプルで理解しやすく、長期的に変更しやすいシステムを作れる。
柔軟性と効率性のバランスを見極めて、必要に応じてフィールドを持つ判断を行う。

状態管理を考えるきっかけになった。

Discussion