干净的架构The Clean Architecture_软件架构系列
本文转载自:https://www.jdon.com/artichect/the-clean-architecture.html ,这个博客站很有历史了,博主经常翻译Github大牛的文章,值得墙裂推荐。
干净的架构The Clean Architecture
这是著名软件大师Bob大叔提出的一种架构,也是当前各种语言开发架构。干净架构提出了一种单向依赖关系,从而从逻辑上形成一种向上的抽象系统。
我们经常听说过如下各种架构:
- 六边形架构Hexagonal Architecture (也称为 端口和适配器) 这是由Alistair Cockburn 提出,被Steve Freeman和 Nat Pryce在他们的书籍Growing Object Oriented Software中采取的。
- Onion Architecture 作者Jeffrey Palermo
- Screaming Architecture Bob大叔
- DCI 由James Coplien和Trygve Reenskaug推动
- BCE Ivar Jacobson在他的书籍Object Oriented Software Engineering: A Use-Case Driven Approach提出
虽然这些架构在细节上都略有不同,但他们都非常相似。它们都具有相同的目标,那就是分离关注。他们都通过软件分层来实现这种分离。至少有一个层代表业务规则,而另一个层用于接口。
这些架构产生的系统特点是:
- 独立的框架. 这样的架构并不依赖与应用软件的具体库包,这样可以将框架作为工具,而不必将你的系统都胡乱混合在一起。
- 可测试. 业务规则能够在没有UI和数据库 或Web服务器的情况下被测试。
- UI的独立性. UI改变变得容易,不必改变系统的其余部分,一个Web UI能被一个控制台或专门的图形UI替代, 这些读不必更改业务核心规则。
- 数据库的独立性. 你能够在Oracle或SQL Server Mongo, BigTable, CouchDB,或之间切换, . 你的业务规则不会和数据库绑定
- 独立的外部代理,其实你的业务规则可以对其外面的技术世界毫无所知,比如是否使用了MVC或DCI都可以不关心。
这种干净的架构图如下:
依赖规则Dependency Rule
上图中同心圆代表各种不同领域的软件。一般来说,越深入代表你的软件层次越高。外圆是战术实现机制,内圆的是战略核心策略。
使此体系架构能够工作的关键是依赖规则。这条规则规定源代码只能向内依赖,在最里面的部分对外面一点都不知道,也就是内部不依赖外部,而外部依赖内部。这种依赖包含代码名称,或类的函数,变量或任何其他命名软件实体。
同样,在外面圈中使用的数据格式不应被内圈中使用,特别是如果这些数据格式是由外面一圈的框架生成的。我们不希望任何外圆的东西会影响内圈层。
实体Entities
实体封装的是企业业务规则,一个实体能是一个带有方法的对象,或者是一系列数据结构和函数,只要这个实体能够被不同的应用程序使用即可。
如果你没有编写企业软件,只是编写简单的应用程序,这些实体就是应用的业务对象,它们封装着最普通的高级别业务规则,你不能希望这些实体对象被一个页面的分页导航功能改变,也不能被安全机制改变,操作实现层面的任何改变不能影响实体层,只有业务需求改变了才可以改变实体。
用例Use Cases
在这个层的软件包含应用指定的业务规则,它封装和实现系统的所有用例,这些用例会混合各种来自实体的各种数据流程,并且指导这些实体使用企业规则来完成用例的功能目标。
我们并不期望改变这层会影响实体层. 我们也不期望这层被更外部如数据库 UI或普通框架影响,这层也是因为关注而外部分离的。
我们期望应用层面的技术操作都不能影响用例层,如果需求中用例发生改变,这个层的代码才会发生改变。
接口适配器Interface Adapters
这一层的软件基本都是一些适配器,主要用于将用例和实体中的数据转换为外部系统如数据库或Web使用的数据,在这个层次,可以包含一些GUI的MVC架构,表现视图 控制器都属于这个层,模型Model是从控制器传递到用例或从用例传递到视图的数据结构。
通常在这个层数据被转换,从用例和实体使用的数据格式转换到持久层框架使用的数据,主要是为了存储到数据库中,这个圈层的代码是一点和数据库没有任何关系,如果数据库是一个SQL数据库, 这个层限制使用SQL语句以及任何和数据库打交道的事情。
框架和驱动
最外面一圈通常是由一些框架和工具组成,如数据库Database, Web框架等. 通常你不必在这个层不必写太多代码,而是写些胶水性质的代码与内层进行粘结通讯。这个层是细节所在,Web技术是细节,数据库是细节,我们将这些实现细节放在外面以免它们对我们的业务规则造成影响伤害。
只有四个圈层吗?
这个圆圈图是示意性的。您可能会发现您需要的不仅仅是这四个。也没有规定说你必须始终只有这四个。然而,依赖规则始终适用。源代码的依赖关系总是由外向内。当你越向内时,抽象水平越高。而最外面的一圈是低层次的具体细节。当你越向内时软件变得越为抽象,封装了更高层次的策略。
跨边界流程
在图的右下方是我们如何越过圆边界的例子。它显示控制器和界面之间是如何和用例进行通信的。注意控制流程。它开始于控制器,通过用例,然后在界面处执行。还要注意源代码的依赖关系。他们中的每一个点都是指向内部用例。我们通常使用依赖注入来实现这种依赖。
那么数据如何跨层流动呢?
通常跨层的数据是简单的数据结构。如果你喜欢你可以使用基本结构或简单的数据传输对象DTO。或可以函数可以调用数据参数。或者你可以打包到哈希表中,或为它建构一个对象。最重要是跨层传递是孤立的、 简单的数据结构。
我们不想让这个数据结构是一个实体或数据库记录,因为我们不希望它们有任何的依赖关系,这会违反了依赖规则。例如,许多数据库框架在查询响应中返回一个方便的数据格式。我们可能会要求这对这个记录重构,因为我们不想要跨层向内传递数据库记录。这就违反了依赖规则,它会迫使内圈要知道关于外圈的东西。所以当我们跨层传递数据,它总是以对内圈最方便的形式。
总结
符合这些简单的规则将会节省您大量的头痛开发。通过将软件分离到各种层,并符合依赖规则,这样您创建一个系统本质上是可测试,这意味着很多好处。
干净的架构The Clean Architecture_软件架构系列的更多相关文章
- 干净的架构The Clean Architecture
干净的架构The Clean Architecture 这是著名软件大师Bob大叔提出的一种架构,也是当前各种语言开发架构.干净架构提出了一种单向依赖关系,从而从逻辑上形成一种向上的抽象系统. 我们经 ...
- 软件架构系列二:Clean架构
外圈的层次可以依赖内层,反之不可以:内圈核心的实体代表业务,不可以依赖其所处的技术环境. 这是著名软件大师Bob大叔提出的一种架构,也是当前各种语言开发架构.干净架构提出了一种单向依赖关系,从而在逻辑 ...
- 清晰架构(Clean Architecture)的Go微服务
我用Go和gRPC创建了一个微服务项目,并试图找出最好的程序结构,它可以作为我其他项目的模板.我还将程序设计和编程的最佳实践应用于Go Microservice程序,例如清晰架构(Clean Arch ...
- 清晰架构(Clean Architecture)的Go微服务: 程序设计
我使用Go和gRPC创建了一个微服务,并将程序设计和编程的最佳实践应用于该项目. 我写了一系列关于在项目工作中做出的设计决策和取舍的文章,此篇是关于程序设计. 程序的设计遵循清晰架构(Clean Ar ...
- 清晰架构(Clean Architecture)的Go微服务—重大升级
去年,我创建了一个清晰架构(Clean Architecture)微服务框架,它功能强大,但有些重.我写了一个系列文章来讲述它,请参阅"清晰架构(Clean Architecture)的Go ...
- [Android]一个干净的架构(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5276587.html 一个干净的架构 原文:https://b ...
- 清晰架构(Clean Architecture)的Go微服务: 程序结构
我使用Go和gRPC创建了一个微服务,并试图找出最佳的程序结构,它可以用作我未来程序的模板. 我有Java背景,并发现自己在Java和Go之间挣扎,它们之间的编程理念完全不同.我写了一系列关于在项目工 ...
- 清晰架构(Clean Architecture)的Go微服务: 设计原则
我最近写了一个Go微服务应用程序,这个程序的设计来自三个灵感: 清晰架构"Clean Architecture"¹ and SOLID (面向对象设计)² 设计 原则³ Sprin ...
- 清晰架构(Clean Architecture)的Go微服务: 程序容器(Application Container)
清晰架构(Clean Architecture)的一个理念是隔离程序的框架,使框架不会接管你的应用程序,而是由你决定何时何地使用它们.在本程序中,我特意不在开始时使用任何框架,因此我可以更好地控制程序 ...
随机推荐
- jmeter-提取器之JSON Path PostProcessor
后置处理器添加 json path postprocessor. 用处: 当前接口响应返回的json中提取内容,作为变量可以在不同的请求中传递. 1. json path postprocessor ...
- 移动web 的viewport设置注意事项的详细解释 六一快乐=-_-_
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 洛谷P3582 [POI2015]KIN
题目描述 共有\(m\)部电影,编号为\(1--m\),第\(i\)部电影的好看值为\(w[i]\).在\(n\)天之中(从\(1~n\)编号)每天会放映一部电影,第\(i\)天放映的是第\(f[i] ...
- JS事件冒泡机制和兼容性添加事件
本篇文章主要来讲讲 事件的冒泡机制 和 添加事件的几种方法. 一. JS的时间传递顺序: 捕获阶段 -> 目标阶段 -> 冒泡阶段 捕获阶段是指从父层往子层找.比如 <body> ...
- 基于SSL加密的vsftpd 服务器搭建和配置
基于SSL加密的VSFTPD 服务器搭建和配置 1.安装 ubuntu系统:apt-get install vsftp lftp centos系统:yum install -y vsftpd ftp ...
- 自动检测GD库支持的图像类型
以下代码通过自动检测GD库支持的图像类型 来写出移直性更好的PHP代码 <?php if(function_exists("imagegif")){ header(" ...
- 练习十七:python辨别数据类型
关于python辨别数据类型可以用python type()方法,那么想要查看一串字符中每项类型,并逐一输出要怎么处理?看下我是怎么处理的 习题要求:输入一行字符,分别统计其中英文字母.数字.空格.和 ...
- Spring RestTemplate GET 请求参数
@Test public void testUpdateProfitJson_GET_Params() throws BusinessException { String apiURL="U ...
- Python3.5 调用Ansible 执行命令
ansible.py #!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import tempfile from collections ...
- Java图形界面开发—简易记事本
在学习了Java事件之后,自己写了一个极其简单的记事本.用到了MenuBar,Menu,MenuITem等控件,事件包括ActionListener以及KeyListener. 代码如下: ...