美文网首页Think Coding微服务架构与应用电商体系
领域驱动设计: 构建你的代码蓝图

领域驱动设计: 构建你的代码蓝图

作者: 魔镜的技术心经 | 来源:发表于2018-09-13 22:07 被阅读67次

    战术设计

    在DDD中,分两部分,战略设计和战术设计,战略设计很好的帮助我们理清问题域,划分服务,具体可参见: https://www.jianshu.com/p/96801c93a47d。今天我们重点聊聊战术设计,如何通过它,指导我们的编码,着眼于单个界限上下文。

    概念篇

    在战术部分,DDD有很多的概念,这里我们聊聊一些重要的概念,各个概念所在层级和调用关系如下:


    image.png

    应用服务

    • 很薄的一层, 与业务用例一一对应,非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);
        }
    
    }
    

    聚合

    那业务逻辑到底放在什么地方呢?

    聚合是一组相关领域对象,其目的是要确保业务规则在领域对象的各个生命周期都得以执行。

    image.png
    如图,每个聚合都有聚合根,它具备如下的一些特征:
    • 核心领域对象,高度内聚。
    • 其内部的所有业务操作都必须经过聚合根,对外提供一致性的边界。
    • 聚合根之间的数据一致性一般通过最终一致性来保证。
    //Good
    order.removeItem(item);
    
    //Bad
    List<Item> items = order.getItems();
    items.remove(item);
    

    领域对象

    它包括实体(Entity)和值对象(Value Object)

    • 实体

      • 具有唯一标识
      • 持久化
      • 具有生命周期
      • 通过ID判断相等性
      • 可变
    • 值对象

      • 无唯一标识
      • 用完就丢,主要起描述性作用
      • 通过属性判断相等性,实现Equals方法
      • 不可变

    领域服务

    有时领域逻辑放在领域对象上面不合适的情况,这时我们将逻辑放在领域服务里面,下图展示了领域服务和应用服务的区别:


    image.png

    资源库

    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 domainEventPublisher) {
            this.policyRepository = policyRepository;
            this.domainEventPublisher = domainEventPublisher;
        }
    
        @Transactional
        public void renew(RenewCommand renewCommand) {
            Policy policy = policyRepository.byPolicyNumber(renewCommand.getPolicyNumber());
            policy.updateStatus(renewCommand);
            policyRepository.save(policy);
            PolicyRenewedEvent domainEvent =
                    new PolicyRenewedEvent(renewCommand.getPolicyNumber(), renewCommand.getCardNumber(), renewCommand.getPrice());
            domainEventPublisher.publish(domainEvent);
        }
    }
    

    总结

    DDD中的概念很多,但这些在面向对象编程里面,或多或少都接触过,对这些概念的掌握,可以方便我们了解各个层级和领域对象的职责,下次我们可以继续过下DDD中常见的架构模式,比如:四层架构,六边形架构,洋葱模型,Clean架构等


    image.png

    相关文章

      网友评论

        本文标题:领域驱动设计: 构建你的代码蓝图

        本文链接:https://www.haomeiwen.com/subject/lzbwgftx.html