DCI架构,来自Trygve Reenskaug等写的论文,是Data(数据),Context(上下文,可理解为“场景”),Interactions(交互)的缩写。
一、 DCI
DCI认为面向对象很好的反映了结构,但是在反映系统动作(行为)方面不够。协作交互也是用户的心智模型,但是找不到内聚的形式去表现他们。
以转账的例子来说,用户思维里对转账的过程或算法是有概念的,而且是从角色(源账户、目标账户)的角度去思维。DCI试图用角色表达用例需求中重要的用户概念,角色是最终用户认知模型中的首要组成部分。
在这些出发点之下,DCI希望把稳定的数据模型和动态的行为模型分离开。数据模型即对象,代表的事物“是什么”,而他的行为“做什么”通过角色来阐述。通过技术手段把角色的逻辑注入到对象,让这些逻辑成为对象的一部分,就好像是对象初始化时从类所得到的方法一样。
完整的DCI架构是:
· 数据,生存在领域对象里,领域对象源自领域类。
· 上下文,按照需要将对象领到它们在场景中的位置。
· 交互,从角色的角度描绘最终用户对算法的思维,算法和角色皆可在最终用户的头脑中找到。
如下图,通过分析用户场景,提取出交互过程中的角色模型、数据模型,通过技术手段将角色模型的方法融入到数据模型中去。即根据交互上下文的需要组装成一个对象。
context描述过程,他根据用户场景把组合出来的对象”cast“成相应的”Role“,完成交互与协作。
二、 尝试
学习完DCI我有了这样的疑问:Trygve Reenskaug大牛的论文中提到,在账户这个对象中加入“转账”这个方法是不合适的,所以需要通过DCI抽取角色、加入上下文的方法来解决。其实,这种通过上下文体现的过程,面向对象里面也有解决方案。如果过程本身也是领域概念可以使用service或聚合来完成。如果仅是用户应用,可以放到app层去。这样,论文中举的例子就有点站不住脚。
为了更好的理解,我把银行转账的例子分别以面向对象和DCI方式简单实现了一下。
面向对象代码:
// 维护收支 Balance.h代码 typedef unsigned int BALANCE; struct Balance { Balance(BALANCE balance):_balance(balance){} void increase(BALANCE balance); bool decrease(BALANCE balance); BALANCE balance(); private: BALANCE _balance; }; |
//发送通知消息 Phone.h代码 struct Phone { Phone(string number):_number(number){} void message(stri |