カプセル化によるルールの強制とその重要性

java

オブジェクト指向を適用すると、ソースコードの重複した記述を排除でき、生産性や品質を向上することができます。
それとは別に、他の開発者にルールを強制できるメリットもあります。
カプセル化を例にして説明するのがわかりやすいので、今回はカプセル化を例に挙げてルールを強制するメリットを書いていきます。


例えば、自分は商品の金額を計算するPriceCalcクラスを作成していて、他の開発者はPriceCalcクラスを利用するUserクラスを作成しているとします。
自分としては「このロジックで金額計算して欲しい」というのがあるのですが、他の開発者にそのロジックの実装をさせるようにしてしまうと、意図が上手く伝わらなかった時に誤ったロジックで計算されてしまいます。
この状況をソースコードで表すと下記のような形になり、PriceCalcクラスは計算に必要な変数をまとめるだけ、PriceCalc側でその変数を参照して独自に業務ロジックを実装するような形となります。

public class PriceCalc {

    public ArrayList<Integer> costs = new ArrayList<Integer>();
    public int taxRate = 0;
    :
    : 色々なメンバ変数定義
    :

}
public class User {

    PriceCalc priceCalc = new PriceCalc();
    :
    : priceCalcオブジェクトのメンバ変数を使った複雑な業務ロジック
    :
    
}

それでは困るので、クラス変数に付随する業務ロジックもPriceCalcクラス側に実装することにします。
変数とメソッドをひとまとまりにして一つのクラスとして提供することで、Userクラス側ではメソッドを呼び出すだけであるべき業務ロジックに基づいた計算を行うことができ、Userクラス側で業務ロジックを意識する必要が無くなります。

しかし、メンバ変数がpublicだと、Userクラス側でその変数を参照して独自に業務ロジックを実装することもできてしまいます。
自分としてはそれでは困るので、「変数を参照して独自に業務ロジックを実装しないでください」と伝えるのですが、それが上手く伝わらないと独自に業務ロジックを実装されてしまう可能性があります。
自分一人でプログラムを作っている場合は全ての変数をpublicにした方が便利だったりもしますが、複数人で開発している場合は意思疎通がうまく行かなかった場合に意図通りではないコーディングをされてしまうリスクがあります。

public class PriceCalc {

    public ArrayList<Integer> costs = new ArrayList<Integer>();
    public int taxRate;
    :
    : 色々なメンバ変数定義
    :
    
    public void registNewCost(int cost) {
        this.costs.add(cost);
    }
    :
    : メンバ変数の設定用メソッド
    :
    
    public int getPrice(int index) {
        :
        : 複雑な業務ロジック
        :
    }

}
public class User {

    PriceCalc priceCalc = new PriceCalc();
    :
    : PriceCalcクラスのメソッドを使った設定
    :
    int priceOk = priceCalc.getPrice(index);
    
    // しかし用意したメソッドを使用せずに独自で計算できてしまう
    int priceNg = priceCalc.costs.get(index) * priceCalc.taxRate;
    
}

それを防ぐためには、変数のアクセスレベルをprivate等にして、変数に自由にアクセスできないようにするのが有効です。
こうすることで、変数を参照して独自に業務ロジックを実装しようとされた場合に、コンパイルエラーとして機械的に失敗させることができます。
これが、カプセル化によるルールの強制であり、意思疎通がうまく行かなかった場合に意図通りではないコーディングをされるリスクを減らすことができます。

public class PriceCalc {

    private ArrayList<Integer> costs = new ArrayList<Integer>();
    private int taxRate;
    :
    : 色々なメンバ変数定義
    :
    
    public void registNewCost(int cost) {
        this.costs.add(cost);
    }
    :
    : メンバ変数の設定用メソッド
    :
    
    public int getPrice(int index) {
        :
        : 複雑な業務ロジック
        :
    }

}
public class User {

    PriceCalc priceCalc = new PriceCalc();
    :
    : PriceCalcクラスのメソッドを使った設定
    :
    int priceOk = priceCalc.getPrice(index);
    
    // 下記はコンパイルエラー
    // int priceNg = priceCalc.costs.get(index) * priceCalc.taxRate;
    
}

いかがでしたでしょうか。

一人で開発する時と複数人で開発する時では、気を付けるべきポイントが変わることがあります。
オブジェクト指向の考え方の一つである「カプセル化」も、単なる慣習として捉えるのではなく、複数人で開発する場合にルールを規定するものとして捉えることで、実務で有効に使えるのではないかと思います。

コメント

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