限界上下文已经定义了,接下来是实现追踪用户银行卡手续费,首先是ApllicationService的AtmController:
@PutMapping("/{id}/{amount}")
@ResponseBody
public String takeMoney(@PathVariable("id") long id, @PathVariable("amount")
float amount) {
AtmDto atmDto = atmRepository.findById(id).orElse(null);
Atm atm = atmDto.convertToAtm();
if (!atm.canTakeMoney(amount).isEmpty()) return
atm.canTakeMoney(amount);
float amountWithCommission =
atm.calculateAmountWithCommission(amount);
paymentGateway.chargePayment(amountWithCommission);
atm.takeMoney(amount);
atmRepository.save(atm.convertToAtmDto());
HeadOffice headOffice = getHeadOfficeInstance();
headOffice.setBalance(headOffice.getBalance() + amountWithCommission);
officeRepository.save(headOffice);
return "You have withrawn amount : $" + amount;
}
通过officeRepository进行手续费累加,这种方式有几个缺点:一,AtmController和HeadOffice紧耦合,ATM和Management限界上下文相互依赖;二,代码重复,如果其它位置需要扣除手续费的话势必要重复编码。第二种方式是在Atm类中执行相关逻辑:
public void takeMoney(float amount, HeadOffice headOffice) {
if (!canTakeMoney(amount).equals("")) {
throw new IllegalStateException();
}
Money output = moneyInside.allocate(amount);
moneyInside = moneyInside.substract(output);
float amountWithCommission = calculateAmountWithCommission(amount);
moneyCharged += amountWithCommission;
headOffice.setBalance(headOffice.getBalance() + amountWithCommission);
}
这种方式也许可以消除代码重复问题,但会带来其它问题:第一,两个限界上下文依旧紧耦合;第二,ATM中出现了其职责外的事件,这显然违背了单职责原则。如何解决?使用领域事件——ATM实体在取款时产生口扣费事件。Management界限上下文订阅事件,改变手续费字段。使用这种方式既避免了代码紧耦合,也消除了冗余代码。