实现DDD领域驱动设计: Part 4

原文链接: https://dev.to/salah856/implementing-domain-driven-design-part-iv-29m2

对象到对象映射

当两个对象具有相同或相似的属性时,自动对象到对象映射是一种将值从一个对象复制到另一个对象的有用方法。

DTO和实体类通常具有相同/相似的属性,你通常需要从实体创建DTO对象。

与手动映射相比,ABP与AutoMapper集成的对象到对象映射系统使这些操作更加容易。

  • 仅对实体使用自动对象映射以输出DTO映射。

  • 不要将自动对象映射用于输入DTO到实体的映射。

不应该使用输入DTO到实体自动映射的原因有一些;

  • Entity类通常有一个构造函数,它接受参数并确保创建有效的对象。自动对象映射操作通常需要一个空的构造函数。

  • 大多数实体属性将具有私有设置器,你应该使用方法以受控方式更改这些属性。

  • 你通常需要仔细验证和处理用户/客户端输入,而不是盲目地映射到实体属性。

示例用例

本节将演示一些示例用例并讨论替代方案。

实体创建

从实体/聚合根类创建对象是该实体生命周期的第一步。

聚合/聚合根规则和最佳实践部分建议为Entity类创建一个主构造函数,以保证创建一个有效的实体。

因此,每当我们需要创建该实体的实例时,我们应该始终使用该构造函数。

请参阅下面的问题聚合根类:

57a036843839f427b0f4de7dbac34b9e.png

让我们看一个用于创建问题的应用程序服务方法:

dffd5391b0a1a3044695f65cc10aabc6.png

CreateAsync方法;

  • 使用问题构造函数来创建一个有效的问题。它使用IGuidGenerator服务传递Id。它在这里不使用自动对象映射。

  • 如果客户端希望在创建对象时将此问题分配给用户,它会使用IssueManager来执行此操作,方法是允许IssueManager在此分配之前执行必要的检查。

  • 将实体保存到数据库

  • 最后使用IObjectMapper返回一个IssueDto,它是通过从新的Issue实体映射自动创建的。

将领域规则应用于实体创建

示例问题实体没有关于实体创建的业务规则,除了构造函数中的一些正式验证。

但是,在某些情况下,实体创建可能需要检查一些额外的业务规则。

例如,假设如果已经存在具有完全相同标题的问题,则你不想允许创建问题。

在哪里执行这个规则?在Application Service中实现此规则是不合适的,因为它是核心业务(域)规则,应始终检查。

此规则应在域服务中实现,在这种情况下为IssueManager。

所以,我们需要强制应用层总是使用IssueManager来创建一个新的Issue。

首先,我们可以将问题构造函数设置为内部的,而不是公开的:

1d48ce76183e7130e971959c6fa96340.png

这可以防止应用程序服务直接使用构造函数,所以他们将使用IssueManager。

然后我们可以在IssueManager中添加一个CreateAsync方法:

ad0b7c96603b3feffb37ec60f1a627c4.png

  • CreateAsync方法检查是否已经存在具有相同标题的问题,并在这种情况下引发业务异常。

  • 如果没有重复,它会创建并返回一个新问题。

为了使用IssueManager的CreateAsync方法,如下所示更改了IssueAppService:

147f179fa274ee911df12bc5eb32c3d9.png

更新/操作实体

一旦创建了实体,它就会被用例更新/操作,直到它从系统中删除。

可以有不同类型的用例直接或间接地改变一个实体。

在本节中,我们将讨论更改问题的多个属性的典型更新操作。

这一次,从更新DTO开始: 

cca5db20d2d71642a5c17d46e7018b08.png

通过与IssueCreationDto进行比较,你看不到RepositoryId。

因为,我们的系统不允许跨存储库移动问题(想象一下GitHub存储库)。

只有Title是必需的,其他属性是可选的。

让我们看看IssueAppService中的Update实现: 

e27d358be78027964acca78f38beddc9.png

领域逻辑和应用逻辑

领域驱动设计中的业务逻辑分为两部分(层):领域逻辑和应用逻辑: 

c97fd5790b952b04e93f1b62f491ddb2.png

领域逻辑由系统的核心域规则组成,而应用程序逻辑实现应用程序特定的用例。

虽然定义很清楚,但实现可能不是那么简单。你可能不确定哪个代码应该放在应用层,哪些代码应该在领域层。

多个应用层

当你的系统很大时,DDD有助于处理复杂性。特别是,如果在单个领域中开发多个应用程序,那么领域逻辑与应用程序逻辑的分离就变得更加重要。

假设你正在构建一个具有多个应用程序的系统;

  • 使用ASP.NET Core MVC构建的公共网站应用程序,用于向用户展示你的产品。这样的网站不需要身份验证即可查看产品。用户仅在执行某些操作(如将产品添加到购物篮)时才登录网站。

  • 使用Angular UI(使用 REST API)构建的后台应用程序。该应用程序由公司的办公室工作人员用来管理系统(如编辑产品描述)。

  • 与公共网站相比,具有更简单UI的移动应用程序。它可以通过REST API或其他技术(如TCP套接字)与服务器通信。

27e3ca5e4f3b85ba1a8b7b70a490d345.png

每个应用程序都会有不同的需求、不同的用例(应用程序服务方法)、不同的DTO、不同的验证和授权规则……等等。

将所有这些逻辑混合到单个应用程序层中,会使你的服务包含太多具有复杂业务逻辑的条件,会使你的代码更难开发、维护和测试,并导致潜在的错误。

如果你有多个具有单个域的应用程序;

  • 为每个应用程序/客户端类型创建单独的应用程序层,并在这些单独的层中实现应用程序特定的业务逻辑。

  • 使用单个领域层来共享核心域逻辑。

这样的设计使得区分领域逻辑和应用逻辑变得更加重要。

为了更清楚地了解实现,你可以为每种应用程序类型创建不同的项目 (.csproj)。例如:

  • IssueTracker.Admin.Application & IssueTracker.Admin.Application.Contracts,后台(管理员)应用程序的项目。

  • IssueTracker.Public.Application & IssueTracker.Public.Application.Contracts,公共 Web 应用程序的项目。

  • IssueTracker.Mobile.Application & IssueTracker.Mobile.Application.Contracts,移动应用项目

示例:在领域服务中创建新组织

14624d3ab49f90f1b7e64d73edd4cc9b.png

让我们看一下CreateAsync方法,讨论代码部分是否应该在领域服务中:

  • 正确:它首先检查重复的组织名称,并在这种情况下抛出异常。这与核心域规则有关,我们绝不允许重复名称。

  • 错误:领域服务不应执行授权。授权应该在应用层完成。

  • 错误:它记录一条包含当前用户的用户名的消息。领域服务不应依赖于当前用户。即使系统中没有用户,领域服务也应该可用。当前用户(会话)应该是一个表示/应用层相关的概念。

  • 错误:它发送一封关于这个新组织创建的电子邮件。我们认为这也是特定于用例的业务逻辑。你可能希望在不同的用例中创建不同类型的电子邮件,或者在某些情况下不需要发送电子邮件。

示例:在应用程序服务中创建新组织

54f6e831e6c3511f035e017b3bfbf9c0.png

让我们一步步看一下 CreateAsync 方法,讨论代码部分是否应该在应用服务中:

  • 正确:应用程序服务方法应该是工作单元(事务性)。ABP的工作单元系统使这一过程自动化(即使不需要为应用程序服务添加[UnitOfWork]属性)。

  • 正确:授权应该在应用层完成。在这里,它是通过使用[Authorize]属性来完成的。

  • 正确:调用付款(基础设施服务)来为此操作收费(创建组织是我们业务中的付费服务)。

  • 正确:应用程序服务方法负责将更改保存到数据库。

  • 正确:我们可以向系统管理员发送电子邮件作为通知。

  • 错误:不要从应用程序服务返回实体。改为返回 DTO。

示例:CRUD 操作

a5de554e599e97eb24b428242277d6fd.png

此应用程序服务本身不做任何事情,并将所有工作委托给领域服务。它甚至将DTO传递给 IssueManager。

  • 不要仅为没有任何领域逻辑的简单CRUD操作创建领域服务方法。

  • 切勿将DTO传递给域服务或从域服务返回DTO。

应用服务可以直接使用仓储来查询、创建、更新或删除数据,除非在这些操作期间需要执行一些领域逻辑。

在这种情况下,创建领域服务方法,但仅用于那些真正需要的方法。

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/290534.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件项目组织管理(六)项目时间管理

文章目录项目计划和进度计划什么是活动活动清单活动属性里程碑时间管理的过程1. 活动定义2. 活动排序三种依赖关系箭线图法(ADM)/双代号网络(AOA)前导图法(PDM)/单代号网络(AON)3. 活…

win7开机按F8后,为什么没有修复计算机的选项

有时win7开机按F8后,没有修复计算机的选项本文将向大家介绍如何通过 Windows 7自带的“配置 Windows 恢复环境(RE)”命令 – ReagentC.exe,启用“高级启动选项”下的“修复计算机”选项。单击 Windows 开始图标,在“搜索程序和文件”输入框中…

TLS/SSL握手过程

参考了:https://www.wosign.com/faq/faq2016-0309-04.htm 1、握手与密钥协商过程 基于RSA握手和密钥交换的客户端验证服务器为示例详解TLS/SSL握手过程。 (1).client_hello 客户端发起请求,以明文传输请求信息,包含版本信息,加密套件候选列表,压缩算法候选列表,随机数,扩…

FluentValidation在C#中是怎么进行数据验证的

介绍FluentValidation 是一个基于 .NET 开发的验证框架,用于构建强类型验证规则的 .NET 库。开源免费支持 .Net所有平台 包括.NetFramework和.NetCore.FluentValidation 组件内提供十几种常用验证器,可扩展性好,支持自定义验证器,…

基于Metronic的Bootstrap开发框架经验总结(5)--Bootstrap文件上传插件File Input的使用...

Bootstrap文件上传插件File Input是一个不错的文件上传控件,但是搜索使用到的案例不多,使用的时候,也是一步一个脚印一样摸着石头过河,这个控件在界面呈现上,叫我之前使用过的Uploadify 好看一些,功能也强大…

软件项目组织管理(七)项目成本管理

文章目录什么是成本什么是项目成本学习曲线理论储备金什么是项目成本管理目的过程成本估算成本估算的工具和技术成本预算主要工作成本估算和成本预算的关系和区别成本管理的工具方法净现值投资回报率挣值分析法什么是成本 为达到一个特定目标而花费的资源。 什么是项目成本 …

大话领域驱动设计——简介

如果说当下最热门的技术概念或架构思想,那么领域驱动设计(DDD)一定占有一席之地。上个系列,我讲了ABP vNext框架在微服务架构下的落地思路,而ABP vNext是基于DDD思想的完整框架之一,同时DDD也是微服务架构服…

软件项目组织管理(八)项目质量管理

文章目录软件质量的重要性对质量的认识传统的认识新的认识质量与等级什么是质量什么是质量管理什么是软件质量软件项目管理的目标质量管理的过程质量管理发展的四个阶段戴明改进循环(PDCA循环)项目质量计划编制方法——质量标杆法影响项目质量的因素(5M1…

Avalonia跨平台入门第十九篇之语音播放

在前面分享的几篇中咱已经玩耍了Popup、ListBox多选、Grid动态分、RadioButton模板、控件的拖放效果、控件的置顶和置底、控件的锁定、自定义Window样式、动画效果、Expander控件、ListBox折叠列表、聊天窗口、ListBox图片消息、窗口抖动、语音发送;今天趁着大周末的时间接着去…

软件项目组织管理(九)项目人力资源管理

文章目录什么是人力资源人力资源的特征什么是项目人力资源管理管理员工的关键所在马斯洛的需求层次理论赫兹伯格的双因素理论权力理论提高项目工作有效性的7种习惯人力资源管理过程人力资源管理的工具方法责任分配矩阵资源负荷资源平衡团队发展的5个阶段(塔克曼模型…

javax.jdo.option.ConnectionURL配置的问题

2019独角兽企业重金招聘Python工程师标准>>> Hive安装过程中出现 The reference to entity "createDatabaseIfNotExist" must end with the ; delimiter.问题,具体如下所示: [Fatal Error] hive-site.xml:132:95: The reference to…

设计模式21:State 状态模式(行为型模式)

State 状态模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态的行为就可能完全…

在 k8s 以外的分布式环境中使用 Dapr

在Dapr 文档和实践案例中多是推荐采用k8s, 其实我目前也是在k8s 上操作的,有公有云TKE,AKS,还有私有云的Rancher ,它并没有传闻中的那么难,而且我认为它非常容易上手。不过,我还是有很多人不愿意使用k8s 。…

javascript原型链中 this 的指向

为了弄清楚Javascript原型链中的this指向问题,我写了个代码来测试: var d {d: 40};var a {x: 10,calculate: function (z) {return this.x this.y z this.d},__proto__:d};var b {y: 20,__proto__: a};var c {y: 30,__proto__: a};运行如下的代码…

Lucene5.5.4入门以及基于Lucene实现博客搜索功能

前言 一直以来个人博客的搜索功能很蹩脚,只是自己简单用数据库的like %keyword%来实现的,所以导致经常搜不到想要找的内容,而且高亮显示、摘要截取等也不好实现,所以决定采用Lucene改写博客的搜索功能。先来看一下最终效果&#x…

都是基于.NET平台,WPF能取代Winform吗?

学Winform还是WPF?很多winform的学者时常在我的技术群咨询要不要学习WPF?我一贯的观点是必须学啊!如果是搞工控做cs软件开发,WPF自然是首选。WPF优势在哪里?①前后端分离:WPF是数据驱动的而非Winform的事件…

正确对待生活

三文鱼,国人称为马哈鱼。是一类洄游性鱼类,为常被食用的鱼类之一。主要生活在大西洋及太平洋,在美洲大湖及其他湖可以找到。三文鱼在淡水环境下出生,之后移到海水生长,又会洄游到淡水繁殖。三文鱼会利用太阳和地球磁场…

WPF 实现验证码控件

WPF开发者QQ群此群已满340500857 &#xff0c;请加新群458041663由于微信群人数太多入群请添加小编微信号yanjinhuawechat 或 W_Feng_aiQ 邀请入群需备注WPF开发者 01—代码如下一、创建CheckCode.xaml代码如下。<ResourceDictionary xmlns"http://schemas.microsoft.c…

Mysql数据库性能优化

2019独角兽企业重金招聘Python工程师标准>>> Mysql数据库性能优化&#xff0c;可以从下面三点入手&#xff1a; 数据库设计 SQL语句优化 架构优化 一.数据库设计优化 1.适度的违反范式&#xff0c;适度 遵循三大范式就会带来查询时经常需要join&#xff0c;导致…

4. 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识wrk、wrk2

1. 前言上一篇文章我们了解了bombardier&#xff0c;并知道了bombardier.yml与开源项目bombardier的关系&#xff0c;接下来的文章我们了解一下wrk、wrk2&#xff0c;并对比一下它们与bombardier的关系2. 认识wrkwrk是一种现代 HTTP 基准测试工具&#xff0c;能够在单个多核 CP…