wildcatsの日記

赤羽在住でIT関係の会社の社長やってます。

1インタフェースに対して1実装クラスを抽出する有害性

去年に書いたエントリの補足
1インタフェースに対して1実装クラスを抽出することが私は有害だと考えています。
理由はインタフェイスに対するContractを破った他の実装クラスが発生する恐れがあるからです。
例として銀行の口座の例を挙げます。


public class AccountImpl {
private int amount;
public int cashOut(int request) {
this.amount = this.amount - request;
return request;
}
public int getAmount() {
return this.amount;
}
public void setAmount(int newAmount) {
this.amount = newAmount;
}
}
と言うクラスがあったと仮定してインタフェースを抽出すると

public interface Accont {
public int cashOut(int request);
public int getAmount();
public void setAmount(int newAmount);
}
となります。
そうした場合にAccount#cashOutメソッドのインタフェースの事前条件としては
this.amount >= request
であると言えます。*1
利用するプログラム側は

Account account = AccountFinedr.find(accountId); // 普通Finderはstaticにはしないけどね。
int cashAmount;
if (account.getAmount() > requestCashOut) {
cashAmount = account.cashOut(requestCashOut);
}
と言ったプログラムとなるでしょう。
ここで機能追加が発生しAccountの実装が増えたと仮定しましょう。
そうした場合にもし先にあげた事前条件であるthis.amount >= requestが満たされないクラスが実装されてしまったらどうなるでしょうか?
利用するプログラム側の

if (account.getAmount() > requestCashOut) {
cashAmount = account.cashOut(requestCashOut);
}
インスタンスによって動作したり動作しなかったりする恐れがあります。
正確に言うと実行時のインスタンスによって利用側がコードを書かなくてはなりません。
すなわちinstanceofによる評価でインスタンスがAccountImplである場合には
上のコードで問題なしとなります。


よって1インタフェース1実装クラスを私は有害だと考えます。

*1:request > 0も事前条件にはあるのだがここでのエントリの議論の対象からははずす