戻る
■保守しやすい設計
以下のように、金額を表すクラスがあるとする
package org.example; import java.util.Currency; public class Money { int amount; // 金額 Currency currency; // 通貨単位 }
このクラスは、以下のようにして使用できる
package org.example; import java.util.Currency; import java.util.Locale; public class Main { public static void main(String[] args) { // クラスの利用 var money = new Money(); // 所持金 money.amount = 1000; money.currency = Currency.getInstance(Locale.JAPAN); // バリデート if (money.amount < 0) { System.out.println("金額には0以上を指定してください。"); System.exit(0); } if (money.currency == null) { System.out.println("通貨単位を指定してください。"); System.exit(0); } // 商品金額 var goods = 300; // 金額の計算 if (goods > money.amount) { System.out.println("金額が足りません。"); } money.amount -= goods; // 結果の表示 System.out.println("残金は" + money.amount + "(" + money.currency + ")です。"); } }
ただしこのMoneyクラスは、クラス単体で正常に動作するように設計できていない 具体的には ・金額や通貨単位がセットされないまま使われる可能性がある ・金額が単純な数値型なので、金額以外の意図しない数値を渡される可能性がある ・バリデートや金額の計算など、ロジックがあちこちに散らばる可能性がある。また重複して同じ処理が何度も書かれる可能性がある ・クラス内の値が意図せず変更されてしまう可能性がある といった問題があり、プログラムの規模が大きくなると仕様変更の際に変更し忘れが発生しやすくなる 今回の場合、以下のようにすることで変更に強いクラスになる
package org.example; import java.util.Currency; public class Money { private final int amount; // 金額 private final Currency currency; // 通貨単位 public Money(final int amount, final Currency currency) { if (amount < 0) { throw new IllegalArgumentException("金額には0以上を指定してください。"); } if (currency == null) { throw new IllegalArgumentException("通貨単位を指定してください。"); } this.amount = amount; this.currency = currency; } public int amount() { return amount; } public Currency currency() { return currency; } public Money pay(final Money other) { if (!currency.equals(other.currency)) { throw new IllegalArgumentException("異なる通貨単位では計算できません。"); } if (other.amount > amount) { throw new IllegalArgumentException("支払う金額が足りません。"); } final int payed = amount - other.amount; return new Money(payed, currency); } }
package org.example; import java.util.Currency; import java.util.Locale; public class Main { public static void main(String[] args) { // 所持金 var money = new Money(1000, Currency.getInstance(Locale.JAPAN)); // 商品金額 var goods = new Money(300, Currency.getInstance(Locale.JAPAN)); // 金額の計算 var payed = money.pay(goods); // 結果の表示 System.out.println("残金は" + payed.amount() + "(" + payed.currency() + ")です。"); } }