限界上下文已经定义了,接下来是实现追踪用户银行卡手续费,首先是ApllicationService的AtmController:
@PutMapping("/{id}/{amount}")@ResponseBodypublic 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()) returnatm.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界限上下文订阅事件,改变手续费字段。使用这种方式既避免了代码紧耦合,也消除了冗余代码。
