当前位置: 首页 > news >正文

小研究 - 领域驱动设计DDD在IT企业内部网站开发中的运用(二)

在企业内部网站的建设过程中,网站后端最初采用传统的表模式的开发方式。这种方式极易导致站点的核心业务逻辑和业务规则分布在架构的各个层和对象中,这使得系统业务逻辑的复用性不高。为了解决这个问题,作者在后期的开发过程中引入了领域驱动设计的开发方式,把系统的业务逻辑独立建模、充分地复用,并基于这些模型打造易于扩展的开发框架,提高了整个团队开发业务逻辑的效率,最终网站如期上线,稳定运行至今。

目录

2 开发模式的应用

2.1 初期采用表模式开发模式

2.2 后期采用DDD开发模式来聚焦业务逻辑

3 结束语


2 开发模式的应用

2.1 初期采用表模式开发模式

在最初的开发过程中,作者带领团队采用表模式开发系统,也就是每个业务功能的开发都遵循如下的流程:
1) 根据业务的需求分析得到数据表的字段,把数据库表建好。
2) 通过ORM将数据库中的表映射成代码中的实体对象。
3) 在业务逻辑层根据功能的需要补充业务逻辑和规则,操作实体对象进行数据的读取和持久化。

这种开发方式简单易行,但是随着网站的功能逐渐增多,逻辑越发地复杂,如下问题逐渐显现出来:
1) 通过ORM得到的实体对象都是贫血模型,它们只有数据库映射的属性和字段,并不具有具体的业务行为。
2) 因为没有明确的约束,核心业务逻辑和业务规则非常容易从业务逻辑层扩散到其他层和对象中。有的跑到了帮助类中、有的跑到了存储过程里,这导致了业务逻辑的复用性不高。

为了解决上述问题,作者再次深入研究了上述的软件开发模式并决定引入DDD来开发和管理项目。

2.2 后期采用DDD开发模式来聚焦业务逻辑

使用DDD开发模式来开发和管理项目,作者带领团队实践了如下的过程。

1) DDD战略设计
①将整个应用程序域进行划分,剥离各个子域在该项目中,经过分析,作者共拆分出账号管理、任务管理、积分管理、图书管理等子域。
②对每个子域进行限界上下文的设计在每个限界上下文中,保证任何一个对象模型的语义是确定的、无歧义的。

虽然两个User对象具有相同的名字,但是它们是完整的用户对象在不同上下文中的投影,是两个不同的对象。

在项目实施的过程中,作者选择将子域和限界上下文一一对应,独立部署在每个AppService中。

2) DDD战术设计
DDD战术设计的核心就是把核心业务逻辑集中放到一起,组成领域层。其他层设计为依赖于该层。领域层中包含所有重要的领域模型,包括聚合根、实体、值对象、领域事件、仓储、领域服务等。

①设计聚合根、实体和领域服务在该项目的领域层中,最重要的对象就是聚合根和实体。它们完成了主要的业务逻辑。

使用聚合根还是实体,在实践中一般都可以,但是如果完成一个业务操作,就一个主要的实体就可以了,不需要其他相关实体的配合,那么暴露这个实体给其他层就可以了。

比如Book这个实体,不仅包含了所有图书的所有信息,还包括增加封面、修改作者、增加点评等各种业务行为。

但是如果完成一个业务操作,需要一个主要的实体,配合上其他一些相关的实体才能完成,那么就将主要的实体暴露成聚合根给其他层使用,把相关的其他实体全部隐藏起来,这些相关的实体的操作统统通过聚合根来暴露。

比如Task这个实体,不仅包含了所有Task自身的信息和操作,还包括其包含的子对象TaskItem实体的信息和各种操作,所以 Task 实体就暴露为聚合根,向外提供所有 Task 和TaskItem的相关操作,其他层无法直接操作TaskItem对象以及其方法。如图6所示。

②设计领域事件
该项目中,非常常见的一个需求就是一个实体改变了,需要通知其他的一些实体就行一些对应的变化。这种需求就需要通过事件模式来实现。

在项目中,作者实现了一个EventBus作为通用的领域事件模型,任何实体都可以挂接这个对象,发布消息,或关注感兴趣的消息并做出响应,这个部分与通用的事件模型并没有太大的不同,示意图如图7所示。

③设计仓储
使用仓储模式可以很好地隔离数据库的操作和领域对象。

在领域层,作者定义了各个仓储接口,仓储与聚合根或实体一一对应,包含对应的增删改查等操作,它们是数据库操作的接口。

需要注意的是,在领域层中,只是定义了接口,并没有具体的持久化的实现。具体的持久化工作放在了基础设施层中。

3) 其他层的一些细节
①基础设施层
这里重点说明一下的是数据库持久化的选型。针对领域层提供的仓储接口,作者实现时选择了使用Enti⁃ty Framework Core(以下简称EF Core) 作为基础框架。使用此类ORM框架大大简化了数据库的操作,使用对象而不是SQL语句的方式可以避免很多语法上的错误,有效地提升了代码的健壮性。

而且使用了EF Core的Code First的方式后,项目只要使用EF Core的包命令就可以非常简单地根据实体对象的变更来创建和维护数据库。

②应用服务层
在该项目中,应用服务层比较简单,它实现了一个公用的AppService,封装了公用的分页的逻辑。其他各项服务比如BookAppService都继承自该基类,实现了自己的逻辑。

在各个服务中,为了调用领域层的业务逻辑,首先需要把前端传过来的输入数据传输对象(Data Transfer Object,以下简称DTO) 转换成领域层的数据模型,然后调用领域层的领域模型和基础设施层的对象完成功能,最后再将结果转换成输出DTO返回给前端。

③后端接口层和前端表现层
接口层使用Restful Api去提供服务,前端表现层使用Vue3.0实现展示,不管是否使用DDD,这些部分都是一样的,不去多解释。
经过上述的分析、设计与重构,最终得到如下新的架构,如图8所示。

3 结束语

采用了DDD来开发和管理项目以后,项目的业务逻辑沉淀到了领域层的领域对象中,领域对象变成了包含业务逻辑的充血模型,这样业务逻辑得到了复用,程序的扩展性得到了保证。

此外,由于存在清晰明确的分层和职责,团队日常的开发效率得到了显著的提升。目前该站点已经上线并稳定地运行至今。

相关文章:

小研究 - 领域驱动设计DDD在IT企业内部网站开发中的运用(二)

在企业内部网站的建设过程中,网站后端最初采用传统的表模式的开发方式。这种方式极易导致站点的核心业务逻辑和业务规则分布在架构的各个层和对象中,这使得系统业务逻辑的复用性不高。为了解决这个问题,作者在后期的开发过程中引入了领域驱动…...

在Qt中实现鼠标监听与交互

文章目录 概述1. 包含头文件2. 实现鼠标事件函数3. 使用示例4. 应用场景 概述 鼠标监听是在Qt应用程序中实现用户交互的关键部分之一。通过捕获鼠标事件,您可以响应用户的点击、移动和释放动作,实现各种交互效果。本篇博文将详细介绍在Qt中如何进行鼠标…...

力扣hot100刷题记录

二刷hot100&#xff0c;坚持每天打卡&#xff01;&#xff01;&#xff01; 1. 两数之和 // 先求差&#xff0c;再查哈希表 public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> map new HashMap<>();for(int i 0;i<nums.length;i){int key …...

阿里云国际站视频直播服务是什么呢?

阿里云国际站视频直播是什么呢&#xff1f;下面一起来看一下&#xff1a; 视频直播服务&#xff08;ApsaraVideo Live&#xff09;是基于前瞻的内容接入、分发网络和大规模分布式实时转码技术打造的音视频直播平台&#xff0c;提供便捷接入、高清流畅、超低延时、高并发的音视频…...

python实现简单的爬虫功能

前言 Python是一种广泛应用于爬虫的高级编程语言&#xff0c;它提供了许多强大的库和框架&#xff0c;可以轻松地创建自己的爬虫程序。在本文中&#xff0c;我们将介绍如何使用Python实现简单的爬虫功能&#xff0c;并提供相关的代码实例。 如何实现简单的爬虫 1. 导入必要的…...

AI文档识别技术之表格识别 (一)

AI文档识别技术之表格识别(一) 文章目录 文章目录 AI文档识别技术之表格识别(一)1. 表格识别原理介绍1.1 表格类型分类1.2 识别原理 2. 整体识别流程2.1 流程图2.2 图像处理部分大致流程 3. 将表格转换为html与json格式输出3.1 html格式3.2 json格式3.3 表格识别实例 前言 此文…...

uni-app 支持 app端, h5端,微信小程序端 图片转换文件格式 和 base64

uni-app 支持 app端 h5端&#xff0c;微信小程序端 图片转换文件格式 和 base64&#xff0c;下方是插件市场的地址app端 h5端&#xff0c;微信小程序端 图片转换文件格式 和 base64 - DCloud 插件市场 https://ext.dcloud.net.cn/plugin?id13926...

云计算——存储虚拟化简介 与 存储模式及方法

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​ 目录 前期回顾 前言 一.存储虚拟化介绍 1.云计算存储基本概念 2.云计算存储模型 3.创…...

数据资产目录建设之数据分类全解

01 数据治理“洗澡论” 其实他们之前做过数据一轮数据资产盘点&#xff0c;做了一个分类&#xff0c;也挂到系统上了&#xff0c;但是后来就没有后来了。治理做一半&#xff0c;等于啥也没干。 我之前在群里开了一个玩笑&#xff0c;数据治理这种事情&#xff0c;就跟洗澡一…...

大模型的数据隐私问题有解了,浙江大学提出联邦大语言模型

作者 | 小戏、Python 理想化的 Learning 的理论方法作用于现实世界总会面临着诸多挑战&#xff0c;从模型部署到模型压缩&#xff0c;从数据的可获取性到数据的隐私问题。而面对着公共领域数据的稀缺性以及私有领域的数据隐私问题&#xff0c;联邦学习&#xff08;Federated Le…...

flask-sqlalchemy使用

# sqlalchemy 集成到flask中 # 第三方: flask-sqlalchemy 封装了用起来&#xff0c;更简洁 安装 pip install flask-sqlalchemy 使用 # 使用flask-sqlalchemy集成1 导入 from flask_sqlalchemy import SQLAlchemy2 实例化得到对象db SQLAlchemy()3 将db注册到app中db.in…...

flask处理token的装饰器

以下是在 Flask 中基于 token 实现的登录验证装饰器的示例代码&#xff1a; import jwt from functools import wraps from flask import request, jsonify, current_appdef login_required(f):wraps(f)def decorated_function(*args, **kwargs):token request.headers.get(A…...

【Express.js】页面渲染

页面渲染 常见的页面分为两种&#xff0c;一种是静态页面&#xff0c;比如用 Vue、React 等写好的静态页面&#xff0c;另一种是动态模板页面&#xff0c;如 Thymeleaf&#xff0c;JSP 等。 本节将简要介绍如何在 express 中渲染静态页面&#xff0c;以及适用于 express 的模…...

2.UE数字人语音交互(UE数字人系统教程)

上一篇&#xff1a;1.Fay-UE5数字人工程导入 2.UE数字人语音交互&#xff08;UE数字人系统教程&#xff09; 1、启动ue数字人 2、下载Fay数字人控制器 Fay数字人控制器下载地址 3、依照说明配置运行Fay 4、启动Fay控制器 5、切换到UE界面开始说话 6、完成了&#xf…...

C语言——水仙花数字

//水仙花数字 //每个数位上的数字的 3次幂之和等于它本身 //列如&#xff1a;1531^35^33^3 #include<stdio.h> int main() {int i,x,y,z;for(i100;i<1000;i){xi%10;yi/10%10;zi/100%10;if(i(x*x*xy*y*yz*z*z))printf("%d\n",i);}return 0; } //输出100-1000…...

java中list对象拷贝至新的list对象并保持两个对象独立的方法

在Java中&#xff0c;如果你想拷贝一个List对象到一个新的List对象&#xff0c;并且修改原来的List不影响新的List中的内容&#xff0c;有几种方法可以实现&#xff1a;使用构造函数&#xff1a; 可以使用List的构造函数&#xff0c;传递原始List作为参数来创建一个新的List对象…...

使用AI工具Lama Cleaner一键去除水印、人物、背景等图片里的内容

使用AI工具Lama Cleaner一键去除水印、人物、背景等图片里的内容 前言前提条件相关介绍Lama Cleaner环境要求安装Lama Cleaner启动Lama CleanerCPU方式启动GPU方式启动 使用Lama Cleaner测试结果NO.1 检测框NO.2 水印NO.3 广州塔NO.4 人物背景 参考 前言 由于本人水平有限&…...

瑞数系列及顶像二次验证LOGS

瑞数商标局药监局专利局及顶像二次验证 日期&#xff1a;20230808 瑞数信息安全是一个专注于信息安全领域的公司&#xff0c;致力于为企业和个人提供全面的信息安全解决方案。他们的主要业务包括网络安全、数据安全、应用安全、云安全等方面的服务和产品。瑞数信息安全拥有一支…...

Anaconda版本和Python版本对应关系(持续更新...)

简介 Anaconda是包管理工具,是专注于数据分析的Python发行版本&#xff0c;其包含Python和许多常用软件包&#xff0c;不同的Anaconda版本里面也配备了不同的Python版本&#xff0c;并且Python的出现时间比Anaconda早很多&#xff1b;相对而言&#xff0c;python原生的pip安装方…...

vscode 搭建STM32开发环境

1.需要软件 1.1 vscode 1.2 STM32CubeMX&#xff0c;这个不是必须的&#xff0c;我是为了方便生成STM32代码 2.vscode配置 2.1安装keil Assistant 2.2配置keil Assistant 3.STMCUBE生成个STM32代码 &#xff0c;如果有自己的代码可以忽略 4.代码添加到vscode&#xff0c;并…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...

若依登录用户名和密码加密

/*** 获取公钥&#xff1a;前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...

Pydantic + Function Calling的结合

1、Pydantic Pydantic 是一个 Python 库&#xff0c;用于数据验证和设置管理&#xff0c;通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发&#xff08;如 FastAPI&#xff09;、配置管理和数据解析&#xff0c;核心功能包括&#xff1a; 数据验证&#xff1a;通过…...

Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例&#xff08;电脑网站支付&#xff09; 1. 添加依赖 <!…...

Django RBAC项目后端实战 - 03 DRF权限控制实现

项目背景 在上一篇文章中&#xff0c;我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统&#xff0c;为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...

ZYNQ学习记录FPGA(二)Verilog语言

一、Verilog简介 1.1 HDL&#xff08;Hardware Description language&#xff09; 在解释HDL之前&#xff0c;先来了解一下数字系统设计的流程&#xff1a;逻辑设计 -> 电路实现 -> 系统验证。 逻辑设计又称前端&#xff0c;在这个过程中就需要用到HDL&#xff0c;正文…...