DDD专题案例一《初识领域驱动设计DDD落地方案》

简介: DDD(Domain-Driven Design 领域驱动设计)是由Eric Evans最先提出,目的是对软件所涉及到的领域进行建模,以应对系统规模过大时引起的软件复杂性的问题。整个过程大概是这样的,开发团队和领域专家一起通过 通用语言(Ubiquitous Language)去理解和消化领域知识,从领域知识中提取和划分为一个一个的子领域(核心子域,通用子域,支撑子域),并在子领域上建立模型,再重复以上步骤,这样周而复始,构建出一套符合当前领域的模型。

前言介绍

DDD(Domain-Driven Design 领域驱动设计)是由Eric Evans最先提出,目的是对软件所涉及到的领域进行建模,以应对系统规模过大时引起的软件复杂性的问题。整个过程大概是这样的,开发团队和领域专家一起通过 通用语言(Ubiquitous Language)去理解和消化领域知识,从领域知识中提取和划分为一个一个的子领域(核心子域,通用子域,支撑子域),并在子领域上建立模型,再重复以上步骤,这样周而复始,构建出一套符合当前领域的模型。

0.jpg

开发目标

依靠领域驱动设计的设计思想,通过事件风暴建立领域模型,合理划分领域逻辑和物理边界,建立领域对象及服务矩阵和服务架构图,定义符合DDD分层架构思想的代码结构模型,保证业务模型与代码模型的一致性。通过上述设计思想、方法和过程,指导团队按照DDD设计思想完成微服务设计和开发。

1、拒绝泥球小单体、拒绝污染功能与服务、拒绝一加功能排期一个月

2、架构出高可用极易符合互联网高速迭代的应用服务

3、物料化、组装化、可编排的服务,提高人效

服务架构

1.jpg

  • 应用层{application}
  • 应用服务位于应用层。用来表述应用和用户行为,负责服务的组合、编排和转发,负责处理业务用例的执行顺序以及结果的拼装。
  • 应用层的服务包括应用服务和领域事件相关服务。
  • 应用服务可对微服务内的领域服务以及微服务外的应用服务进行组合和编排,或者对基础层如文件、缓存等数据直接操作形成应用服务,对外提供粗粒度的服务。
  • 领域事件服务包括两类:领域事件的发布和订阅。通过事件总线和消息队列实现异步数据传输,实现微服务之间的解耦。
  • 领域层{domain}
  • 领域服务位于领域层,为完成领域中跨实体或值对象的操作转换而封装的服务,领域服务以与实体和值对象相同的方式参与实施过程。
  • 领域服务对同一个实体的一个或多个方法进行组合和封装,或对多个不同实体的操作进行组合或编排,对外暴露成领域服务。领域服务封装了核心的业务逻辑。实体自身的行为在实体类内部实现,向上封装成领域服务暴露。
  • 为隐藏领域层的业务逻辑实现,所有领域方法和服务等均须通过领域服务对外暴露。
  • 为实现微服务内聚合之间的解耦,原则上禁止跨聚合的领域服务调用和跨聚合的数据相互关联。
  • 基础层{infrastructrue}
  • 基础服务位于基础层。为各层提供资源服务(如数据库、缓存等),实现各层的解耦,降低外部资源变化对业务逻辑的影响。
  • 基础服务主要为仓储服务,通过依赖反转的方式为各层提供基础资源服务,领域服务和应用服务调用仓储服务接口,利用仓储实现持久化数据对象或直接访问基础资源。
  • 接口层{interfaces}
  • 接口服务位于用户接口层,用于处理用户发送的Restful请求和解析用户输入的配置文件等,并将信息传递给应用层。

开发环境

1、jdk1.8【jdk1.7以下只能部分支持netty】

2、springboot 2.0.6.RELEASE

3、idea + maven

代码示例

1itstack-demo-ddd-01
 2└── src
 3    ├── main
 4    │   ├── java
 5    │   │   └── org.itstack.demo
 6    │   │       ├── application
 7    │   │       │    ├── event
 8    │   │       │    │   └── ApplicationRunner.java  
 9    │   │       │    └── service
10    │   │       │        └── UserService.java    
11    │   │       ├── domain
12    │   │       │    ├── model
13    │   │       │    │   ├── aggregates
14    │   │       │    │   │   └── UserRichInfo.java   
15    │   │       │    │   └── vo
16    │   │       │    │       ├── UserInfo.java   
17    │   │       │    │       └── UserSchool.java 
18    │   │       │    ├── repository
19    │   │       │    │   └── IuserRepository.java    
20    │   │       │    └── service
21    │   │       │        └── UserServiceImpl.java    
22    │   │       ├── infrastructure
23    │   │       │    ├── dao
24    │   │       │    │   ├── impl
25    │   │       │    │   │   └── UserDaoImpl.java    
26    │   │       │    │   └── UserDao.java    
27    │   │       │    ├── po
28    │   │       │    │   └── UserEntity.java 
29    │   │       │    ├── repository
30    │   │       │    │   ├── mysql
31    │   │       │    │   │   └── UserMysqlRepository.java
32    │   │       │    │   ├── redis
33    │   │       │    │   │   └── UserRedisRepository.java        
34    │   │       │    │   └── UserRepository.java 
35    │   │       │    └── util
36    │   │       │        └── RdisUtil.java
37    │   │       ├── interfaces
38    │   │       │    ├── dto
39    │   │       │    │   └── UserInfoDto.java    
40    │   │       │    └── facade
41    │   │       │        └── DDDController.java
42    │   │       └── DDDApplication.java
43    │   ├── resources    
44    │   │   └── application.yml
45    │   └── webapp    
46    │       └── WEB-INF
47    │            └── index.jsp   
48    └── test
49         └── java
50             └── org.itstack.demo.test
51                 └── ApiTest.java

演示部分重点代码块,完整代码下载关注公众号;bugstack虫洞栈 | 回复DDD落地

application/UserService.java | 应用层用户服务,领域层服务做具体实现

1/**
 2 * 应用层用户服务
 3 * 虫洞栈:https://bugstack.cn
 4 * 公众号:bugstack虫洞栈 | 欢迎关注并获取更多专题案例源码
 5 * Create by fuzhengwei on @2019
 6 */
 7public interface UserService {
 8
 9    UserRichInfo queryUserInfoById(Long id);
10
11}

domain/repository/IuserRepository.java | 领域层资源库,由基础层实现

1/**
 2 * 虫洞栈:https://bugstack.cn
 3 * 公众号:bugstack虫洞栈 | 欢迎关注并获取更多专题案例源码
 4 * Create by fuzhengwei on @2019
 5 */
 6public interface IUserRepository {
 7
 8    void save(UserEntity userEntity);
 9
10    UserEntity query(Long id);
11
12}

domain/service/UserServiceImpl.java | 应用层实现类,应用层是很薄的一层可以只做服务编排

1/**
 2 * 虫洞栈:https://bugstack.cn
 3 * 公众号:bugstack虫洞栈 | 欢迎关注并获取更多专题案例源码
 4 * Create by fuzhengwei on @2019
 5 */
 6@Service("userService")
 7public class UserServiceImpl implements UserService {
 8
 9    @Resource(name = "userRepository")
10    private IUserRepository userRepository;
11
12    @Override
13    public UserRichInfo queryUserInfoById(Long id) {
14
15        // 查询资源库
16        UserEntity userEntity = userRepository.query(id);
17
18        UserInfo userInfo = new UserInfo();
19        userInfo.setName(userEntity.getName());
20
21        // TODO 查询学校信息,外部接口
22        UserSchool userSchool_01 = new UserSchool();
23        userSchool_01.setSchoolName("振华高级实验中学");
24
25        UserSchool userSchool_02 = new UserSchool();
26        userSchool_02.setSchoolName("东北电力大学");
27
28        List<UserSchool> userSchoolList = new ArrayList<>();
29        userSchoolList.add(userSchool_01);
30        userSchoolList.add(userSchool_02);
31
32        UserRichInfo userRichInfo = new UserRichInfo();
33        userRichInfo.setUserInfo(userInfo);
34        userRichInfo.setUserSchoolList(userSchoolList);
35
36        return userRichInfo;
37    }
38
39}

infrastructure/po/UserEntity.java | 数据库对象类

1/**
 2 * 数据库实体对象;用户实体
 3 * 虫洞栈:https://bugstack.cn
 4 * 公众号:bugstack虫洞栈 | 欢迎关注并获取更多专题案例源码
 5 * Create by fuzhengwei on @2019
 6 */
 7public class UserEntity {
 8
 9    private Long id;
10    private String name;
11
12    get/set ...
13}

infrastructrue/repository/UserRepository.java | 领域层定义接口,基础层资源库实现

1/**
 2 * 虫洞栈:https://bugstack.cn
 3 * 公众号:bugstack虫洞栈 | 欢迎关注并获取更多专题案例源码
 4 * Create by fuzhengwei on @2019
 5 */
 6@Repository("userRepository")
 7public class UserRepository implements IUserRepository {
 8
 9    @Resource(name = "userMysqlRepository")
10    private IUserRepository userMysqlRepository;
11
12    @Resource(name = "userRedisRepository")
13    private IUserRepository userRedisRepository;
14
15    @Override
16    public void save(UserEntity userEntity) {
17        //保存到DB
18        userMysqlRepository.save(userEntity);
19
20        //保存到Redis
21        userRedisRepository.save(userEntity);
22    }
23
24    @Override
25    public UserEntity query(Long id) {
26
27        UserEntity userEntityRedis = userRedisRepository.query(id);
28        if (null != userEntityRedis) return userEntityRedis;
29
30        UserEntity userEntityMysql = userMysqlRepository.query(id);
31        if (null != userEntityMysql){
32            //保存到Redis
33            userRedisRepository.save(userEntityMysql);
34            return userEntityMysql;
35        }
36
37        // 查询为NULL
38        return null;
39    }
40
41}

interfaces/dto/UserInfoDto.java | DTO对象类,隔离数据库类

1/**
 2 * 虫洞栈:https://bugstack.cn
 3 * 公众号:bugstack虫洞栈 | 欢迎关注并获取更多专题案例源码
 4 * Create by fuzhengwei on @2019
 5 */
 6public class UserInfoDto {
 7
 8    private Long id;        // ID
 9
10    public Long getId() {
11        return id;
12    }
13
14    public void setId(Long id) {
15        this.id = id;
16    }
17
18}

interfaces/facade/DDDController.java | 门面接口

1/**
 2 * 虫洞栈:https://bugstack.cn
 3 * 公众号:bugstack虫洞栈 | 欢迎关注并获取更多专题案例源码
 4 * Create by fuzhengwei on @2019
 5 */
 6@Controller
 7public class DDDController {
 8
 9    @Resource(name = "userService")
10    private UserService userService;
11
12    @RequestMapping("/index")
13    public String index(Model model) {
14        return "index";
15    }
16
17    @RequestMapping("/api/user/queryUserInfo")
18    @ResponseBody
19    public ResponseEntity queryUserInfo(@RequestBody UserInfoDto request) {
20        return new ResponseEntity<>(userService.queryUserInfoById(request.getId()), HttpStatus.OK);
21    }
22
23}

综上总结

  • 以上基于DDD一个基本入门的结构演示完成,实际开发可以按照此模式进行调整。
  • 目前这个架构分层还不能很好的进行分离,以及层级关系的引用还不利于扩展。
  • 后续会持续完善以及可以组合搭建RPC框架等,让整个架构更利于互联网开发。
目录
相关文章
|
前端开发 架构师 搜索推荐
COLA 4.0:直击应用架构本质的最佳实践
COLA 4.0:直击应用架构本质的最佳实践
4205 0
COLA 4.0:直击应用架构本质的最佳实践
|
Linux 网络安全 Android开发
|
索引 存储 数据库
数据库设计规范
基于阿里数据库设计规范扩展而来
52064 4
|
算法 关系型数据库 MySQL
TiDB保证数据一致性的策略与优势
【2月更文挑战第28天】TiDB作为一款分布式数据库,通过其独特的策略和优势,确保在分布式环境下数据的一致性。本章将详细探讨TiDB保证数据一致性的核心策略,包括其采用的分布式一致性协议、数据复制机制以及容错处理等方面,并阐述这些策略所带来的优势。通过理解TiDB的数据一致性保证机制,读者将能更深入地认识其作为分布式数据库的价值。
|
8月前
|
开发框架 Java 测试技术
领域驱动设计(DDD)在中小型项目中的落地实践
本文探讨领域驱动设计(DDD)在中小型项目中的落地实践,涵盖核心概念如领域模型、聚合、限界上下文与事件驱动架构,并结合电商订单系统案例,展示分层架构、仓储模式与领域服务的实际应用,助力团队构建高内聚、易维护的业务系统。
1477 10
|
设计模式 架构师 Java
一文详谈领域驱动设计实践
本文作者结合在团队的实践过程,分享了自己对领域驱动设计的一些思考。
1010 9
|
设计模式 Java 程序员
【23种设计模式·全精解析 | 概述篇】设计模式概述、UML图、软件设计原则
本系列文章聚焦于面向对象软件设计中的设计模式,旨在帮助开发人员掌握23种经典设计模式及其应用。内容分为三大部分:第一部分介绍设计模式的概念、UML图和软件设计原则;第二部分详细讲解创建型、结构型和行为型模式,并配以代码示例;第三部分通过自定义Spring的IOC功能综合案例,展示如何将常用设计模式应用于实际项目中。通过学习这些内容,读者可以提升编程能力,提高代码的可维护性和复用性。
4127 1
【23种设计模式·全精解析 | 概述篇】设计模式概述、UML图、软件设计原则
|
消息中间件 测试技术 领域建模
DDD - 一文读懂DDD领域驱动设计
DDD - 一文读懂DDD领域驱动设计
51811 6
|
机器学习/深度学习 算法 数据挖掘
技术视界|多模态说话人开源项目3D-Speaker
技术视界|多模态说话人开源项目3D-Speaker