如果我看得更远,那是因为我站在巨人的肩膀上。(If I have seen further it is by standing on ye shoulder of Giants.)
                                                                                                                                                                                                                    Newtown,I. 1676
DDD:指领域驱动设计,是domain driven design的缩写。
介绍DDD基础知识的相关文章很多,本文就不普及相关的基础知识了,基础理论知识可参考如下文章:

1. 初识DDD

脚本式编程(dao+service)与DDD领域驱动模式区别如下:
其每一层的作用范围和含义如下:
1)展现层(Presentation Layer):负责以Restful的格式接受Web请求,然后将请求路由给Application层执行,并返回视图模型(View Model),其载体通常是DTO(Data Transfer Object);
2)应用层(Application Layer):主要负责获取输入,组装上下文,做输入校验,调用领域层做业务处理,如果需要的话,发送消息通知。当然,层次是开放的,若有需要,应用层也可以直接访问基础实施层;
3)领域层(Domain Layer):主要是封装了核心业务逻辑,并通过领域服务(Domain Service)和领域对象(Entities)的函数对外部提供业务逻辑的计算和处理;
4)基础实施层(Infrastructure Layer)主要包含Tunnel(数据通道)、防腐层,Config和Common。这里我们使用Tunnel这个概念来对所有的数据来源进行抽象,这些数据来源可以是数据库(MySQL,NoSql)、搜索引擎、文件系统、也可以是SOA服务等;Config负责应用的配置;Common是通用的工具类。
常见的领域驱动业务调用链过程如下图所示:

 调用过程大致如下:

  1. 业务调用方基于网关传入DTO数据,为了便于区分业务场景,将DTO数据又细分为CQE三种模式的数据。
  2. 业务数据传入后,基于Spring Validation等模式做基础数据验证(如必填,格式,大小等基础验证);
  3. 数据进入到Controller层,并调用应用层相关的应用功能;
  4. 应用层不做具体的业务实现,只做编排处理,做业务的流程处理。应用层可做如下操作:
  • 应用层调用防腐层查询其他系统的数据;
  • 应用层调用仓库层查询本系统相关的数据;
  • 应用层调用工厂创建实体(简单实体,可在应用层直接生成);
  • 应用层调用第三方领域服务,实体或聚合根的方法处理业务逻辑;
  • 应用层调用仓库层保存数据;
  1. 工厂创建实体,简单的实体可不基于工厂创建;
  2. 领域层处理实体的行为,核心业务逻辑处理放在领域层,领域层可调用基础层的所有模块处理业务(领域层原则上不直接调用仓库层保存数据,保存数据应该放在应用层调用);
  3. 仓库实现层最终落地数据,进行数据存储(其他层不能直接与Tunnel(数据通道)交互,必须基于仓库层才可以);
  4. 一个业务行为结束后,若产生副作用,再应用层发出事件通知,其他模块再监听处理。(事件归属应用层还是领域层,网上各有不同的方案,本例是放在应用层。领域层本身只是内存化操作。等一个实体行为真正数据存储成功后,再发出事件,便于理解和维护。)

2. 巨人的肩膀

作者接触DDD相关知识,是从一篇名为《一文教会你如何写复杂业务的代码》的文章开始的。带着好奇,越看越有共鸣,初步发现了DDD的神奇之处并一发不可收拾,开始入坑DDD领域驱动设计。在查看DDD各种教程博客时,综合对比并摒弃一些低质量的博客,强烈推荐以下两位老师的系列教程。
阿里-张建飞:张老师的新书《代码精进之路》。
阿里-殷浩:
  1. 《DDD系列第一讲》
  2. 《DDD系列第二讲: 应用架构》
  3. 《DDD系列第三讲:Repository模式》
  4. 《DDD系列第四讲:领域层设计规范》
  5. 《DDD系列第五讲:如何避免写流水账代码》

3. 为什么要写DDD系列博客

在初步了解了DDD的相关知识后,作者的第一感受是:DDD概念很多,各种专业术语,一堆下来还有点复杂,看了理论知识,还是云里雾里。看了诸多理论博客,总结一句就是:“听君一席话,如是一席话”。似乎明白了,又似乎还是什么都不懂。
经过第一轮的理论知识打击后,作者决定还是继续学习。既然理论知识太多,那就在实践中去寻找真理。
DDD到底应该怎样落地?
网上介绍DDD理论知识的相关文章很多,但真正介绍DDD如何应用在项目中的高质量技术文章就凤毛麟角了,更别提有完整示例的项目了。在这个探索的过程中,作者发现了殷浩的系列DDD教程,张建飞的COLA 4.0开源项目。
为了更透彻的掌握DDD相关的知识细节,并考虑落地DDD模式到公司的项目,还是没有采用开源项目COLA 4.0。作者选择通过殷浩老师的系列教程,一步一步开始DDD的探索之路。
适逢公司刚好存在一个老项目急需改造,老系统是基于(dao+service)脚本式编程开发的。由于时间较远且不同时间段由不同的开发人员维护,这种老代码,呵呵呵,懂的都懂。团队讨论决定就用这个项目来做DDD的落地。
虽然一开始看了很多理论知识文档,一些技术实现细节文档。但在编写初版本的DDD设计文档时,依旧发现特别的别扭,总感觉很奇怪。本质原因还是缺乏DDD设计经验,并且对DDD的各个知识点,分层细节理解不够深入。在这个迷茫阶段,作者抱着试一试的心态,尝试加了殷浩老师的钉钉,所幸他同意了。后续就是请教学习了,请教各种理论细节的实现和注意事项。在这个过程中,有以下几点感想:
  1. 深入理解理论知识,需要落地去反复的验证,总结出来的理论知识一般具有高度的概括性,为什么是这样,不这样会如何往往需要自己去验证;
  2. 自以为已经明白了理论知识,但在实际项目使用中,却是错误的使用,比如仓库层,领域层的一些细节问题;
  3. DDD落地困难的点还在于实现一个功能可以有不同的模式,这些模式不一定都对,但从功能实现层面来说却是都可以完成功能。比如,你在领域层直接调用仓库层保存数据,但领域层本身只是做纯内存化的业务逻辑处理,领域层是不可直接操作数据的。诸如此类的问题,导致不同的人对DDD理解不同,实现模式也不同。由于每一层的标准,实现方案不完全不同,才导致了DDD落地的复杂性。
  4. DDD做设计时,不单是对领域层做业务设计,应该是拉通整个流程一起做设计。
  5. 实体,聚合根,这些概念在实际项目中落地到具体的业务场景时,需要反复的迭代设计。
  6. 规范无处不在,注重编程细节,小到名命,大到使用设计模式,都需要规范编码。DDD在不同的层面,需要开发人员更加注重规范,不可张冠李戴,错误如:在仓库层里面写业务逻辑。
  7. 特别感谢殷浩老师的耐心指导,技术人传道授业,简单而纯粹。这份技术人独有的编码情怀和工匠精神,很帅。
本文旨在为使用或学习DDD模式的同行者,提供一个快速的入门案例(案例gitHub地址),抛砖引玉,共同学习。目前网上还缺乏完善的DDD设计案例,本着相互探讨和学习的思想,现基于实际的案例,在脱敏处理后,详述DDD从理论到落地的流程。大致分为以下模块:
  1. 《DDD领域设计-案例-需求说明文档》
  2. 《DDD领域设计-案例-建模设计说明》
  3. 《DDD领域设计-项目目录结构说明》
  4. 《DDD领域设计-案例-源码使用说明》
  5. 《DDD领域设计-设计规范》
特别说明DDD落地的方案没有统一的标准,本系列文章采用的技术方案也不一定能完全实现DDD的思想。由于作者水平有限,在一些理解上面若出现偏差,欢迎指导和批评。

DDD领域驱动设计-概述-Ⅰ的更多相关文章

  1. 浅谈我对DDD领域驱动设计的理解

    从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品 ...

  2. DDD 领域驱动设计-商品建模之路

    最近在做电商业务中,有关商品业务改版的一些东西,后端的架构设计采用现在很流行的微服务,有关微服务的简单概念: 微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独 ...

  3. DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)

    上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(2)> 这篇文章主要是对 DDD.Sample 框架增加 Transa ...

  4. DDD 领域驱动设计-两个实体的碰撞火花

    上一篇:<DDD 领域驱动设计-领域模型中的用户设计?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 在 ...

  5. DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(2)

    上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(1)> 阅读目录: 抽离 IRepository 并改造 Reposi ...

  6. DDD 领域驱动设计-领域模型中的用户设计

    上一篇:<DDD 领域驱动设计-如何控制业务流程?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新,并增加了 ...

  7. DDD 领域驱动设计-如何控制业务流程?

    上一篇:<DDD 领域驱动设计-如何完善 Domain Model(领域模型)?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sa ...

  8. DDD 领域驱动设计-如何完善 Domain Model(领域模型)?

    上一篇:<DDD 领域驱动设计-如何 DDD?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 阅读目录: ...

  9. DDD领域驱动设计之领域服务

    1.DDD领域驱动设计实践篇之如何提取模型 2.DDD领域驱动设计之聚合.实体.值对象 3.DDD领域驱动设计之领域基础设施层 什么是领域服务,DDD书中是说,有些类或者方法,放实体A也不好,放实体B ...

随机推荐

  1. 解决FTPClient下载网络文件线程挂起问题

    今天在windows上调试FTP下载文件时,出险线程假死,代码如下: if (inputStream != null) { byte[] data = null; ByteArrayOutputStr ...

  2. JDBC管理事务

    一.事务概念:打包一起的多个步骤的业务操作,要么同事成功,要么同时失败,则需要用事务管理: 二.代码实现

  3. Windows中nginx多次启动的问题

    在Windows上做开发环境中的nginx服务器.为了使nginx在后台运行,使用如下命令来启停nginx: cd <nginx安装目录> # 开启nginx并在后台运行 start ng ...

  4. [第十二篇]——Docker Dockerfile之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker Dockerfile 什么是 Dockerfile? Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明. 使用 Dockerfile 定制 ...

  5. 多线程run()方法是不能够被直接调用的

    操作系统线程的五种状态: 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于"可运行 ...

  6. 深入学习Composer原理(一)

    Composer作为PHP的包管理工具,为PHPer们提供了丰富的类库,并且让PHP重焕新生,避免被时代淘汰的悲剧.可以说,Composer和PHP7是现在PHP开发者的标配,如果你还没用过Compo ...

  7. 学习PHP中的国际化功能来查看货币及日期信息

    做为一门在世界范围内广泛使用的编程语言,国际化能力往往是衡量一个编程语言是否能够大范围流行的重要内容.特别是对于 PHP 这种以 Web 页面编程为主战场的语言来说,国际化能力更是重中之重.在 PHP ...

  8. ecshop增加调用字段问题汇总

    一.ecshop文章列表页调用缩略图.网页描述等 打开includes/lib_article.php文件,大约在69行 添加 $arr[$article_id]['description'] = $ ...

  9. Linux系列(4) - 目录处理命令(1)

    前言 linux中一切皆文件.目录为目录文件,普通文件用来保存数据,目录文件用来保存文件 建立目录:mkdir mkdir -p [目录名] -p 递归创建目录,例子:mkdir -p LinuxTe ...

  10. Windows 10 64位操作系统 下安装、连接测试sqlite3 sql基本操作 增删改

    一.下载sqlite安装包 1:详细下载安装版本可见官网:https://www.sqlite.org/download.html 2:百度盘分享连接:https://pan.baidu.com/s/ ...