百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

【译】The Clean Architecture(architect翻译)

mhr18 2024-09-14 05:39 33 浏览 0 评论

在过去几年我们看到关于系统架构的很多想法。这些包括:

  • Alistair Cockburn的六边形架构(也叫做端口与适配器),Steve Freeman, 和 Nat Pryce在他们精彩的著作Growing Object Oriented Software(http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627)采用。
  • Jeffrey Palermo的Onion Architecture (http://jeffreypalermo.com/blog/the-onion-architecture-part-1/)
  • 去年一片博客里的 Screaming Architecture (http://blog.cleancoders.com/2011-09-30-Screaming-Architecture)
  • James Coplien 与Trygve Reenskaug的DCI(http://www.amazon.com/Lean-Architecture-Agile-Software-Development/dp/0470684208/)。
  • Ivar Jacobson的书: Object Oriented Software Engineering: A Use-Case Driven Approach 的BCE(http://www.amazon.com/Object-Oriented-Software-Engineering-Approach/dp/0201544350)

尽管这些架构在一些细节上都有不同,它们仍是相似的。他们都有同样的目标,隔离关注点。他们都通过将软件分层来达到隔离。每个都至少有一层业务规则,另一层作为接口。

每个这些架构产出的系统都是:

  1. 独立的框架。架构不依赖一些存在类库的特性。这样你可以像工具一样使用这种框架,而不需要让你的系统受到它的约束条件。
  2. 可测试。业务规则可以脱离UI,数据库,web服务器或其他外部元素进行测试。
  3. 独立的UI。UI可以很容易的更换,系统的其他部分不需要变更。例如,Web UI可以被换成控制台UI,不需要变更业务规则。
  4. 独立的数据库。你可以交换Oracle或SQL Server,用于Mongo,BigTable,CouchDB或其他的东西。你的业务规则不与数据库绑定。
  5. 独立的外部代理。实际你的业务规则并不知道关于外部世界的任何事情。

这篇文章上面的图试着将以上所有架构整合成一个可执行的想法。

依赖规则

同心圆表示软件的不同部分。大体上,你走的越远,软件的级别更高。外部的圆是机制,内部的圆是策略。

让这个架构工作的覆盖规则是依赖规则。这个规则说明了源代码依赖只能向内。内部圆不能知道任何外部圆的事。实践中,外部圆里一些声明的名字不能被内部圆里的代码提到。这包括,函数,类,变量或其他任何软件实体。

同样的,外部圆使用的数据格式不应该被内部圆使用,尤其是当这些格式是被外部圆使用的框架生成的时候。我们不想让外部圆的东西影响到内部圆。

实体

实体封装企业域范围的业务规则。实体可以是一个有方法的对象,也可以是一组数据结构和函数。只要企业里不同的应用可以使用这些实体就可以。

如果你不是企业级,而只是写一个单体应用,那么这些实体就是应用的业务对象。它们封装了最通用和高层的规则。当外部变化时它们基本不太会变化。例如,你不会认为这些对象会因为页面导航或安全方面的变化而改变。任何特定应用的操作都不应该影响实体层。

用例

这层的软件包含特定应用的业务规则。它封装并实现了系统的所有用例。这些用例组织了实体中的数据流向,并指挥这些实体使用他们的企业域业务规则来完成用例的目标。

我们不期望这层影响实体。我们也不希望这层会在如数据库,UI,或其他常用框架这样的外部变化时被影响。这层隔离了以上关注点。

当然我们期望对于应用操作的变化会影响用例而进一步影响到这层的软件。 如果一个用例的细节变化了,那么这层的代码肯定也会被影响。

接口适配器

这层的软件是一组适配器,其将数据转换成从用例和实体最合适的格式,到对于一些类似数据库或网站这种外部设施最合适的格式。在这一层,举个例子,会包含GUI的MVC架构。Presenters, Views,与Controllers都属于这里。模型基本就是从controllers传递到用例的数据结构,并从用例返回到presenters和views。

类似的,数据被转换了,在这层,从对于实体和用例合适的结构,变成对于持久层框架使用的结构。这圈内的代码不应该知道数据库。如果数据库是一个SQL数据库,那么所有SQL都应该在这层内,特别是此层与数据库有关的部分。

这层其他适配器也需要将数据从类似外部服务的外部的结构,转换成用例和实体使用的内部结构。

框架与驱动

最外层主要组合了数据库,网络框架这样的框架和工具。在这层你除了写一些与内层环通信的胶水代码,基本不会有其他代码。

这层是所有细节存在的地方。网络是细节。数据库是细节。 我们将这些东西放在外部保证它们不会影响其他部分。

只有四个圈?

不是的,圆圈是个示意。你可能发现你需要不止4个。没有规则说你一定要有四个。 实际上,依赖规则一直存在。源代码依赖一直指向内部。当你向内部移动时抽象的层次在增加。最外部的圆是很低层的具体细节。当你内移时软件变得更抽象,并封装了高一级的策略规则。最内部的圆是最普遍的抽象层级。

跨越边界

在图的右下方是我们穿越圆圈边界的示例。它展示了Controller和Presenter与下一层的用例进行通信。注意控制流。它从controller出发,穿过用例,然后在presenter里执行。也注意下源码依赖。它们每个都指向内部的用例。

我们通常使用依赖反转原则解决这个明显的问题。在java这样的语言中,我们会整理源码依赖与控制流相反的接口和继承关系,让它们从边界正确的穿过。

例如,用例需要调用presenter。但是,这个调用不能直接进行因为会违反依赖规则。外圈的名字不能被内圈提到。所以我们的用例调用内圈的一个接口(在这个例子里是Use Case Output Port),并让外圈的presenter实现它。

架构里所有的边界穿越都用这个技巧。我们使用动态多态来创建与控制流相反的源码依赖,以便于无论在控制流的任何方向都不会违反依赖规则。

什么样的数据会穿越边界

正常来说穿过边界的数据是简单数据结构。你可以使用基本结构或简单的Data Transfer 对象。或者可以方便的进行函数赋值的数据。或者你可以打包进一个hashmap,或者将它组装成一个对象。重要的是穿过边界的是隔离,简单的数据结构。我们不想搞变通传递实体或数据库行数据。我们不想数据结构有任何违反依赖规则的依赖。

例如,很多数据库框架在查询后返回一个方便的数据格式。我们可以叫它RowStructure(行结构)。我们不想将这个行机构通过边界传递给内部的圈。这会导致内部圈需要知道外部圈的内容进而违反依赖规则。

所以当我们在边界传递数据是,要注意其应该是内部圈的格式。

结论

遵从这些简单规则并不难,并且能帮你减少以后的问题。通过将软件隔离分层,并遵从依赖规则,你可以建立一个真正可测试的系统,包含了以上所有好处。当任何系统额外部部分过时了,比如数据库或web框架,你可以容易的替换这些过时的元素。

作者:Robert C. Martin

相关推荐

甲骨文签署多项大型云协议,其一未来可贡献超300亿美元年收入

IT之家7月1日消息,根据甲骨文Oracle当地时间6月30日向美国证券交易委员会(SEC)递交的FORM8-K文件,该企业在始于2025年6月1日的202...

甲骨文获TEMU巨额合同,后者大部分基础设施将迁移至Oracle云

IT之家6月23日消息,Oracle甲骨文创始人、董事长兼首席技术官LarryEllison(拉里埃里森)在本月早些时候的2025财年第四财季和全财年财报电话会议上表示,Oracle...

Spring Boot 自定义数据源设置,这些坑你踩过吗?

你在使用SpringBoot进行后端开发的过程中,是不是也遇到过这样的问题:项目上线后,数据库连接总是不稳定,偶尔还会出现数据读取缓慢的情况,严重影响了用户体验。经过排查,发现很大一部分原因竟然...

一个开箱即用的代码生成器(一个开箱即用的代码生成器是什么)

今天给大家推荐一个好用的代码生成器,名为renren-generator,该项目附带前端页面,可以很方便的选择我们所需要生成代码的表。首先我们通过git工具克隆下来代码(地址见文末),导入idea。...

低代码建模平台-数据挖掘平台(低代码平台的实现方式)

现在来看一下数据连接。·这里是管理数据连接的空间,点击这里可以新增一个数据连接。·输入连接名称,然后输入url,是通过gdbc的方式去连接的数据库,目前是支持mysql、oracle以及国产数据库达梦...

navicat 17.2.7连接oracle数据库提示加载oracle库失败

系统:macOS15.5navicat版本:navicatpremiumlite17.2.7连接oracle测试报错:加载oracle库失败【解决办法】:放达里面找到程序,显示简介里面勾选“使...

开源“Windows”ReactOS更新:支持全屏应用

IT之家6月17日消息,ReactOS团队昨日(6月16日)在X平台发布系列推文,公布了该系统的最新进展,包括升级Explorer组件,支持全屏应用,从Wine项目引入了...

SSL 推出采用全模拟内置混音技术的模拟调音台Oracle

英国调音台传奇品牌SolidStateLogic宣布推出Oracle——一款采用全模拟内置混音技术的调音台,在紧凑的AWS尺寸机箱内集成了大型调音台的功能。该调音台提供24输入和...

47道网络工程师常见面试题,看看有没有你不会的!

你们好,我的网工朋友。网络工程师面试的时候,都会被问到什么?这个问题其实很泛,一般来说,你肯定要先看明白岗位需求写的是什么。基本上都是围绕公司需要的业务去问的。但不可否认的是,那些最基础的概念,多少也...

汉得信息:发布EBS系统安装启用JWS的高效解决方案

e公司讯,从汉得信息获悉,近日,微软官方宣布InternetExplorer桌面应用程序将于2022年6月15日正式停用。目前大部分客户都是使用IE浏览器打开EBS的Form界面,IE停用后,只能使...

36.9K star ! 推荐一个酷炫低代码开发平台!功能太强!

前言最近在逛github,看看能不能搜罗到一些对自己有帮助的开源软件。不经意间看到一个高star的java开源项目:jeecg-boot。进入在线演示版一看,感叹实在是太牛了!此开源项目不管是给来学习...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

手把手教你在嵌入式设备中使用SQLite3

摘要:数据库是用来存储和管理数据的专用软件,使得管理数据更加安全,方便和高效。数据库对数据的管理的基本单位是表(table),在嵌入式linux中有时候它也需要用到数据库,听起来好难,其实就是几个函数...

JAVA语言基础(java语言基础知识)

一、计算机的基本概念什么是计算机?计算机(Computer)全称:电子计算机,俗称电脑。是一种能够按照程序运行、自动高速处理海量数据的现代化智能电子设备。由硬件和软件组成、没有安装过任何软件的计算机称...

再见 Navicat!一款开源的 Web 数据库管理工具!

大家好,我是Java陈序员。在日常的开发工作中,常常需要与各种数据库打交道。而为了提高工作效率,常常会使用一些可视化工具进行操作数据库。今天,给大家介绍一款开源的数据库管理工具,无需下载安装软件,基...

取消回复欢迎 发表评论: