DDD实战进阶第一波(十五):开发一般业务的大健康行业直销系统(总结篇)
前面我们花了14篇的文章来给大家介绍经典DDD的概念、架构和实践。这篇文章我们来做一个完整的总结,另外生成一个Api接口文档。
一.DDD解决传统的开发的几大问题:
- 没有描述需求的设计模型;而是直接通过数据库表的方式体现,也就是需求与设计是脱节的。
- 编码的架构也没有与设计和需求对应起来。
- 业务逻辑与技术混在一起;业务逻辑可能直接调用的数据访问,这样把业务逻辑与数据访问的技术混在一起。
- 开发没有层次感和节奏感;系统没有一个统一的约束,开发人员没有一个统一的节奏,这主要体现在随意的编码。
- Bug 定位困难:当系统出现业务异常行为时,无法快速准确的定位出现问题的位置,因为系统不同开发人员的代码放置随意性。
- 需求变更响应缓慢:在大型的系统或产品中,当需要增加功能或修改现有功能时,因为代码架构的随意性,可能会出现改了功能可能会影响到其他的功能,造成系统极不稳定。
解决软件设计与开发问题的套路就是领域驱动设计(简称 DDD)。DDD 这个套路能够灵活解决以上的问题,为我们提供一个好的设计、架构以及高质量的代码。
二.DDD解决之道:
DDD 方法首先是需要将需求分析后,形成一个反应需求的领域模型。领域模型就是大家平常理解的类、类的属性、类之间的关系等。当然在 DDD 中,为了更好的将领域模型反应需求,对类、类的属性、类之间的关系等有一些模式的指导。比如类的属性可能是一般属性,也可能是值对象;比如有关系的类之间是否是代表一个整体概念、有相同生命周期、需要统一持久化等。所以我们的领域模型除了能够跑通需求外,还要考虑聚合根、实体、值对象、聚合等概念的应用,这样领域模型的设计才能更好的反应需求,也能够更好的将设计对应成有约束力的代码。另外 DDD 也提供了大量模式,告诉我们应该如何编写对应设计的代码,能够将我们的代码真正映射到设计;如何进行业务逻辑与持久化机制的剥离;如何进行更好的架构设计等。
1.DDD能应对复杂性:系统复杂性主要体现在三个方面。一是技术维度,有业务代码的实现、有与数据库或其他持久化存储交互的实现、有消息队列的实现、有身份验证与授权的实现、有 WebAPI 暴露的实现等;二是业务维度,有太多的模块和功能需要去做;三是时间维度,需要快速的开发,快速的响应需求的变更,快速的修正 Bug。DDD应对复杂性主要通过三个方面:
- a. 技术维度:通过合理的架构分层,能够让每层关注自己的事情,比如领域层只关注业务逻辑的事情,仓储实现层只关注持久化数据与查询的事情,应用服务层只关注协调领域层与仓储实现层完成用例的事情,接口层只关注暴露给前端的事情。
- b. 业务维度:通过将大系统划分成多个界限上下文,可以让不同团队和不同人只关注当前上下文的开发。在当前界限上下文中的领域层、仓储实现层、应用服务层、接口层都与其他界限上下文独立开来,这样可以专注开发,并且在修改代码与发布产品时,影响面较小。
- c. 时间维度:通过敏捷式迭代快速验证,快速修正。
2.高效掌握DDD:
a. 熟悉概念:充分熟悉前面文章介绍的界限上下文、实体、值对象、领域服务、聚合、聚合根、仓储、应用服务、接口等。
b. 熟悉架构:充分熟悉前面文章介绍的经典DDD的架构。
c. 实践:前面文章从产品、经销商、订单三个界限上下文分析了需求、建立了领域模型、通过经典DDD架构实现了代码,需要你在实际项目中灵活的运用。
三.接口文档的生成
当我们已经做好了所有的接口后,需要生成WebApi在线的接口文档,便于前端人员进行查看与使用。.net core webapi中使用Swagger生成接口文档。
1.在WebApi项目中引入Nuget包:Swashbuckle.AspNetCore。
2.在WebApi项目属性的生成中,勾选“XML 文档文件”。此目的是可以包括WebApi中每个接口的注释。

3.在WebApi Startup.cs文件的ConfigureServices方法中,添加如下的代码:
//swagger接口文档的信息
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info
{
Version = "v1",
Title = "产品界限上下文接口文档",
Description = "包括产品界限上下文所有接口的描述",
Contact =new Contact {Name="曹剑",Email="malaoko@hotmail.com"}
});
//使用Xml文档中接口的注释
var basePath = ApplicationEnvironment.ApplicationBasePath;
var xmlPath = Path.Combine(basePath, "Product.WebApi.xml");
c.IncludeXmlComments(xmlPath);
});
4.在Configure方法中,添加如下的代码:
//制定swagger接口文档的访问url路径信息
app.UseSwagger();
app.UseSwaggerUI(p =>
{
p.SwaggerEndpoint("/swagger/v1/swagger.json", "Product接口");
});
5.修改Properties下的launchSettings.json文件中的两个launchUrl的值都改为swagger,这样在打开这个WebApi时,自动跳转到swagger帮助文件:
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Product.WebApi": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5000"
}
}
6.访问时,最终的效果如下图:

7.在点击每个接口时,可以看到详细的调用说明:

本系列的文章就到这里,这个系列的文章主要是讲解了经典DDD,关于CQRS DDD与微服务,可以继续关注我们后续的系列文章,也可以加入QQ群或关注我们的
微信公众号。在后续CQRS与微服务的内容中,我们将实现如下的架构
微服务架构:

CQRS架构:

QQ讨论群:309287205
DDD实战进阶视频请关注微信公众号:
DDD实战进阶第一波(十五):开发一般业务的大健康行业直销系统(总结篇)的更多相关文章
- DDD实战进阶第一波(十):开发一般业务的大健康行业直销系统(实现经销商登录仓储与逻辑)
上一篇文章主要讲了经销商注册的仓储和领域逻辑的实现,我们先把应用服务协调完成经销商注册这部分暂停一下,后面文章统一讲. 这篇文章主要讲讲经销商登录的仓储和相关逻辑的实现. 在现代应用程序前后端分离的实 ...
- DDD实战进阶第一波(一):开发一般业务的大健康行业直销系统(概述)
本系列文章 DDD实战进阶第一波(一):开发一般业务的大健康行业直销系统(概述) DDD实战进阶第一波(二):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架一) 近年来,关于如何开发基于 ...
- DDD实战进阶第一波(二):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架一)
要实现软件设计.软件开发在一个统一的思想.统一的节奏下进行,就应该有一个轻量级的框架对开发过程与代码编写做一定的约束. 虽然DDD是一个软件开发的方法,而不是具体的技术或框架,但拥有一个轻量级的框架仍 ...
- DDD实战进阶第一波(八):开发一般业务的大健康行业直销系统(业务逻辑条件判断最佳实践)
这篇文章其实是大健康行业直销系统的番外篇,主要给大家讲讲如何在领域逻辑中,有效的处理业务逻辑条件判断的最佳实践问题. 大家都知道,聚合根.实体和值对象这些领域对象都自身处理自己的业务逻辑.在业务处理过 ...
- DDD实战进阶第一波(三):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架二)
了解了DDD的好处与基本的核心组件后,我们先不急着进入支持DDD思想的轻量级框架开发,也不急于直销系统需求分析和具体代码实现,我们还少一块, 那就是经典DDD的架构,只有了解了经典DDD的架构,你才能 ...
- DDD实战进阶第一波(六):开发一般业务的大健康行业直销系统(实现产品上下文仓储与应用服务层)
前一篇文章我们完成了产品上下文的领域层,我们已经有了关于产品方面的简单领域逻辑,我们接着来实现产品上下文关于仓储持久化与应用层的用例如何来协调 领域逻辑与仓储持久化. 首先大家需要明确的是,产品上下文 ...
- DDD实战进阶第一波(九):开发一般业务的大健康行业直销系统(实现经销商上下文仓储与领域逻辑)
上篇文章主要讲述了经销商上下文的需求与POCO对象,这篇文章主要讲述该界限上下文的仓储与领域逻辑的实现. 关于界限上下文与EF Core数据访问上下文参考产品上下文相应的实现,这里不再累述. 因为在经 ...
- DDD实战进阶第一波(十一):开发一般业务的大健康行业直销系统(实现经销商代注册用例与登录令牌分发)
前两篇文章主要实现了经销商代注册的仓储与领域逻辑.经销商登录的仓储与相关逻辑,这篇文章主要讲述经销商代注册的用例与经销商登录的查询功能. 一.经销商代注册用例 在经销商代注册用例中,我们需要传递经销商 ...
- DDD实战进阶第一波(十三):开发一般业务的大健康行业直销系统(订单上下文领域逻辑)
前一篇文章主要讲了订单上下文的POCO模型,其中订单与订单项中有大量的值对象.这篇文章主要讲讲这些值对象以及订单项.订单相关的领域逻辑. 1.ProductSKUs值对象领域逻辑:ProductSKU ...
- DDD实战进阶第一波(四):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架三)
上一篇文章我们讲了经典DDD架构对比传统三层架构的优势,以及经典DDD架构每一层的职责后,本篇文章将介绍基础结构层中支持DDD的轻量级框架的主要代码. 这里需要说明的是,DDD轻量级框架能够体现DDD ...
随机推荐
- Android Studio 2.1及其以上版本中的instant run功能 介绍
Android Studio 2.0及其以后版本中的instant run功能 介绍 转 https://blog.csdn.net/zy987654zy/article/details/514961 ...
- Activity 切换效果
Activity 切换效果 设置Activity 的 启动/退出时动画效果. 1.设置动画 通过方法 overridePendingTransition(enterAnim:Int,exitAnim: ...
- scrapy递归解析和post请求
递归解析 递归爬取解析多页页面数据 每一个页面对应一个url,则scrapy工程需要对每一个页码对应的url依次发起请求,然后通过对应的解析方法进行作者和段子内容的解析. 实现方案: 1.将每一个页码 ...
- linux shell 发送qq邮件失败
安装 发送邮件功能 yum -y install postfix yum -y install mailx 使用 mail -s “fsfds” @qq.com < hh 第二次返回此信息 您在 ...
- yum的一些命令使用方法
yum 选项 参数 yum命令是在Fedora和RedHat以及SUSE中基于rpm的软件包管理器,它可以使系统管理人员交互和自动化地更细与管理RPM软件包,能够从指定的服务器自动下载RPM包并且安装 ...
- nodejs, 阿里oss上传下载图片
const archiver = require('archiver')const send = require('koa-send')const oss = require('ali-oss').W ...
- BZOJ3592 : Architext
首先特判多边形面积$=0$的情况,此时内部没有点,答案只会在顶点处取到. 对于面积$>0$的情况,离线询问,将所有多边形合在一起得到平面图,然后求出对偶图,那么每条多边形边的两侧分别对应对偶图中 ...
- mac效率工具
前言:在命令行中切换目录是最常用的操作,我相信一遍又一遍重复“cd ls cd ls cd ls ……”绝对会让你抓狂. 记录一下,方便下次系统重装,哈哈 一. oh-my-zsh mac 预装了 z ...
- js将一篇文章中多个连续的<br>标签替换成两个连续的<br>标签
写本文的目的是今天恰好有一个之前做SEO的同事问我怎样把一篇文章中多个连续的br标签替换成两个连续的br标签,这里就牵涉到SEO层面的问题了. 在做SEO优化的时候,其中有一个需要注意的地方就是尽量减 ...
- vue动态添加路由addRoutes之不能将动态路由存入缓存
在我不知道vue的路由还可以通过addRoutes动态添加时,我只知道vue的路由都是写死在路由表中的,每当跳转时再去加载相应的路由.直到在一个新公司接到需要根据用户的权限显示不同的菜单的需求时才知道 ...