这是【一文一点】的第9篇学习文章,不拘泥于篇幅字数,用一篇文章说清一个知识点。
本文的知识,你可以作为一个了解,如果你对DCI和Qi4j框架的初心感兴趣可以继续。
1、
我昨天晚上乘坐高铁,看了郑晔老师的极客专栏《软件设计之美》,其中讲面向对象继承的这课的思考题,提到了DCI架构。
这让我隐约想起来,记得《架构整洁之道》这本书里面也提到过一次,当时是跟六边形架构和BEC架构拿来一起同比介绍,当然《架构整洁之道》这本书里面主要介绍的是六边形架构和clean架构。
为了写这篇文章,我又去翻看了下书中的介绍,”无论哪种架构风格,他们都具有同一个设计目标:按照不同的关注点对软件进行切割“,也就是我们经常说的分离关注点。
当前软件设计中比较流行,或者说知名的四种架构,整洁架构、DCI架构、DDD架构(严格说是一种设计方法)、六边形架构。
这些架构都是分层的架构风格,因为分层可以让各层各负其责,实际上,也是单一职责原则的宏观展现。
2、
说了上面这么多,到此也仅仅知道DCI也是一种分层的架构,那么到底什么是DCI架构呢。
所谓DCI架构,就是对象的Data数据、对象使用的Context场景、对象的Interactions交互,Data、Context、Interactions 简称DCI。
对于传统的面向对象而言,有数据和行为,如果不是太严格的话,实际可以对应这里的数据和交互,唯独没有场景,或者换个角度来讲传统的面向对象较好的表达了结构,但在表达交互方面欠佳。
大家,可以大胆想一下,如果要能够较好的表现出交互,是不是需要有角色的概念,数据有了,场景有了,行为也有了,谁参与其中呢,唯独缺少角色。
DCI架构就提出了角色Roles的概念,而其中的场景就是角色参与到具体业务活动中的表现。
图自网络
Roles
DCI架构的核心思想是在描述对象的时候,不再强调类或者POJO,而是强调,对象是由Roles来组合组装行为。
Data
DCI架构中的数据就是实体对象中的数据。
Context
Context掌握了在一个交互场景中角色与一个特定对象实例的关系映射。·
Interactions
交互是作为场景实现的方法,寻找场景中相关的角色,然后**调用其领域方法。
3、
Spring框架的主要作用就是将行为和数据天然的做了分离,伟大之处就是让不太懂面向对象编程的人,也能够写出规范化的工程代码,不好的地方也显而易见,就是对象过于贫血,反而失去了面向对象的味道。
另外,还有一点,我们大家常常在编程的时候大量使用了继承,特别是在我们进行领域建模的时候,因为大家直觉上就是有个模型我继承就好了。
举个例子,比如我要计算订单参与优惠之后的实际价格,我就写了一个类来继承订单类来干这件事,原因是订单类里面有优惠的算法,那实际上订单和优惠算法完全是描述不同的关注点。
这里,仔细想过之后,肯定是用组合比较好,这也是在Java这门面向对象的语言开发中,有一个经常被我们提及的规则:“组合优先于集成“。
当我们使用组合的时候,被嵌入的自然而然可能就是接口了,可能有的同学会问了,那么有没有把接口嵌入模型中的框架呢,就像spring那样,而同时呢又不像spring那样搞的太贫血。
Qi4j框架就是这样的一种框架,框架被提出的时候,它的口号是:“类已死,接口万岁”。(注:保持谨慎态度来看待)
我从InfoQ网站上找到一段关于它的描述,原文地址https://www.infoq.cn/article/2007/11/qi4j-intro ,这篇文章的时间已经比较早,不过我们可以看下它当初提出的初心。
Qi4j 带来了面向组合编程的新思想,提出类中不再放有任何的行为,取而代之的是,类成为混入(mixins)的‘组合’,并在类中使用标注定义接口。Qi4j 本身是一个提供给所有 java 开发者使用的面向组合编程的 Java 框架。
尽管面向组合编程需要较大的思想转变,但是面向组合编程不需要单独的工具、语言或 XML。Qi4j 的应用程序可以在 Spring 应用软件、Web 应用容器、OSGi 和其他地方运行。Qi4j 大量使用了标注,以此摆脱框架特定的知识,让开发者更关注业务规则。
该项目的创始人也曾说过如下的内容。
Qi4j 是一个以领域为中心的应用开发框架,融入了从面向方面编程、依赖注入和领域驱动设计演化而来的思想。
我需要一个能使领域模型和业务规则再度成为关注焦点、让领域专家和开发者能够清晰沟通的系统。
4、
一说到面向对象编程,我们立马会提到封装、集成、多态,其中封装呢,又是面向对象的基础,那么封装的是什么?
有的人说是数据、有的人说是行为、其实,在这里可以告诉大家的是,封装最重要的是封装行为,数据是行为产生的数据。
而DCI呢,其实就是特别关注行为的设计方法,这点,大家可以跟设计模式中的行为模式做个参照。
5、
在上面我们提到了DCI架构的开源框架QI4J的期望之一就是想要在领域驱动设计方面和让领域专家和开发者之间有清晰的沟通。
那么DCI其实跟DDD是有一定的“心心相惜”的。
那么DCI对我们所了解到的DDD有什么辅助作用么,我们来看一下中兴通讯的架构师张晓龙在ArchSummit 深圳 2019 大会的分享。
首先,DCI 助力 DDD 战术设计:
1、显式地对 ROLE 建模,解决了贫血模型与充血模型之争;
2、一个聚合可以支持哪些 ROLE,一个 ROLE 可以由哪些聚合扮演,一个场景下哪些聚合要扮演哪些角色;
3、当 Aggregate 内部实体行为比较多时可以嵌套使用 DCI 来拆分和组合;
其次,DCI 助力 DDD 代码落地:
1、对象就是 Data,Client 为 Context,对象在 Client 中的行为就是 ROLE。
2、根据正交设计原则得到小类(素材库),根据多重继承(only C++)或依赖注入来组合素材,不管是行为类还是数据类,都按 Role 的方式来组合,对像仅仅组合 Role 并注入依赖;
3、小类大对象:类作为一种模块化手段,遵循高内聚,低耦合,让软件易于应对变化;对象作为一种领域对象的的直接映射,解决了过多的类带来的可理解性问题,让领域可以指导设计,设计真正反映领域;领域对象需要真正意义上的生命周期管理。
6、
说点题外话,对于极客时间和得到或者其它音频类知识,如果能有环境去看,我绝不会去听,你可以试试,看的效果要比听的效果好的多了,因为看是主动式学习,听属于被动式学习。
本文,因为也只是花了今天三小段时间来学习,早上上班前,中午午饭后和晚上回到住处,可能分析的不会那么到位,不过希望也能做个引子吧。
感谢你读到这里,本文完。
学习参考资料
https://www.jdon.com/37976 精读架构设计之 DCI
https://zhuanlan.zhihu.com/p/27654319 DCI架构是什么?
https://www.jdon.com/38266 使用qi4j实现DCI架构