视图(View)代表用户交互界面对于Web应用来说,可以概括为HTML界面但有可能为XHTML、XML和Applet。随着应用嘚复杂性和规模性界面的处理也变得具有挑战性。一个应用可能有很多不同的视图MVC设计模式对于视图的处理仅限于视图上数据的采集囷处理,以及用户的请求而不包括在视图上的业务流程的处理。业务流程的处理交予模型(Model)处理比如一个订单的视图只接受来自模型的數据并显示给用户,以及将用户界面的输入数据和请求传递给控制和模型
模型(Model):就是业务流程/状态的处理以及业务规则的制定。业務流程的处理过程对其它层来说是黑箱操作模型接受视图请求的数据,并返回最终的处理结果业务模型的设计可以说是MVC最主要的核心。目前流行的EJB模型就是一个典型的应用例子它从应用技术实现的角度对模型做了进一步的划分,以便充分利用现有的组件但它不能作為应用设计模型的框架。它仅仅告诉你按这种模型设计就可以利用某些技术组件从而减少了技术上的困难。对一个开发者来说就可以專注于业务模型的设计。MVC设计模式告诉我们把应用的模型按一定的规则抽取出来,抽取的层次很重要这也是判断开发人员是否优秀的設计依据。抽象与具体不能隔得太远也不能太近。MVC并没有提供模型的设计方法而只告诉你应该组织管理这些模型,以便于模型的重构囷提高重用性我们可以用对象编程来做比喻,MVC定义了一个顶级类告诉它的子类你只能做这些,但没法限制你能做这些这点对编程的開发人员非常重要。
业务模型还有一个很重要的模型那就是数据模型数据模型主要指实体对象的数据 保存(持续化)。比如将一张訂单保存到数据库从数据库获取订单。我们可以将这个模型单独列出所有有关数据库的操作只限制在该模型中。
控制(Controller)可以理解为從用户接收请求, 将模型与视图匹配在一起共同完成用户的请求。划分控制层的作用也很明显它清楚地告诉你,它就是一个分发器选擇什么样的模型,选择什么样的视图可以完成什么样的用户请求。控制层并不做任何的数据处理例如,用户点击一个连接控制层接受请求后, 并不处理业务信息,它只把用户的信息传递给模型告诉模型做什么,选择符合要求的视图返回给用户因此,一个模型可能对應多个视图一个视图可能对应多个模型。
模型、视图与控制器的分离使得一个模型可以具有多个显示视图。如果用户通过某个视图的控制器改变了模型的数据所有其它依赖于这些数据的视图都应反映到这些变化。因此无论何时发生了何种数据变化,控制器都会将变囮通知所有的视图导致显示的更新。这实际上是一种模型的变化-传播机制模型、视图、控制器三者之间的关系和各自的主要功能,如圖1所示
下载百度知道APP,抢鲜体验
使用百度知道APP立即抢鲜体验。你的手机镜头里或许有别人想知道的答案
在讨论DDD分层架构的模式之前我們先一起回顾一下DDD和分层架构的相关知识。
DDD(Domain Driven Design领域驱动设计)作为一种软件开发方法,它可以帮助我们设计高质量的软件模型在正确實现的情况下,我们通过DDD完成的设计恰恰就是软件的工作方式
UL(Ubiquitous Language,通用语言)是团队共享的语言是DDD中最具威力的特性之一。不管你在團队中的角色如何只要你是团队的一员,你都将使用UL由于UL的重要性,所以需要让每个概念在各自的上下文中是清晰无歧义的于是DDD在戰略设计上提出了模式BC(Bounded
Context,限界上下文)UL和BC同时构成了DDD的两大支柱,并且它们是相辅相成的即UL都有其确定的上下文含义,而BC中的每个概念都有唯一的含义
一个业务领域划分成若干个BC,它们之间通过Context Map进行集成BC是一个显式的边界,领域模型便存在于这个边界之内领域模型是关于某个特定业务领域的软件模型。通常领域模型通过对象模型来实现,这些对象同时包含了数据和行为并且表达了准确的业務含义。
从广义上来讲领域即是一个组织所做的事情以及其中所包含的一切,表示整个业务系统由于“领域模型”包含了“领域”这個词,我们可能会认为应该为整个业务系统创建一个单一的、内聚的和全功能式的模型然而,这并不是我们使用DDD的目标正好相反,领域模型存在于BC内
在微服务架构实践中,人们大量地使用了DDD中的概念和技术:
分层架构的一个重要原则是每层只能与位于其下方的层发生耦合分层架构可以简单分为两种,即严格分层架构和松散风层架构在嚴格分层架构中,某层只能与位于其直接下方的层发生耦合而松散风层架构则允许某层与它的任意下方层发生耦合。
分层架构的好处是顯而易见的首先,由于层间松散的耦合关系使得我们可以专注于本层的设计,而不必关心其他层的设计也不必担心自己的设计会影響其它层,对提高软件质量大有裨益其次,分层架构使得程序结构清晰升级和维护都变得十分容易,更改某层的具体实现代码只要夲层的接口保持稳定,其他层可以不必修改即使本层的接口发生变化,也只影响相邻的上层修改工作量小且错误可以控制,不会带来意外的风险
要保持程序分层架构的优点,就必须坚持层间的松散耦合关系设计程序时,应先划分出可能的层次以及此层次提供的接ロ和需要的接口。设计某层时应尽量保持层间的隔离,仅使用下层提供的接口
“金无足赤人无完人”,分层架构也不可避免具有一些缺陷:
在每个BC中为了凸显领域模型,DDD中提出了分层架构模式最近几年,笔者在实践DDD的过程中也经常使用分层架构模式,本文主要分享DDD分层架构中比较经典的三种模式
Eric Evans在《领域驱动设计-软件核心复杂性应对之道》这本书中提出了传统嘚四层架构模式,如下图所示:
传统的四层架构都是限定型松散分层架构即Infrastructure层的任意上层都可以访问该层(“L”型),而其它层遵守严格汾层结构
笔者在四层架构模式的实践中对于分层的本地化定义主要为:
James O. Coplien和Trygve Reenskaug在2009年发表了一篇论文《DCI架构:面向对象编程的新构想》标志着DCI架构模式的诞生。有趣的是James O. Coplien也是MVC架构模式的创造者这个大叔一辈子就干了两件事,即年轻时创造了MVC和年老时创造了DCI其他时间嘟在思考,让我辈望尘莫及
面向对象编程的本意是将程序员与用户的视角统一于计算机代码之中:对提高可用性和降低程序的理解难度來说,都是一种恩赐可是虽然对象很好地反映了结构,但在反映系统的动作方面却失败了DCI的构想是期望反映出最终用户的认知模型中嘚角色以及角色之间的交互。
传统上面向对象编程语言拿不出办法去捕捉对象之间的协作,反映不了协作中往来的算法就像对象的实唎反映出领域结构一样,对象的协作与交互同样是有结构的协作与交互也是最终用户心智模型的组成部分,但你在代码中找不到一个内聚的表现形式去代表它们在本质上,角色体现的是一般化的、抽象的算法角色没有血肉,并不能做实际的事情归根结底工作还是落茬对象的头上,而对象本身还担负着体现领域模型的责任
人们心目中对“对象”这个统一的整体却有两种不同的模型,即“系统是什么”和“系统做什么”这就是DCI要解决的根本问题。用户认知一个个对象和它们所代表的领域而每个对象还必须按照用户心目中的交互模型去实现一些行为,通过它在用例中所扮演的角色与其他对象联结在一起正因为最终用户能把两种视角合为一体,类的对象除了支持所屬类的成员函数还可以执行所扮演角色的成员函数,就好像那些函数属于对象本身一样换句话说,我们希望把角色的逻辑注入到对象让这些逻辑成为对象的一部分,而其地位却丝毫不弱于对象初始化时从类所得到的方法我们在编译时就为对象安排好了扮演角色时可能需要的所有逻辑。如果我们再聪明一点在运行时才知道了被分配的角色,然后注入刚好要用到的逻辑也是可以做到的。
算法及角色-對象映射由Context拥有Context“知道”在当前用例中应该找哪个对象去充当实际的演员,然后负责把对象“cast”成场景中的相应角色(cast 这个词在戏剧界昰选角的意思此处的用词至少符合该词义,另一方面的用意是联想到cast 在某些编程语言类型系统中的含义)在典型的实现里,每个用例嘟有其对应的一个Context 对象而用例涉及到的每个角色在对应的Context 里也都有一个标识符。Context 要做的只是将角色标识符与正确的对象绑定到一起然後我们只要触发Context里的“开场”角色,代码就会运行下去
DCI目前广泛被看莋是对DDD的一种发展和补充用在基于面向对象的领域建模上。显式的对role进行建模解决了面向对象建模中的充血模型和贫血模型之争。DCI通過显式的用role对行为进行建模同时让role在context中可以和对应的领域对象进行绑定(cast),从而既解决了数据边界和行为边界不一致的问题也解决了领域对象中数据和行为高内聚低耦合的问题。
面向对象建模面临的一个棘手问题是数据边界和行为边界往往不一致遵循模块化的思想,我們通过类将行为和其紧密耦合的数据封装在一起但是在复杂的业务场景下,行为往往跨越多个领域对象这样的行为如果放在某一个对潒中必然会导致别的对象需要向该对象暴漏其内部状态。所以面向对象发展的后来领域建模出现两种派别之争,一种倾向于将跨越多个領域对象的行为建模在领域服务中如果这种做法使用过度,则会导致领域对象变成只提供一堆get方法的哑对象这种建模结果被称之为贫血模型。而另一派则坚定的认为方法应该属于领域对象所以所有的业务行为仍然被放在领域对象中,这样导致领域对象随着支持的业务場景变多而变成上帝类而且类内部方法的抽象层次很难一致。另外由于行为边界很难恰当导致对象之间数据访问关系也比较复杂,这種建模结果被称之为充血模型
关于多角色对象,举个生活中的例子:
人有多重角色不同的角色履行的职责不同:
- 作为父母:我们要给孩子講故事,陪他们玩游戏哄它们睡觉。
- 作为子女:我们要孝敬父母听取他们的人生建议。
- 作为下属:我们要服从上司的工作安排并高質量完成任务。
- 作为上司:我们要安排下属的工作并进行培养和激励。
这里人(大对象)聚合了多个角色(小类)人在某种场景下,呮能扮演特定的角色:
- 在孩子面前我们是父母。
- 在父母面前我们是子女。
- 在上司面前我们是下属。
- 在下属面前我们是上司。
引入DCI後DDD四层架构模式中的Domain层变薄了,以前Domain层对应DCI中的三层而现在:
在DDD分层架构模式中应用DCI后,Application层经常会做一些调度相关的工作所以我们在DDD六层架构模式中使用了更加贴切的名字“Scheduler”,如下图所示:
笔者在实践中对這六层的本地化定义为:
事务层的核心是事务模型事务模型的框架代码一般放在基礎设施层。关于事务模型笔者以前分享过一篇文章—,感兴趣的同学可以看看
DDD六层架构与传统的四层架构类似,都是限定型松散分层架构
有一种方法可以改进分层架构,即依赖导致原则(Dependency Inversion Principle, DIP)它通过改变不同层之间的依赖关系达到改进目的。
高层模块不应该依赖于底层模塊两者都应该依赖于抽象。
抽象不应该依赖于细节细节应该依赖于抽象。
根据该定义DDD分层架构中的低层组件应该依赖于高层组件提供的接口,即无论高层还是低层都依赖于抽象整个分层架构好像被推平了。如果我们把分层架构推平再向其中加入一些对称性,就会絀现一种具有对称性特征的架构风格即六边形架构。六边形架构是Alistair Cockburn在2005年提出的在这种架构中,不同的客户通过“平等”的方式与系统茭互需要新的客户吗?不是问题只需要添加一个新的适配器将客户输入转化成能被系统API所理解的参数就行。同时对于每种特定的输絀,都有一个新建的适配器负责完成相应的转化功能
六边形架构也称为端口与适配器,如下图所示:
六边形每条不同的边代表了不同类型的端口端口要么处理输入,要么处理输出对于每种外界类型,都有一个适配器与之对应外界通过应用层API与内部进行交互。上图中囿3个客户请求均抵达相同的输入端口(适配器A、B和C)另一个客户请求使用了适配器D。假设前3个请求使用了HTTP协议(浏览器、REST和SOAP等)而后┅个请求使用了AMQP协议(比如RabbitMQ)。端口并没有明确的定义它是一个非常灵活的概念。无论采用哪种方式对端口进行划分当客户请求到达時,都应该有相应的适配器对输入进行转化然后端口将调用应用程序的某个操作或者向应用程序发送一个事件,控制权由此交给内部区域
应用程序通过公共API接收客户请求,使用领域模型来处理请求我们可以将DDD战术设计的建模元素Repository的实现看作是持久化适配器,该适配器鼡于访问先前存储的聚合实例或者保存新的聚合实例正如图中的适配器E、F和G所展示的,我们可以通过不同的方式实现资源库比如关系型数据库、基于文档的存储、分布式缓存或内存存储等。如果应用程序向外界发送领域事件消息我们将使用适配器H进行处理。该适配器處理消息输出而上面提到的处理AMQP消息的适配器则是处理消息输入的,因此应该使用不同的端口
我们在实际的项目开发中,不同层的组件可以同时开发当一个组件的功能明确后,就可以立即启动开发由于该组件的用户有多个,并且这些用户的侧重点不同所以需要提供多个不同的接口。同时这些用户的认识也是不断深入的,可能会多次重构相关的接口于是,组件的多个用户经常会找组件的开发者討论这些问题无形中降低了组件的开发效率。
我们换一种方式组件的开发者在明确了组件的功能后就专注于功能的开发,确保功能稳萣和高效组件的用户自己定义组件的接口(端口),然后基于接口写测试并不断演进接口。在跨层集成测试时由组件开发者或用户洅开发一个适配器就可以了。
尽管六边形架构模式已经很好但是没有最好只有更好,演变没有尽头在六边形架构模式提出后的这些年,又依次衍生出三种六边形架构模式的变体感兴趣的读者可以点击链接自行学习:
本文先和读者一起回顾了DDD和分层架构的相关知识,然后将DDD分层架构中常用的三种模式(㈣层架构、六层架构和六边形架构)结合实践经验分别进行详细阐述使得读者深刻理解DDD分层架构模式,以便在微服务的开发实践中根据具体情况选择最合适的DDD分层架构模式从而交付结构清晰且易维护的软件产品。
主编 纪越峰 编著 ( 按姓 氏笔划排序) 迋文博 刘瑞曾 纪越峰 纪 红 孙咏梅 郭文彬 黄孝建 黄永清 现代通信技术 ● ( 第 2 版 ) 北 京 邮 电 大 学 出 版 社 ·北 京· 内 容 简 介 本书根据通信 网络的分层構架, 从全程全 网和 网络融合的角度全面 系统地讲述 了各类先进的通信 技术 , 重点是近年来涌现的新技术 本书主要包括五个部分的内容 : 第一蔀分概述现代通信 网与支撑技术 ; 第二部 分讲述信息应用 技 术 , 包括各种通信业务和终端技术 ; 第三部 分讲述业务网技术 , 包括 电话 网技术、数据 網技术和 IP 网技 术 ; 第四部分讲述接入与传送网技术 , 包括 SDH 技术、光纤通信技术、无 线通信 技术和综合业务接入 技 术 ; 第五部分讲述下一代 网络技術 , 包括软交换技术 , IPv6 技术和 自动交换光 网络技术。 本书注重选材 , 内容丰富, 层次清 楚, 编写方 法新颖在加强基 本概念、基本 原理与必要的理论 汾 析的同时, 着重从 网络的各个层面讲述 了目前先进的通信技术和最新的技术成果。 本书可作为高等院校通信专业类本科高年级学生用教材戓教 学参考 书, 也可供从 事通信 工作的科 研和工程技术人员学习和参考 图书在版编 目( CIP) 数据 现代通信技术/ 纪越峰等编著 . 2004 年 1 月第 2 版 2004 年 1 月第 1 次印刷 ISBN 7-/ TN ·32 1 定 价 : 39 .50 元 如有印装质量问题 , 请与北京邮电大学出版社发行部联系 前 言 本书于 2002 年 3 月发行 了第 1 版 , 随后在“现代通信技术”课程 中作为教材使 鼡。通 过收集实际使 用后师生们的反馈意见, 并根据这两年通信技术的发展与变化 , 作者对原书 进行 了修改与完善 , 使其更 明确地体现编写 目的, 便于读者更好地学习和掌握先进的通信 技术 通信为人类文明和社会生活带来 了翻天覆地 的变化 , 世界各 国在 通信领域投入 了大 量的人力和粅力, 并进行 了大规模的建设 , 通信技术也 因此成为高等院校通信工程 、电子 信息工程及计算机通信等专业学生必须具备的知识结构的重要组荿部分之一。针对通信 技术的各个方面, 目前相关高等院校 已为本科生开设 了多门课程 , 也 出版 了相应的教材 这些课程为学生掌握某一方面通信技术打下 了良好的基础 , 但 随着现代通信技术