当前位置:网站首页>Implementing DDD based on ABP
Implementing DDD based on ABP
2022-07-31 15:47:00 【DotNET cross-platform】
什么是DDD呢?领域驱动设计[DDD]是一种针对复杂需求的软件开发方法.将软件实现与不断发展的模型联系起来,专注于核心领域逻辑,而不是基础设施细节.DDD适用于复杂领域和大规模应用,而不是简单的CRUD应用.它有助于建立一个灵活、模块化和可维护的代码库.
1.《Implementing Domain Driven Design》电子书: https://url39.ctfile.com/f/2501739-610635606-674948?p=2096(访问密码:2096)
2.《基于ABP Framework实现领域驱动设计》电子书: https://url39.ctfile.com/f/2501739-610635608-94e753?p=2096(访问密码:2096)
3.《Mastering ABP Framework》电子书: https://url39.ctfile.com/f/2501739-610635610-9a8f66?p=2096(访问密码:2096)
一.DDD中的领域层和应用层相关概念
DDD主要关注领域层和应用层.
1.DDD中的领域层
领域层中的基本概念有:
(1)实体[Entity]
实体就像面向对象中的对象,它包含属性和方法,并且有唯一的ID.
(2)值对象[Value Object]
值对象是领域中类型的领域对象.这听起来很抽象,举个例子就明白了.比如,订单Order这个聚合根由一系列的属性构成:唯一标识ID、OrderDate、OrderItems、Address等.其中Address就是一个值对象.值对象=值+对象=将一个值用对象的方式进行表述,来表达一个具体的固定不变的概念.
(3)聚合[Aggregate]和聚合根[Aggregate Root]⼀个聚合是一系列对象[实体和值对象]的集合,通过聚合根将所有关联对象绑定在⼀起.比如,Issue聚合是由Issue[聚合根]、Comment[实体]和IssuelLabel[值对象]组成的集合.
(4)仓储[Repository]
仓储接口定义在领域层,实现在基础设施层.为什么需要仓储呢?主要就是解耦数据库,把增删查改等数据库操作和不同类型的数据库解耦.DDD通用原则之一就是数据库独立性原则,领域层和应用层只依赖于仓储接口,并且仓储接口不适合使用用任何ORM特殊对象.
(5)领域服务[Domain Service]
领域服务封装了核心的业务逻辑,它对同一个实体的一个或多个方法进行组合和封装,或对多个不同实体的操作进行组合或编排,对外暴露成领域服务.
(6)规约[Specification]
规约是⼀个命名的、可重⽤的、可组合的和可测试的类,⽤于根据业务规则过滤领域对象.
(7)领域事件[Domain Event]
通过消息队列的方式,比如RabbitMQ等,实现一个特定的领域事件发生时,会通知其它的服务.
2.DDD中的应用层
应用层中的基本概念有:
(1)应用服务[Application Service]
通常应用服务层的输入和输出都是DTO,并且一个应用服务通常被认为是一个事务.
(2)数据传输对象[DTO]
目的主要是解耦应用服务层和展示层.如果没有DTO,那么应用服务层返回的是完整的对象,包含了展示层并不需要的字段,并且也可能泄露了对象字段信息.
(3)工作单元[Unit Of Work]
简单理解就是要么全部成功,要么全部失败.
二.基于ABP模板创建的解决方案结构
基于ABP模板创建的解决方案结构如下所示:1.领域层
(1)IssueTracking.Domain[领域层]:该项⽬包含实体、值对象、领域服务、规约、仓储接⼝等.(2)IssueTracking.Domain.Shared[领域共享层]:通常定义的常量和枚举,都放在该项⽬中.
2.应用层
(1)IssueTracking.Application.Contracts[应用契约层]:包含应用服务接口和数据传输对象.该项⽬被应⽤程序客户端引用,比如Web项目、API客户端项目.(2)IssueTracking.Application[应用层]:实现在Contracts项目中定义的接⼝.
3.展示层
(1)IssueTracking.Web[展示层]:这个是前后端不分离的项目命名方式,那么通常是一个ASP.NET Core MVC/Razor Pages应用.
说明:如果是前后端分离的项目,在解决方案中不会包含该项目,而是通过IssueTracking.HttpApi.Host项目提供HTTP API服务,供客户端调用.
4.远程服务层
(1)IssueTracking.HttpApi[远程服务层]:简单理解就是很薄的控制层,该项目主要用于定义HTTP API,即应用服务层的包装器,将它们公开给远程客户端调用.
(2)IssueTracking.HttpApi.Client[远程服务代理层]:当第三方客户端引用该项目时,就可以直接通过依赖注入使用远程服务应用,通过基于ABP的动态C#客户端API代理系统来实现的.
5.基础层
(1)IssueTracking.EntityFrameworkCore:EF Core核心基础依赖项目,包含数据上下文、数据库映射、EF Core仓储实现等.
(2)IssueTracking.EntityFrameworkCore.DbMigrations:用于管理Code First数据迁移的特殊的工具项目.最新ABP中已经移除了该项目,不用了解了.
6.其它层
(1)IssueTracking.DbMigrator:控制台应用程序,主要是迁移数据库结构并初始化种子数据.
三.解决方案中项目依赖关系
该解决方案中项目之间的依赖关系如下:1.Domain.Shared
所有项目直接或间接依赖此项目,此项目中的所有类型都可以被其它项目所引用
2.Domain
仅依赖Domain.Shared项目.
3.Application.Contracts
依赖Domain.Shared项目,可以在DTO中复用Domain.Shared中的类型.
4.Application
依赖Application.Contracts项目,因为此项目需要实现应用服务的接口及接口使用的DTO.另外也依赖Domain项目,因为在应用服务中使用仓储接口或领域对象.
5.EntityFrameworkCore
依赖Domain项目,因为此项目需要将领域对象[实体或值对象]映射到数据库的表,另外还需要实现Domain项目中的仓储接口.
6.HttpApi
依赖Application.Contracts项目,因为Controllers需要注入应用服务接口.
7.HttpApi.Client
依赖Application.Contracts项目,因为此项目需要使用应用服务接口.
8.Web
依赖HttpApi项目,发布定义的HTTP API.另外也间接依赖Application.Contracts项目,可以在页面/组件中使用应用服务.
看上面解决方案依赖关系图的虚线部分,就会发现Web项目依赖于Application和EntityFrameworkCore项目.这是因为Web是一个可部署的项目,在应用时需要应用服务和仓储的实现.这样框架设计的一个弊端就是在展示层中是可以使用实体和EF Core对象的,但这是严格避免的.
四.DDD应用程序执行流程
第1步:无论是浏览器中的Web Application,还是远程客户端,它们发起HTTP请求到服务器.
第2步:MVC UI或者HTTP API接收并处理请求,在这个阶段执行AOP逻辑,比如授权、输入验证、异常处理、审计日志、缓存等.MVC Controller在构造函数中注入应用服务接口,调用方法发送和接收DTO对象.
第3步:应用服务使用领域层的对象[实体、仓储接口、领域服务等]来实现用例,在这个阶段同样执行一些AOP逻辑,比如授权、验证、审计日志和工作单元等.一个应用服务方法是一个工作单元,具有原子性.
参考文献:
[1]abp-vnext-pro:https://github.com/WangJunZzz/abp-vnext-pro
[2]iEricLee的ABP博客:https://www.cnblogs.com/YGYH/
[3]cms-kit:https://github.com/abpframework/abp/tree/dev/modules/cms-kit
[4]基于ABP Framework实现领域驱动设计
人工智能干货推荐专注于人工智能领域的技术分享
游戏元宇宙专注于游戏领域的技术分享
边栏推荐
- R language test whether the sample conforms to normality (test whether the sample comes from a normally distributed population): shapiro.test function tests whether the sample conforms to the normal d
- Unity中实现点选RenderTexture中的3D模型
- R language ggplot2 visualization: use the ggmapplot function of the ggpubr package to visualize the MA plot (MA-plot), the font.legend parameter and the font.main parameter to set the title and legend
- Kubernetes principle analysis and practical application manual, too complete
- .NET 20周年专访 - 张善友:.NET 技术是如何赋能并改变世界的
- 删除表格数据或清空表格
- Snake Project (Simple)
- Applicable Scenarios of Multi-Master Replication (1) - Multi-IDC
- Linux查看redis版本(查看mongodb版本)
- Qt practical cases (54) - using transparency QPixmap design pictures
猜你喜欢
mysql black window ~ build database and build table
定时器的类型
MySQL基础篇【单行函数】
mysql黑窗口~建库建表
[MySQL] Mysql paradigm and the role of foreign keys
Qt实战案例(54)——利用QPixmap设计图片透明度
"Autumn Recruitment Series" MySQL Interview Core 25 Questions (with answers)
TextBlock控件入门基础工具使用用法,取上法入门
.NET 20周年专访 - 张善友:.NET 技术是如何赋能并改变世界的
01 邂逅typescript,环境搭建
随机推荐
org.apache.jasperException(could not initialize class org)
Kubernetes common commands
2020微信小程序反编译教程(小程序反编译源码能用吗)
TRACE32 - Common Operations
ML.NET related resources
Insert into data table to insert data
三、数组
字符串反转的实现方法总结「建议收藏」
type of timer
第二届中国PWA开发者日
【Meetup预告】OpenMLDB+OneFlow:链接特征工程到模型训练,加速机器学习模型开发
Efficient use of RecyclerView Section 3
JVM parameter analysis Xmx, Xms, Xmn, NewRatio, SurvivorRatio, PermSize, PrintGC "recommended collection"
Deployment应用生命周期与Pod健康检查
Bilateral filtering acceleration "recommended collection"
ASP.NET Core 产生连续 Guid
ES6 类
长得很怪的箱图
mysql black window ~ build database and build table
浏览器自带的拾色器