领域驱动设计-贫血模型VS充血模型

2023-10-08 21:59

本文主要是介绍领域驱动设计-贫血模型VS充血模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

项目实现方式

事务脚本

事务脚本的核心是过程,通过过程的调用来组织业务逻辑,每个过程处理来自表现层的单个请求。大部分业务应用都可以被看成一系列事务,从某种程度上来说,通过事务脚本处理业务,就像执行一条条Sql语句来实现数据库信息的处理。事务脚本把业务逻辑组织成单个过程,在过程中直接调用数据库,业务逻辑在服务(Service)层处理

领域模型

领域模型的特点也比较明显, 属于面向对象设计,领域模型具备自己的属性行为状态,并与现实世界的业务对象相映射。各类具备明确的职责划分,领域对象元素之间通过聚合和引用等关系配合解决实际业务应用和规则。可复用,可维护,易扩展,可以采用合适的设计模型进行详细设计。缺点是相对复杂,要求设计人员有良好的抽象能力。

贫血模型VS充血模型

贫血模型

所谓贫血模型,是基于数据库的建模(Database Modeling)。

通过数据抽象系统关系,即传统数据库分析设计。该种模式实际上就是一种典型的贫血模型,通过数据库映射的实体类只有对应的属性,成为了只有getter和setter方法的数据载体,而没有具体行为,相应的行为要通过Service层去实现,随着业务升级积累,会出现胖服务层和贫血的领域模型,维护起来会越发乏力。即便如此,该种模式仍是广泛应用在软件开发领域。

充血模型

所谓充血模型,基于对象的建模: Object Modeling

通过面向对象方式抽象系统关系,也就是面向对象设计。毫无疑问,在面向对象编程环境中,面向对象无疑是领域建模最佳方式。通过面向对象构建的领域模型,因为有类的继承、封装、多态等特性显得生动许多,不仅包含自身属性状态,还包括有方法行为等,即充血的领域模型。一些Service层的行为凝练为领域服务,Service层则变薄了,领域模型则丰富了行为。

举例说明

我们通过一个例子,展现一个贫血模型与充血模型中显而易见的差别。 场景:网上转账

采用贫血模型实现

贫血模型是我们常常采用的MVC的三层架构

Dao 持久层

贫血对象-AccountEntity

/*** 账号Entity* @author yangyanping* @date 2021-08-30*/
@Data
public class AccountEntity {private Integer id;/*** 账号*/private Integer accountNum;/*** 用户名称*/private String userName;/*** 手机号码*/private String mobile;/*** 用户余额*/private Integer balance;
}

Dao 层

/*** 账号Dao层* @author yangyanping* @date 2021-08-30*/
public interface AccountMapper {int deleteByPrimaryKey(Integer id);int insert(AccountEntity record);int insertSelective(AccountEntity record);AccountEntity selectByPrimaryKey(Integer id);int updateByPrimaryKeySelective(AccountEntity record);int updateByPrimaryKey(AccountEntity record);
}

 Service 服务层

/*** 账户服务* @author yangyanping* @date 2021-09-20*/
public interface AccountService {/*** 转账*/Boolean transferAccount(AccountEntity source, AccountEntity target, Integer money);
}

采用充血模型设计

对传统DDD四层架构升级改造

(1)根据依赖倒置原则对分层结构进行了改进,通过改变不同层的依赖关系(即将基础设施层倒置)来改进具体实现与抽象之间关系;

(2)在基础设施层中增加引用适配层(防腐层)来增强防御策略,用来统一封装外部系统接口的引用。改进的分层结构如下:

依赖倒置原则(DIP):

  • 高层模块不依赖于低层模块,两者都依赖于抽象;
  • 抽象不应该依赖于细节,细节应依赖抽象

分层作用

分层描述
用户接口层用户界面层,或者表现层,负责向用户显示解释用户命令
应用层定义软件要完成的任务,并且指挥协调领域对象进行不同的操作。该层不包含业务领域知识。
领域层或称为模型层,系统的核心,负责表达业务概念,业务状态信息以及业务规则。即包含了该领域(问题域)所有复杂的业务知识抽象和规则定义。该层主要精力要放在领域对象分析上,可以从实体,值对象,聚合(聚合根),领域服务,领域事件,仓储,工厂等方面入手
基础设施层主要有2方面内容,一是为领域模型提供持久化机制,当软件需要持久化能力时候才需要进行规划;一是对其他层提供通用的技术支持能力,如消息通信,通用工具,配置等的实现;

 领域层 Domain Layer

和传统的三层架构不同,DDD领域驱动设计开发先设计好领域对象。我们先定义 Account 账户领域对象

充血模型是有血有肉的,核心领域方法都会放到领域对象中,而不是把领域方法放到模型之上的service层中去。 

package com.yyp.ddd.domain.model.account;import com.yyp.ddd.domain.factory.RepoFactory;
import com.yyp.ddd.infrastructure.persistence.repository.AccountRepository;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 充血模型* @author yangyanping* @date 2021-08-30*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Account {/*** 账号*/private Integer accountNum;/*** 用户名称*/private String userName;/*** 手机号码*/private String mobile;/*** 用户余额*/private Integer balance;/*** 转入*/public void deposit(Integer amount) {if (amount == null || amount.intValue() < 0) {throw new IllegalArgumentException("参数错误");}balance += amount;RepoFactory.get(AccountRepository.class).updateAccount(this);}/*** 转出*/public void withdrawal(Integer amount) {if (amount == null || amount.intValue() < 0) {throw new IllegalArgumentException("参数错误");}if (balance < amount) {throw new IllegalArgumentException("转出金额过大");}balance -= amount;RepoFactory.get(AccountRepository.class).updateAccount(this);}
}
/*** 仓储工厂用来统一获取仓储实现*/
public class RepoFactory {/*** 根据仓储接口类型获取对应实现且默认取值第一个** @param tClass 目标仓储接口类型* @param <T>    目标类型* @return 如果不是指定实现,默认获得第一个实现Bean*/public static <T> T get(Class<? extends T> tClass) {Map<String, ? extends T> map = ApplicationUtils.getApplicationContext().getBeansOfType(tClass);Collection<? extends T> collection = map.values();if (collection.isEmpty()) {//throw new PersistException("未找到仓储接口或其指定的实现:" + tClass.getSimpleName() );}return collection.stream().findFirst().get();}
}

应用层 Application Layer  代码

 AccountDTO 账户DTO类定义

/*** 账户信息DTO* @author yangyanping * @date 2021-09-20*/
@Data
public class AccountDTO  implements Serializable {/*** 账号*/private Integer accountNum;/*** 用户名称*/private String userName;/*** 手机号码*/private String mobile;/*** 用户余额*/private Integer balance;
}

 AccountService 账户服务类定义

/*** 账户服务* @author yangyanping* @date 2021-09-20*/
public interface AccountService {/*** 转账*/Boolean transferAccount(AccountDTO source, AccountDTO target, Integer money);
}

AccountServiceImpl账户实现类定义

/*** 账户服务层定义* @author yangyanping* @date 2021-08-30*/
@Service
public class AccountServiceImpl implements AccountService {@Overridepublic Boolean transferAccount(AccountDTO source, AccountDTO target, Integer money) {Account sourceAccount = ConvertUtils.convertVo2Do(source, Account::new);Account targetAccount = ConvertUtils.convertVo2Do(target, Account::new);// 转出sourceAccount.withdrawal(money);// 转入targetAccount.deposit(money);return true;}
}

 基础设施层 infrastructure Layer

Repository数据仓库
/*** 数据仓库* @author yangyanping*/
@Slf4j
@Repository
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class AccountRepository {/*** 数据持久层*/private AccountMapper accountMapper;/*** 更新账户信息*/public void updateAccount(Account account) {// account 转换AccountEntityAccountEntity record = ConvertUtils.convertDo2Vo(account, AccountEntity::new);System.out.println("name=" + record.getUserName() + ",balance=" + record.getBalance());//accountMapper.updateByPrimaryKeySelective(record);}
}

参考

从壹开始微服务 [ DDD ] 之一 ║ D3模式设计初探 与 我的计划书 - 简书

DDD-经典四层架构应用_最爱下雨天-CSDN博客_ddd四层架构

阿里技术专家详解 DDD 系列 第一讲- Domain Primitive - 知乎

https://github.com/alibaba/COLA

Rickie (rickiechina) - Gitee.com

COLA 4.0:直击应用架构本质的最佳实践【图文】_mb6018e8479df66_51CTO博客

殷浩详解DDD系列 第二讲 - 应用架构-阿里云开发者社区

殷浩详解DDD系列 第三讲 - Repository模式-阿里云开发者社区

阿里技术专家详解DDD系列 第五讲:聊聊如何避免写流水账代码 - 知乎

阿里技术专家详解DDD系列 第四讲 - 领域层设计规范 - 知乎

这篇关于领域驱动设计-贫血模型VS充血模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/168260

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry