写点什么

没有依赖注入和面向方面编程,能很好地进行领域驱动设计吗?

  • 2008-03-04
  • 本文字数:2408 字

    阅读完需:约 8 分钟

领域驱动设计(DDD)的主要思想是在设计中将业务领域中的概念与软件元素对应起来,面向对象的编程方法(OOP)是DDD 实现中的核心要素。OOP 中的对象就代表现实中某个实体。在充分利用诸如继承、封装和多态等OOP 概念的基础上, 领域对象会被设计成简单Java 类和接口。

在一个典型的业务单元中,领域对象通常需要与其他对象协同工作,无论此对象是服务(Service) 仓库(Repository) 还是工厂(Factory)。与此同时,诸如领域状态变化跟踪、审核、缓冲、事务管理(包括事务重试)之类的横切关注点也是领域对象必须密切关注的。然而,这些东西大都是可重用的并且是非领域相关的,它们往往会散布或者重复出现在包括领域层的所有代码中。这些嵌入领域代码中的非领域逻辑往往会导致领域层的繁杂与混乱。

为了很好管理代码间依赖,同时解耦领域对象与独立的横切关注点,只使用OOP 技术往往不能为领域驱动设计提供一流的设计和开发解决方案。正是由于这些原因催生了依赖注入 (DI) 和面向方面编程 (AOP) 等概念。它们作为 OOP 的补充,能很好地减少代码间紧密耦合、增加产品模块化特性和管理横切关注点。

以上就是 DomainDrivenDesign 用户组的论坛最近一个帖子讨论的主题。讨论由Ramnivas Laddad 有关DDD 的一段演讲引出,在陈述中他断言DDD 在没有AOP 和DI 辅助的情况下是无法完全实现的。Ramnivas 谈到了应用AOP 实现细粒度DI 这一概念,他认为此概念能使领域对象的行为更合理。他还提到领域对象如果想要有丰富的功能行为,就必须有权使用其他细粒度的对象,这往往是通过将服务、工厂或者仓库注入到领域对象中实现的(使用Aspects 在构造函数或者 setter 函数中进行注入 )。

管理域对象之间的依赖关系(例如实体与其仓库间依赖)是任何一个 DDD 开发者都会涉及的典型问题。通常的设计解决方法是让 Service 或者 Façade 直接调用 Repository,Repository 获得实体对象后将其返回给调用者。这种设计方式往往会导致胖服务层和贫血模型( Anemic Domain Model )的出现,结果就是 façade 类会开始堆积越来越多的业务逻辑,领域对象也逐渐变成只有一些 setter 和 getter 函数的纯粹的数据载体。

InfoQ 与 Ramnivas Laddad 和《领域驱动设计》一书的作者 Eric Evans 就 DDD 实现中 DI 和 AOP 的角色问题进行了讨论。当谈到 DDD 在没有 AOP 和 DI 辅助的情况下是无法完全实现的这一断言时,Ramnivas 认为这个结论的重要前提是领域对象如果想要表现得更灵活,与 Repositories 和 Services 这样的对象打交道是不可避免的。

问题的关键是领域对象怎样得到此类对象?DI 似乎是个正确的选择。AOP 此时也正好派上用场,它将类 Spring 的 DI(将 DI 限制在 application context 中声明的对象范围内)扩展到任意的对象,而不管它是在哪里创建的。当然,AOP 也会在任何领域层面的横切关注点上起作用(此处的基本假设是领域概念应尽可能地映射到某一软件制品上)。

Eric 在谈到 OOP、DI 和 AOP 为何非常适合实现 DDD 时说:

虽然 DDD 能用任何范式实现,只要这些范式支持抽象并且能表达领域概念就行。但在实际应用中人们的选择几乎总是 OOP。因此说 OOP 是 DDD 实践的基础。 DI 目前已经成为了一项广为人知的技术,如果应用得当,它能帮助 DDD 实践者改善设计。在我看来,最重要的还是 DI 实现了领域的隔离。

人们正逐渐认识 AOP 的潜力。这种潜力就是它可以改变领域层的杂乱状态。这对领域概念的清晰表达甚至领域隔离非常有帮助。但是,它还不是“基础”(译者注:指 OOP)的一个经受过实践检验的组成部分,在这一点上它还是跟 OOP 和 DI 有区别的。

以上这些就形成了目前支持 DDD 的最佳实践架构的基础。

他还强调说弄清设计思想(DDD)与能帮助我们实现这种思想的技术工具(OOP、DI 甚或 AOP)间的界限也是非常重要的。

近来定义和管理 Aspects 和 DI 的趋势是应用注释(Annotations)。Spring 采用 @Configurable 将 Repository 和 Services 注入到领域对象。InfoQ 就注释(Annotations)在 DDD 项目中的角色问题咨询了 Eric:

通常,任何依附于某个对象并且代表领域中某个概念的东西,包括注释(Annotation),应该在概念上与此对象有某种联系。@Configurable 属于技术范畴,并非属于领域范畴,因此我不赞成给领域对象加上这样的注释。在另一方面,对 Repository 来说,我一般会有一个接口和一个实现类。我将接口看作其中的领域部分,尽量保持其纯概念化。但是实现类往往会引用某种技术(例如 DAO 是这些技术中的典型代表)。这样在 Repository 的实现类中应用 @Configurable 注释就合情合理了。

在 @Configurable 注释之外,Spring 框架继续扩展了“领域依赖注入”的思想。Ramnivas 最近写了一篇关于 Spring2.5.2 版本( project snapshot build 379 )最新进展的博客文章。Spring2.5.2 有三个新的方面(AnnotationBeanConfigurerAspect, AbstractInterfaceDrivenDependencyInjectionAspect 和 AbstractDepndencyInjectionAspect),它们为领领域对象的依赖注入提供了简单并且灵活的选择。Ramnivas 说引入前述第二个方面(AbstractInterfaceDrivenDependencyInjectionAspect)的目的是让特定领域的注释和接口能起到应有的作用。他最后补充道 @Configurable 虽说是一个简单的选项,但它往往不是最优雅的。

目前也有了一些关于服务编排(对多步骤的业务单元来说)和业务对象生命周期的讨论。在关于 BPEL 是怎样影响领域对象生命周期和不同领域对象之间交互这一问题上,Eric 的观点是:

服务编排和对象生命周期是很微妙的一对概念。服务编排是一种将解耦的业务片段重新结合在一起同时又能描述出工作流程的重要方法。在另一方面,在领域实体有一定的生命周期并且这些周期处于建模的中心地位的情况下,让编制层来管理对象生命周期,领域对象里面就没剩多少东西了。不过此问题并没有现成的标准答案。对设计者设计好坏的评估要个别分析,不能一概而谈。

查看英文原文: Can DDD be Adequately Implemented Without DI and AOP?

2008-03-04 23:143579
用户头像

发布了 23 篇内容, 共 56198 次阅读, 收获喜欢 3 次。

关注

评论

发布
暂无评论
发现更多内容

2022秋招前端面试题(五)(附答案)

helloworld1024fd

前端面试题

图数据科学和机器学习图数据科学GDS概览

flow

8月月更

Sass.vs.Less | 简介

Jason199

SaaS 8月月更

Shell脚本中常用命令复习

Albert Edison

Linux centos 运维 shell脚本编程 8月月更

MPLS网络向SRv6网络演进

穿过生命散发芬芳

8月月更 SRv6

C++对象模型和this指针实例分析(二)

CtrlX

c++ 后端 面向对象思想 热门活动 8月月更

基于消息中间件开发的优点

阿泽🧸

消息中间件 8月月更

数据治理(三):数据质量管理

Lansonli

大数据 数据治理 8月月更

rocketmq整合SpringCloudStream

急需上岸的小谢

8月月更

测试也应该具备的项目管理能力

老张

项目管理 质量保障

3 款非常实用的 Node.js 版本管理工具

Geek_z9ygea

JavaScript node.js 前端

提升领导力的有效方法

宇宙之一粟

领导力 8月月更

2022秋招前端面试题(六)(附答案)

helloworld1024fd

前端面试题

深入了解 Spring篇之BeanDefinition结构

邱学喆

对象初始化 BeanDefinition 对象创建 属性注入 对象检索

「控制反转」和「依赖倒置」,傻傻分不清楚?

蝉沐风

ioc 依赖倒置原则 DIP DI 控制反转

语音聊天app开发——对用户更具吸引力的设计

开源直播系统源码

软件开发 语聊房 开源源码 语音直播系统 语音源码

梦回战国,领略两千多年前公孙龙如何将面向对象运用得炉火纯青

迷彩

Java 面向对象 签约计划第三季 8月月更 面向过程编程

阿里云云原生加速器企业硬之城携手阿里云 Serverless 应用引擎(SAE)打造低代码平台

阿里巴巴云原生

阿里云 Serverless 云原生 合作伙伴

《MySQL入门很轻松》第2章:MySQL管理工具介绍

乌龟哥哥

8月月更

生于云、长于云,RocketMQ 5.0 再出发

阿里巴巴云原生

阿里云 RocketMQ 云原生 消息队列

结合实际聊聊防反接电路(防反接电路总结)

矜辰所致

防反接电路设计 8月月更

头脑风暴:除数博弈

HelloWorld杰少

8月月更

用户权限-Linux系统ACL控制

Albert Edison

Linux centos 运维 服务器 8月月更

Ingress Nginx 接连披露高危安全漏洞,是否有更好的选择?

阿里巴巴云原生

阿里云 Kubernetes 云原生 ingress

云原生时代下,微服务体系与 Serverless 架构的发展、治理与融合

阿里巴巴云原生

阿里云 Serverless 微服务 云原生

高层次综合(HLS)

贾献华

8月月更

部署spark2.2集群(standalone模式)

程序员欣宸

spark 8月月更

开源一夏|Flutter实现搜索的三种方式

坚果

开源 OpenHarmony 8月月更

没有依赖注入和面向方面编程,能很好地进行领域驱动设计吗?_架构_Srini Penchikala_InfoQ精选文章