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も事前条件にはあるのだがここでのエントリの議論の対象からははずす