领域驱动设计基本概念答疑

简介: 领域驱动设计基本概念答疑

实体与值对象  


问题:DDD实现中领域对象区分实体(Entity)和值对象(Value Object)的目的(Why)是什么?或者换一种问法:领域对象区分实体(Entity)和值对象(Value Object)之后,带来的好处和收益是什么?

回答:从DDD的概念上讲,实体(Entity)与值对象(Value Object)的本质区别仅在于后者无需identity(唯一标识)。这其实就是带来的价值——就是你设计的对象不需要去跟踪和管理这个唯一标识。

这是概念划分上,值对象带来的价值。

再来说设计层面。通常情况下,我们建议将值对象设计成一个不变(Immutable)对象。当一个对象是不变的时,你就基本不需要担心并发带来的诸如同步、冲突等问题了,这既降低了编程的难度,又可以无需引入额外的同步锁影响程序的性能。

反而过来说,之所以可以将值对象设计成不变的,其根本原因还是在于我们无需跟踪和管理唯一标识。

在领域驱动设计中,我们提倡的实践是尽量定义值对象来替代基本类型,原因在于基本类型无法体现统一语言中的领域概念。此外,在多数语言中,我们无法对基本类型做封装,就意味着一个领域概念缺乏领域行为来支持。假设一个实体定义了许多属性,如果这些属性都是基本类型,就会导致与这些属性相关的领域行为都要放到实体中,导致实体的职责变得不够单一。

引入值对象后,情况就不同了,因为我们可以利用合理的职责分配,将这些职责(领域行为)按照内聚性分配到各个值对象中,这个领域模型就能变得协作良好。

当然,反过来说,之所以可以这样设计,还是在于值对象无需承担跟踪和管理唯一标识的职责。

这也是为何Eric要将实体和值对象分开的主要原因,也是值对象给我们带来的价值所在。

Repository与DAO 


问题:Repository与DAO其实都是两种模式的名称。然而在领域驱动设计中,名称本身就是非常重要的。Dao即Data Access Object,即数据访问对象。从其命名上看,就应该属于数据访问层,即DDD中的基础设施层。

回答:在DDD中,所有的领域对象应该都属于领域层。那么,该如何访问这些领域对象呢?DDD希望解除领域层与基础设施层之间的关系,即将设计的注意力完全放在领域建模和领域设计上,思考领域逻辑的实现时,应尽可能地不要考虑领域对象的持久化(数据访问),于是就定义了Repository这个抽象。无论放在哪里(文件、DB或者内存),Repository都将其视为一个“资源库”的抽象。经过这么一层的抽象之后,获取领域对象,或者说管理领域对象生命周期的逻辑就应该属于领域层。

在实现上,你当然可以将这样的Repository接口命名为DAO,这本身没有问题,但名不正则言不顺,如果在领域层中夹杂了一个名为DAO的接口,仍然有“将基础设施混入领域层”的嫌疑。

所以,Repository是抽象,代表了对领域对象生命周期的管理,但并不等于是持久化,持久化只是Repository的其中一种实现。你可以假设一台服务器无比的强大,内存大且永远不会宕机,这时何须持久化呢?但无论怎么修改生命周期的具体管理方式,都不会影响到Repository的抽象。

领域服务与应用服务  


问题:应用服务与领域服务的区别在哪?

回答:从分层架构上,应用服务属于应用层,领域服务属于领域层。

从职责上看,应用服务只是一个门面(Facade),它具体并不做领域服务的活儿,也就是不提供领域实现,也就是不包含业务逻辑。之所以要引入应用服务,有两个原因:

  • 领域服务或其他领域对象的粒度太细(便于协作、扩展和重用),不利于客户端的调用,基于“最小知识原则”,还是让客户端少知道这些领域对象协作的知识为好。此时的应用服务更像是对领域对象的一种“编排”。
  • 在调用领域对象去完成一个用例时,不可避免地要牵涉到一些属于“横切关注点”的内容,如事务、异常处理、授权认证等。这些横切关注点从职责上看,不属于领域层,放在领域服务中可能会导致对领域逻辑的污染,这些职责就像砌砖墙时需要的水泥。水泥自身不提供砖头的职责,但没有水泥,墙就没法砌起来。


相关文章
|
存储 关系型数据库 MySQL
MVCC多版本并发控制
MVCC多版本并发控制 1、MVCC MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
775 0
|
Linux C语言
Linux 中的文件锁定命令:flock、fcntl、lockfile、flockfile
Linux 中的文件锁定命令:flock、fcntl、lockfile、flockfile
686 0
|
传感器 测试技术 atlas
Landsat系列卫星:Landsat 9 详解和细节(NASA/USGS)
Landsat系列卫星:Landsat 9 详解和细节(NASA/USGS)
4187 0
Landsat系列卫星:Landsat 9 详解和细节(NASA/USGS)
|
9月前
《跟老卫学仓颉编程语言开发》实战:猜数字游戏
本文介绍了用仓颉语言开发的一个简单猜数字游戏,综合运用了流程控制、标准输入、字符串操作和整型比较等知识。程序生成1到100之间的随机整数,用户通过标准输入猜数字,程序提示“太大”或“太小”,直至猜中并显示祝贺信息。代码使用`std.console`包处理输入,`std.convert`包实现字符串转整型,通过`if-else`判断大小,`while`循环支持多次输入。示例源于《跟老卫学仓颉编程语言开发》,源码可在其GitHub仓库获取。
413 0
|
JavaScript
request to https://registry.npm.taobao.org/cnpm failed, reason: certificate has expired
request to https://registry.npm.taobao.org/cnpm failed, reason: certificate has expired
755 2
|
机器学习/深度学习 数据采集 人工智能
智能化运维在现代IT基础设施中的应用与价值####
本文探讨了智能化运维(AIOps)在现代IT基础设施管理中的实际应用、面临的挑战及其带来的深远影响。通过引入先进的算法和机器学习模型,智能化运维不仅提高了故障检测与响应的速度,还显著优化了资源配置,降低了运营成本,为企业数字化转型提供了强有力的技术支撑。 ####
|
移动开发 Dart 前端开发
深度分析:React Native、Flutter、UniApp、Taro、Vue的差异
深度分析:React Native、Flutter、UniApp、Taro、Vue的差异
1141 6
|
前端开发 Java 开发工具
移动应用开发之旅:从新手到专家
【9月更文挑战第2天】本文将带你走进移动应用开发的世界,无论你是初学者还是有经验的开发者,都能从中获得新的知识和技能。我们将一起探讨移动操作系统的基本知识,学习如何选择合适的开发工具,并深入理解移动应用开发的生命周期。你还将了解到如何通过实践和不断学习来提升自己的技能,以及如何保持对新技术的敏锐洞察力。让我们一起开启这场移动应用开发之旅吧!
|
Ubuntu 应用服务中间件 Linux
Linux Centos7 ubuntu 安装nginx,脚本一键安装nginx
Linux Centos7 ubuntu 安装nginx,脚本一键安装nginx
391 2
|
监控 Dubbo Java
唯品会开源分布式作业调度平台Saturn
Saturn英文意思是:土星,太阳系中的第二大行星。比地球高一个层级,地球是八大行星之一。而今天我们介绍的Saturn,是IT行业的一个分布式作业调度平台。
1586 0
唯品会开源分布式作业调度平台Saturn