编辑推荐: |
本文来自于简书,本文主要重点聊聊战术设计,如何通过它,指导我们的编码,着眼于单个界限上下文。
|
|
战术设计
在DDD中,分两部分,战略设计和战术设计,战略设计很好的帮助我们理清问题域,划分服务。
在战术部分,DDD有很多的概念,这里我们聊聊一些重要的概念,各个概念所在层级和调用关系如下:
应用服务
很薄的一层, 与业务用例一一对应,非CRUD
协调代理的作用
其本身不包含业务逻辑
可以作为事务的边界
@Service
public class UserApplicationService {
private static Logger logger = LoggerFactory.getLogger(UserApplicationService.class);
@Autowired
private UserRepository userRepository;
@Autowired
private EmailService emailService;
@Autowired
private RegisterService registerService;
@Transactional
public String register(RegisterCommand command)
{
User user = registerService.createUser(command.getOwnerEmail(),
command.getPolicyNumber());
String uuid = user.getUuid();
userRepository.save(user);
emailService.sendEmail(uuid);
logger.info("Create user with email [{}]",
command.getOwnerEmail());
return uuid;
}
@Transactional
public void initPassword(InitPasswordCommand
command) {
User user = userRepository.findByUuid(command.getUuid());
user.initPassWord(command.getPassword());
logger.info("Set password with uuid[{}]",
command.getUuid());
userRepository.save(user);
}
} |
聚合
那业务逻辑到底放在什么地方呢?
聚合是一组相关领域对象,其目的是要确保业务规则在领域对象的各个生命周期都得以执行。
如图,每个聚合都有聚合根,它具备如下的一些特征:
核心领域对象,高度内聚。
其内部的所有业务操作都必须经过聚合根,对外提供一致性的边界。
聚合根之间的数据一致性一般通过最终一致性来保证。
//Good
order.removeItem(item);
//Bad
List<Item> items = order.getItems();
items.remove(item); |
领域对象
它包括实体(Entity)和值对象(Value Object)实体
具有唯一标识
持久化
具有生命周期
通过ID判断相等性
可变
值对象
无唯一标识
用完就丢,主要起描述性作用
通过属性判断相等性,实现Equals方法
不可变
领域服务
有时领域逻辑放在领域对象上面不合适的情况,这时我们将逻辑放在领域服务里面,下图展示了领域服务和应用服务的区别:
资源库
DDD中的持久化组件,也是聚合根的集合,它屏蔽了底层的数据获取细节,分离业务复杂度和数据库操作带来的技术复杂度。注意:只对聚合根建立对应的资源库;不要将事务放在这一层。
public interface
UserRepository {
void save(User user);
User findByUuid(String uuid);
User findByEmail(String email);
boolean existByEmail(String email);
} |
领域事件
An event is something that has happened in the past.
领域专家所关心的具有显著业务意义的事件,或者是需要发布到另一个界限上下文的事件以实现最终一致性。
常在应用服务或者资源库中发布领域事件:
@Service
public class PolicyApplicationService {
private PolicyRepository policyRepository;
private DomainEventPublisher domainEventPublisher;
@Autowired
public PolicyApplicationService(PolicyRepository
policyRepository, DomainEventPublisher domainEventPub
lisher) {
this.policyRepository = policyRepository;
this.domainEventPublisher = domainEventPublisher;
}
@Transactional
public void renew(RenewCommand renewCommand)
{
Policy policy = policyRepository.byPolicyNumber(renewCommand.getPoli
cyNumber());
policy.updateStatus(renewCommand);
policyRepository.save(policy);
PolicyRenewedEvent domainEvent =
new PolicyRenewedEvent(renewCommand.getPolicyNumber(),
renewCommand.getCardNumber(), renewCommand.getPrice());
domainEventPublisher.publish(domainEvent);
}
} |
总结
DDD中的概念很多,但这些在面向对象编程里面,或多或少都接触过,对这些概念的掌握,可以方便我们了解各个层级和领域对象的职责,下次我们可以继续过下DDD中常见的架构模式,比如:四层架构,六边形架构,洋葱模型,Clean架构等
|