而Domain Service只需要调用Domain Entity对象完成业务逻辑。
public class MoneyTransferServiceDomainModelImpl implements MoneyTransferService { private AccountRepository accountRepository; private BankingTransactionRepository bankingTransactionRepository; . . . @Override public BankingTransaction transfer( String fromAccountId, String toAccountId, double amount) { Account fromAccount = accountRepository.findById(fromAccountId); Account toAccount = accountRepository.findById(toAccountId); . . . fromAccount.debit(amount); toAccount.credit(amount); BankingTransaction moneyTransferTransaction = new MoneyTranferTransaction(fromAccountId,toAccountId,amount); bankingTransactionRepository.addTransaction(moneyTransferTransaction); return moneyTransferTransaction; }}
通过DDD重构后,虽然类的数量比以前多了一些,但是每个类的职责更加单一,代码的可读性和可扩展性也随之提高。
7.3 数据驱动和领域驱动
7.3.1 数据驱动
目前主流的开发模式是由数据驱动的。数据驱动的开发很容易上手,
有了业务需求,创建数据库表,然后编写业务逻辑,开发过程如图7-1所示。数据驱动以数据库为中心,其中最重要的设计是数据模型,但随着业务的增长和项目的推进,软件开发和维护的难度会急剧增加。
以客户关系管理(Customer Relationship Management,CRM)为例,其中很重要的概念有销售、机会、客户、私海、公海,实体的定义分别如下。
- 销售(Sales):公司的销售人员,一个销售可以拥有多个销售机会。
- 机会(Opportunity):销售机会,每个机会包含至少一个客户信息,且归属于一个销售人员。
- 客户(Customer):客户,也就是销售的对象。
- 私海(Private sea):专属于某个销售人员的领地(Territory),私海里面的客户,其他销售人员不能触碰。
- 公海(Public sea):公共的领地,所有销售人员都可以从公海里捡入客户到其私海。
按照我们曾经学习的数据库建模理论,对于上面的场景,不难画出图7-2所示的实体联系(Entity Relationship,ER)图。
可以看到,图7-2所示的ER图中不存在公海和私海,因为所谓的机会在私海,就是这个机会是不是归属某个销售,这样我们只需要看机会上是否有salesId。如果有,说明机会被某个销售占有,也就是在私海中;反之,这个机会就在公海中。
在这种开发模式下,最后的产出是几张数据库表,以及针对表中数据进行操作的事务脚本,如图7-3所示。