什么是DDD呢?领域驱动设计[DDD]是一种针对复杂需求的软件开发方法。将软件实现与不断发展的模型联系起来,专注于核心领域逻辑,而不是基础设施细节。DDD适用于复杂领域和大规模应用,而不是简单的CRUD应用。它有助于建立一个灵活、模块化和可维护的代码库。

一.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实现领域驱动设计:https://url39.ctfile.com/f/2501739-616007877-f3e258?p=2096 (访问密码: 2096)

基于ABP实现DDD--DDD相关概念的更多相关文章

  1. 基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践和原则

    目录 前言 聚合 聚合和聚合根原则 包含业务原则 单个单元原则 事务边界原则 可序列化原则 聚合和聚合根最佳实践 只通过ID引用其他聚合 用于 EF Core 和 关系型数据库 保持聚合根足够小 聚合 ...

  2. WeText项目:一个基于.NET实现的DDD、CQRS与微服务架构的演示案例

    最近出于工作需要,了解了一下微服务架构(Microservice Architecture,MSA).我经过两周业余时间的努力,凭着自己对微服务架构的理解,从无到有,基于.NET打造了一个演示微服务架 ...

  3. 基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式

    -之动态查询,查询逻辑封装复用 基于领域驱动设计(DDD)超轻量级快速开发架构详细介绍请看 https://www.cnblogs.com/neozhu/p/13174234.html 需求 配合Ea ...

  4. 基于ABP落地领域驱动设计-06.正确区分领域逻辑和应用逻辑

    目录 系列文章 领域逻辑和应用逻辑 多应用层 示例:正确区分应用逻辑和领域逻辑 学习帮助 系列文章 基于ABP落地领域驱动设计-00.目录和前言 基于ABP落地领域驱动设计-01.全景图 基于ABP落 ...

  5. 基于ABP实现DDD--领域逻辑和应用逻辑

      本文主要介绍了多应用层的问题,包括原因和实现.通过理解介绍了如何区分领域逻辑和应用逻辑,哪些是正确的实践,哪些是不推荐的或者错误的实践. 一.多应用层的问题 1.多应用层介绍   不知道你们是否会 ...

  6. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(六)

    系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...

  7. 基于ABP落地领域驱动设计-01.全景图

    什么是领域驱动设计? 领域驱动设计(简称:DDD)是一种针对复杂需求的软件开发方法.将软件实现与不断发展的模型联系起来,专注于核心领域逻辑,而不是基础设施细节.DDD适用于复杂领域和大规模应用,而不是 ...

  8. 基于ABP落地领域驱动设计-03.仓储和规约最佳实践和原则

    目录 系列文章 仓储 仓储的通用原则 仓储中不包含领域逻辑 规约 在实体中使用规约 在仓储中使用规约 组合规约 学习帮助 围绕DDD和ABP Framework两个核心技术,后面还会陆续发布核心构件实 ...

  9. 基于ABP落地领域驱动设计-00.目录和小结

    <实现领域驱动设计> -- 基于 ABP Framework 实现领域驱动设计实用指南 翻译缘由 自 ABP vNext 1.0 开始学习和使用该框架,被其优雅的设计和实现吸引,适逢 AB ...

随机推荐

  1. ngx-lua实现高级限流方式一

    基于POST请求体中的某个参数限流 背景 电商平台有活动,活动涉及优惠券的抢券,优惠券系统对大并发支持略差,为了保护整体系统平稳,因此在入口Nginx层对抢券接口做了一层限流. 完整实现如下: lua ...

  2. jQuery操作标签,jQuery事件操作,jQuery动画效果,前端框架

    jQuery操作标签 jQuery代码查找标签绑定的变量名推荐使用 $xxxEle 样式类操作 addClass();// 添加指定的CSS类名. removeClass();// 移除指定的CSS类 ...

  3. 常见的邮箱服务器(SMTP,POP3)地址,端口

    163.com: POP3服务器地址:pop.163.com(端口:110) SMTP服务器地址:smtp.163.com(端口:25) sina.com: POP3服务器地址:pop3.sina.c ...

  4. 无线:WEP

    WEP是Wired Equivalent Privacy的简称,有线等效保密(WEP)协议是对在两台设备间无线传输的数据进行加密的方式,用以防止非法用户窃听或侵入无线网络.不过密码分析学家已经找出 W ...

  5. unity---公共模块MonoController

    公共模块 如果有很多类使用Update()函数,会导致性能浪费 如果函数统一在一个Update()中执行 代码 上述,需要将脚本挂载到物体上, 故新建了一个管理类MonoMgr Mgr另外的作用 可以 ...

  6. 安装Siege到Linux(源码)

    运行环境 系统版本:CentOS Linux release 7.3.1611 (Core) 软件版本:siege-4.0.4 硬件要求:无 安装过程 1.安装依赖 [root@localhost ~ ...

  7. redis高可用、redis集群、redis缓存优化

    今日内容概要 redis高可用 redis集群 redis缓存优化 内容详细 1.redis高可用 # 主从复制存在的问题: 1 主从复制,主节点发生故障,需要做故障转移,可以手动转移:让其中一个sl ...

  8. Python数据分析--Numpy常用函数介绍(3)

    摘要:先汇总相关股票价格,然后有选择地对其分类,再计算移动均线.布林线等. 一.汇总数据 汇总整个交易周中从周一到周五的所有数据(包括日期.开盘价.最高价.最低价.收盘价,成交量等),由于我们的数据是 ...

  9. javaweb开发案例

    1.实验3 (1)当运行Servlet时,碰到"空指针异常"错误怎么处理? 答:应提示用户操作有误,或设置对象值为空字符串或一个默认值,或是不执行某操作,直接跳转到其他处理中. ( ...

  10. st表 LCA

    我当时知道ST表可以 \(O(1)\) 求 LCA 的时候是极为震惊的,可以在需要反复使用 LCA 的时候卡常使用. ST表!用于解决 RMQ问题 ST表 我可能写得不好,看专业的 怎么实现? 考虑把 ...