现在我们开始实现第二个限界上下文——ATM。它要比SnackMachine要简单,只有取款和手续费等的功能。在这里,我们选择第一种代码隔离类型。
package com.lugew.springbootddd.atm;import com.lugew.springbootddd.common.AggregateRoot;import com.lugew.springbootddd.sharedkernel.Money;import lombok.Getter;import lombok.Setter;import static com.lugew.springbootddd.sharedkernel.Money.None;@Getter@Setterpublic class Atm extends AggregateRoot {private static float commissionRate = 0.01f;private Money moneyInside = None;private float moneyCharged;public void takeMoney(float amount) {Money output = moneyInside.allocate(amount);moneyInside = moneyInside.substract(output);float amountWithCommission = amount + amount * commissionRate;moneyCharged += amountWithCommission;}public void loadMoney(Money money) {moneyInside = moneyInside.add(money);}}
显然ATM是聚合根,它包含三个字段moneyInside和moneyCharged,和takeMoney取款和loadMoney存款方法。接下来为其添加测试
package com.lugew.springbootddd.atm;import org.junit.Test;import static com.lugew.springbootddd.sharedkernel.Money.Dollar;import static org.junit.jupiter.api.Assertions.assertEquals;public class AtmTest {@Testpublic void take_money_exchanges_money_with_commission() {Atm atm = new Atm();atm.loadMoney(Dollar);atm.takeMoney(1);assertEquals(atm.getMoneyInside().getAmount(), 0, 0);assertEquals(atm.getMoneyCharged(), 1.01, 0.001);}}
测试验证取款功能,且取款手续费为0.01。除此之外,还有其它需求,如取款0.01如何处理,取款1.10手续费是0.01还是0.02,这些需求可以咨询领域专家。假设手续费最低0.01且四舍五入计算。
@Testpublic void commission_is_at_least_one_cent() {Atm atm = new Atm();atm.loadMoney(Cent);atm.takeMoney(0.01f);assertEquals(atm.getMoneyCharged(), 0.02, 0.001);}@Testpublic void commission_is_rounded_up_to_the_next_cent() {Atm atm = new Atm();atm.loadMoney(Dollar.add(TenCent));atm.takeMoney(1.1f);assertEquals(atm.getMoneyCharged(), 1.12, 0.01);}
public void takeMoney(float amount) {Money output = moneyInside.allocate(amount);moneyInside = moneyInside.substract(output);float amountWithCommission = calculateAmountWithCommission(amount);moneyCharged += amountWithCommission;}public void loadMoney(Money money) {moneyInside = moneyInside.add(money);}public float calculateAmountWithCommission(float amount) {float commission = amount * commissionRate;float lessThanCent = commission % 0.01f;if (lessThanCent > 0) {commission = commission - lessThanCent + 0.01f;}return amount + commission;}
还需添加一些验证:
public void takeMoney(float amount) {if (!canTakeMoney(amount).equals("")) {throw new IllegalStateException();}Money output = moneyInside.allocate(amount);moneyInside = moneyInside.substract(output);float amountWithCommission = calculateAmountWithCommission(amount);moneyCharged += amountWithCommission;}public String canTakeMoney(float amount) {if (amount <= 0f)return "Invalid amount";if (moneyInside.getAmount() < amount)return "Not enough money";if (!moneyInside.canAllocate(amount))return "Not enough change";return "";}
