写点什么

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

  • 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:143552
用户头像

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

关注

评论

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

RocketMQ消息模型

废材姑娘

Java RocketMQ

Arthas 定位 Dubbo 手动注册 Eureka 异常

阿里巴巴云原生

阿里云 云原生 dubbo 工具 征文大赛

SourceTree 如何连接 GitLab

TroyLiu

git gitlab SSH sourcetree

【薪火计划】07 - 与领导沟通的方法

码上生长

管理

甲方日常 79

句子

工作 随笔杂谈 日常

Spring 源码学习 13:initMessageSource

程序员小航

spring 源码 源码解析

mysql binlog轻量同步工具binlog portal

dothetrick

Java MySQL springboot Binlog spring Boot Starter

区块链钱包开发的核心优势

区块链钱包开发的功能与特点

平安社区平台解决方案,智慧社区综合服务平台搭建

t13823115967

智慧社区管理平台开发

阿里巴巴云原生的 2020,注定不凡的一年

阿里巴巴云原生

阿里云 容器 开发者 云原生 年终总结

影像恋上智能:麒麟9000中的高甜CP创新

脑极体

面试官:不会真有人不知道什么是线程池吧?

Java鱼仔

Java 线程池 并发

数字银行成长性和盈利能力可期

CECBC

数字化转型

Pulsar 2.7.0 新增特性概览:事务支持、Topic 级别策略配置等

Apache Pulsar

大数据 开源 pulsar Apache Pulsar 消息中间件

Android开发经验谈:2021最新Android常用开源库总结,成功收获美团,小米安卓offer

欢喜学安卓

android 程序员 面试 移动开发

数仓缓慢变化维深层讲解

大数据老哥

大数据 数据仓库 数仓

《数据挖掘:实用的机器学习工具和技术,第4版》PDF版免费下载

计算机与AI

数据挖掘 机器学习 数据科学

区块链商城系统开发技术详解

数字化浪潮下 哪些银行业务或“生变”

CECBC

金融科技

稻盛和夫《干法》| 教你做快乐的打工人

小匚

读书笔记 程序员 个人成长

程序员如何解决中年危机?资深Android开发带你入门Framework,醍醐灌顶!

欢喜学安卓

android 程序员 面试 移动开发

Ubuntu 使用 Iptables 做网络转发

wong

iptables Ubuntu20.04

ChaosBlade 在工商银行混沌工程体系中的应用实践

阿里巴巴云原生

云计算 高可用 开发者 云原生 实践

使用 iTerm2 打造美观高效的 Mac 终端

郭旭东

Mac 终端 iterm2

涨知识!一个三非渣本的Android校招秋招之路,赶紧收藏!

欢喜学安卓

android 程序员 面试 移动开发

币币交易所系统开发详情说明

大数据分析决策平台建设方案,警务情报研判系统搭建

t13823115967

大作业1

蓝黑

区块链挖矿系统开发功能方案

区块链app开发要多少钱?如何根据项目需求了解价格?

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