写点什么

DCI:James O. Coplien 和 Trygve Reenskau 提出的新架构方法

  • 2009-05-14
  • 本文字数:2132 字

    阅读完需:约 7 分钟

James O. Coplien 和 Trygve Reenskaug 最近发表了系列文章的第一篇,该系列文章介绍一种面向对象编程的新架构方法,该方法基于 DCI(数据、上下文和交互)模式

作者在第一篇文章里主张,即便面向对象编程有助于描述结构,但它并不能充分表明用户的心智模式,因为它不能表示“最终用户的行为需求”。为了说明“行为”到底指什么,他们举了一个储蓄账户对象的例子,该对象可以减少余额,也能提款。按照 Coplien 和 Reenskaug 的意思,“这两种行为完全不同”:“减少余额只是数据的特征:它是什么。提款则反映了数据的目的:它做了什么。”事实上,能减少余额在任何情况下都是以数据为特征的——这一点是不变的。相反,提款则涉及“与 ATM 或审计跟踪之间的交互”——这是动态的,不再关乎“是什么”,而关乎“做什么”。

虽然用户模型很自然地结合了是什么和做什么这两个部分,但“在面向对象里很少有内容会帮助开发人员在代码中描述做什么,在 MVC 里则根本就没有。”“面向对象将这两部分混在一起”,很难把“简单、不变的数据模型和动态的行为模型区分开来”,但从架构和维护的角度来说,把两者分清楚可是很必要的。另外,纯粹的面向对象要求对大型算法进行分割,将各细分部分(也就是方法)分布到对象中,对象与给定的方法有着紧密的联系。即使有些算法能存在于单个对象中,“有意思的业务功能往往还是会跨多个对象。”

James 和 Trygve 提倡用 DCI 模型描述这些动态的行为模型,DCI 模型基于以下三个概念:

——数据,描述领域对象,表示不变的部分;

——交互,以角色的语言去描述,角色是“对象能进行的行为的集合”;

——上下文,可看成是“一个表格,将角色的一个功能(表格的一行)映射到一个对象方法上(表格的列是对象)。表格根据 Context 对象中程序员提供的业务智能进行填充,对给定的用例来说,Context 知道什么对象应该扮演什么角色。”

作者用转账用例给读者做了具体的说明。转账会涉及储蓄账户和投资账户,但用户在讨论这个用例的时候更喜欢用“源账户”和“目的账户”。这全都是角色,而转账的交互可以用角色的算法描述。上下文不同,角色可以由不同的对象去扮演:在这个具体的例子中,源账户角色将关联到储蓄账户对象上。

代码中能表示角色的一般设计概念是Trait,但 Trait 的实现依赖于特定编程语言中存在的结构:Scala 中的 Traits、Squeak Smalltalk 中的 Squeak Traits、C++ 中的模板等……DCI 方法的最大好处是,作者提供的示例代码“几乎就是用例描述文字的自然展开”:

比起让逻辑主观任意地跨越许多类的边界,DCI 将更容易理解——因为更符合最终用户的心智模型中逻辑的自然组织。

这篇文章引发了很多评论和批评,让James 和Trygve 提供更多精确的DCI 概念

Michael Feather 和很多其他评论者认为,把转账的任务指派给源账户太随意了,这实际上并不符合用户的心智模型,在用户看来,转账并不是由哪个账户来完成的,而是由银行或交易对象完成,“交易对象映射到交互的用户概念”。比如说,John Zabroski 建议用分析类 TransferSlip。另一些人则认为,DCI 所涉及的正是人们早已知道的内容:某些语言中的“Traits”,“函数编程的一般思想(算法比较紧要、应该能表达清楚)”,等等……

James O. Coplien 回应道,DCI“试图结合二十世纪八十年代面向对象里很多很好的领域建模概念,重现过程语言(比如 Fortran)过去用算法表达给我们带来的方便性”。像 Scala 这些语言中的 Traits 是一种实现方法,但在其它语言里可以用不同的结构去完成 DCI 架构。实际上,重要的并不是文中建议的工具或使用的例子,而是区分以下内容的架构方法:1)任何情况下都专属于领域对象的行为;2)特定于上下文的行为,这种行为属于业务逻辑,往往跨越多个对象。正如 Bill Venners 所说,“如果应用的十个用例都涉及账户概念,结果可能每个用例都有一些行为进入了 Account 类”,这对设计者来说也是个很大的挑战。所以,运用 DCI 让“对象在每个上下文中有一个不同的类”是“改善 OO 程序可理解性的一种尝试”:

[……] 这篇文章指出,有时候你可能在对象中放置了太多的行为,因为在不同上下文中要用到这些行为的不同子集。作者建议用 Traits 对额外的内容进行建模,Traits 可以映射到用户心智模型的任务上去。然后在某个特定的上下文或用例中,再往基本的领域对象中添加上下文需要的 Traits。

Coplien 指出了 DCI 使代码更易于阅读和调试的四个理由,以强调 DCI 带来的可读性:

  1. 跨业务功能的上下文切换比较少,而且更接近心智模型(基于角色),而不是程序员模型(基于领域);
  2. 包含多态(inclusion polymorphism)几乎完全消失了。调用 Foo 就得到 Foo:而不是子类型化层次中派生出的众多 Foo 里的一个。
  3. 我可以找到有业务价值的测试点:也就是说,我可以做到真正的 BDD(行为驱动开发)。这更易于开发测试用例,以支持调试。
  4. 不太需要进行运行时调试,因为代码在编译时就更加易读。

Trygve Reenskaug 强调说,要理解 DCI,需要“减少对类抽象的关注,勇于接受更适用于以上对象结构的额外抽象”,还需要“增加一种既能扩充类,又仍然保持对象身份的对象抽象”,即角色

查看英文原文: Data, Context and Interaction : A New Architectural Approach by James O. Coplien and Trygve Reenskau

2009-05-14 00:535732
用户头像

发布了 151 篇内容, 共 63.4 次阅读, 收获喜欢 18 次。

关注

评论

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

jQuery 的节点操作

Jason199

jquery js 7月月更

架构实战营|模块7

KDA

#架构实战营

查找——平衡二叉树

乔乔

7月月更

知其然,而知其所以然,JS 对象创建与继承

掘金安东尼

JavaScript 前端 设计模式 7月月更

qt 实现遍历文件夹

小肉球

qt 7月月更

getchar()

謓泽

7月月更

【LeetCode】滑动窗口的平均值Java题解

Albert

LeetCode 7月月更

SAP Fiori 的附件处理(Attachment handling)

汪子熙

SAP Fiori SAP UI5 ui5 7月月更

基于CSS mask-image 实现炫酷图片过渡效果之星球大战

南城FE

前端 动画效果 7月月更 过渡

以太坊升级在即,Arbitrum 引领 L2 Summer 新航向

TinTinLand

Tortoisegit工具的安装和使用

空城机

git Tortoisegit 7月月更

TCP拥塞控制详解 | 7. 超越TCP

俞凡

算法 网络 TCP拥塞控制

李宏毅《机器学习》|1. Introduction of this course(机器学习介绍)

AXYZdong

机器学习 7月月更

云原生(五) | Docker篇之深入Dockerfile

Lansonli

云原生 7月月更

java零基础入门-File类(实战篇)

喵手

Java 7月月更

数据库每日一题---第25天:银行账户概要 II

知心宝贝

数据库 云计算 前端 后端 7月月更

各厂商的数据湖解决方案

五分钟学大数据

数据湖 7月月更

nacos服务注册之SpringCloud 集成nacos

急需上岸的小谢

7月月更

LeetCode-108. 将有序数组转换为二叉搜索树(java)

bug菌

Leet Code 7月月更

HarmonyoS快速入门:Hello world

逝缘~

7月月更

王者荣耀商城异地多活架构设计

爱晒太阳的大白

使用Java获取给定日期所在周的第一天

李印

Java 小工具

C# SerialPort配置和属性了解

IC00

C# 7月月更

如何使用SVG制作沿任意路径排布的文字效果

南极一块修炼千年的大冰块

7月月更

OpenCV编程:OpenCV3.X训练自己的分类器

DS小龙哥

7月月更

【愚公系列】2022年7月 Go教学课程 012-强制类型转换

愚公搬代码

7月月更

开发第一个Flink应用

程序员欣宸

Java flink 7月月更

推荐 6 个实用的 Vue 组件库

devpoint

JavaScript Vue 前端开发 7月月更

数字化转型的两种误区

奔向架构师

数据仓库 数据资产 7月月更

MFC|框架下自绘CEdit控件

中国好公民st

c++ 7月月更

博弈论(depu)与投资(40/100)

hackstoic

投资

DCI:James O. Coplien和Trygve Reenskau提出的新架构方法_Scala_Sadek Drobi_InfoQ精选文章