以下内容为原创,欢迎转载,转载请注明
来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5276587.html

一个干净的架构

原文:https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html

在过去几年中我们能看到的一系列关于系统架构的思想。它们包括:

尽管这些书在细节上有些不同之处,但是它们是非常相似的。从分离的观点上来讲它们都有着同样的目标。它们都是通过软件分层来实现分离的。每一个都至少有一层是用于业务规则,另外一层用于接口。

这些架构生产系统:

  1. 框架独立性。架构并不依赖于已经存在的某些库的有负载的特性。这允许你作为工具去使用框架,而不是把你的系统强塞到限制和约束中。

  2. 可测试性。业务规则可以脱离UI、数据库、web服务器和其它外部元素去进行测试。

  3. UI的独立性。UI可以在不修改系统其它地方的情况下很容易地被改变。比如,一个Web UI可以使用console UI替换,而不改变任何业务规则。

  4. 数据库独立。你可以使用Mongo、BitTable、CouchDB或者其它来置换Oracle或SQL Server。你的业务规则不会被数据库束缚。

  5. 外部代理的独立性。事实上,你的业务规则根本不知道外面的世界。

这篇文章顶部的图表就是尝试所有这些结构到单个可操作的思想中去。

依赖准则

同心圆表示不同软件的区域。一般情况下,走得越远,软件水平也会变得越高。外面的圆是机制,而内部的圆是政策。

使得这个架构可行的最重要的规则是 依赖准则 。这个准则指 代码的依赖 只能 向内 。没有一个内部圆可以知道外部圆的任何东西。尤其是在内部圆声明的东西名字不能被内部圆中的代码提到。这里包括方法、类、变量、或者其它软件实体的名字。

同样的原因,外部圆中用到的数据格式不能被内部圆使用,尤其是这些格式是被外部圆中的框架生成的。我们不希望任何在外部圆中的东西影响到内部圆。

Entities

实体封装了 企业级 业务规则。一个实体可以是一个有方法的对象,或者有一系列的数据结构和函数。只要这个实体可以被很多不同企业中的应用使用就没关系。

如果你没有一个企业,并且只是编写单个的应用程序,那么这些实体就是应用程序中的业务对象。它封装了大部分一般的和高级别的规则。它们最不可能在外部改变的时候被改变。比如,由于安全你不希望这些对象被导航页面改变而影响。没有特别的可操作的改变可以影响实体层。

用例

软件在这一层包含应用程序指定的业务规则。它封装和实现了这个系统的所有用例。这些用例转化数据流到实体和从实体转化到数据流,然后这些实体直接使用它们企业范围的业务规则来达到用例的目的。

我们不期望改变这一层来影响到实体。我们也不希望这一层被外部的改变,比如数据库、UI、任何常见的框架等影响。在这一层在这的观点上是被孤立的。

然而,我们要做的是希望应用程序操作的改变会影响到软件的用例,所以应该是在这一层。如果用例的细节改变了,那么这一层的某些代码当然也会受到影响。

接口适配器

在软件的这一层是一系列的适配器,通过最方便的用例和实体转换数据格式,最方便的外部代理格式有数据库或者Web等。在这一层,举个例子,将会完整包含 GUI 的 MVC 架构。Presenters、Views、 Controllers 都属于这里。Models有可能仅仅是数据结构,它们从 contrllers 被传入到用例中,然后从用例到 presenters 和 views。

同样的,在这一层,数据会被转换,从最方便的方式如实体和用例,转换到使用的用于持久框架的最方便的方式,即数据库。
这个圆中没有代码可以向内知道任何关于数据库的东西。如果数据库是一个 SQL database,那么所有 SQL 应该在这一层被限制,特别是在这一层需要进行数据库操作的部分。

在这一层也有必要从一些外部形式去转换数据,比如一个外部服务,转化为内部用例和实体使用的形式。

框架和驱动

最外层通常是框架和工具,通常是数据库、Web 框架等的组合。通常你不需要在这一层编写太多的代码,除了一些用于向内圈进行通信的固定代码。

这一层是所有细节走向的地方。Web是一个细节。数据库是一个细节。我们把这些东西放置在外部,这样它们就难以造成伤害。

只有四个圆?

不,这些圆只是简图。你可能会需要多于这四个圆。这里并没有一个规则来让你必须要使用这四个圆。然而,依赖规则 总是适用的。代码依赖总是指向内部。当你向内移动时,抽象级别增加。最外层的圆是最低级别的具体细节。当你向内移动,就会变得更加抽象和更高级别策略的封装。最内部的圆是最通用的。

跨越边界

右下方的图是一个我们怎么去跨越圆的边界的例子。它展示了 Controllers 和 Presenters 通过下一层使用用例进行通信。注意控制流。它在controller中开始,通过用例,然后再Presenter中执行。也要注意代码的依赖。它们每一个都是向内指向用例。

我们通常使用 依赖反转准则 来解决这个明显的矛盾。在像Java的语言中,举个例子,我们使用了interfaces和继承关系,这样代码依赖关系控制权被反转,达到跨越边界的目的。

举个例子,考虑到用例需要调用Presenter。然而,这些调用必须不能是直接的,因为它会违反_依赖准则_:内部圆不能提到外部圆中的任何名字。所以我们这种情况我们会调用在内部圆中的接口(就像这里展示的 Use Case Output Port)),然后在外部圆中的Presenter去实现它。

同样的技术在架构的所有跨越边界的地方被使用到。我们利用动态代理的优势去创建代码依赖来达到控制反转,所以我们可以确保无论什么方向的 依赖准则 控制流都能有效。

什么数据跨越边界。

典型的跨越边界的数据就是简单的数据结构。如果你喜欢你可以使用基本结构或者简单的数据传输对象。或者是方法调用时的简单的参数数据。或者你可以把它放进一个HashMap,或者构建它到一个对象中。重要的是分离的、简单的数据结构跨越过边界。我们不希望去欺骗并传递 Entities 或者数据库的行。我们不希望数据结构有任何的违反 依赖准则 的依赖。

举个例子,很多数据库框架通过一个查询返回一个方便的数据形式的响应。我们可能称它为一个RowStructure。我们不希望这个行结构向内跨越边界。这将违反 依赖准则 因为这将强制一个内部圆去知道外部圆的一些东西。

所以当我们跨越边界传递数据时,它对于内圆来说总是以最方便的形式的。

遵守这些简单的规则并不难,前进的道路上会解决很多头疼的事情。通过分离软件到不同层次,并遵守 依赖准则 ,你将会创建一个本质上可测试的系统,这意味这所有的好处。当任何系统外置的部分变得过时,就像数据库,或者web框架,你可以在最小的改动下替换这些外置元素。

[Android]一个干净的架构(翻译)的更多相关文章

  1. Android一个炫酷的树状图组织架构图开源控件实现过程

    Android一个炫酷的树状图组织架构图开源控件 文章目录 [1 简介] [2 效果展示] [3 使用步骤] [4 实现基本布局流程] [5 实现自由放缩及拖动] [6 实现添加删除及节点动画] [7 ...

  2. Android开发-浅谈架构(一)

    写在前面的话 嗯 聊聊架构. 这段时间一直在维护旧项目. 包括自己之前写的新项目 越来越发现 一个架构清晰的项目往往让人赏心悦目.不至于在一个bug丢过来之后手足无措.包括以后别人接收自己的项目 能很 ...

  3. 干净的架构The Clean Architecture_软件架构系列

    本文转载自:https://www.jdon.com/artichect/the-clean-architecture.html ,这个博客站很有历史了,博主经常翻译Github大牛的文章,值得墙裂推 ...

  4. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    相关:http://www.cnblogs.com/wytiger/p/5996876.html 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于 ...

  5. Android群英传》读书笔记 (1) 第一章 Android体系与系统架构 + 第二章 Android开发工具新接触

    第一章 Android体系与系统架构 1.Dalvik 和 ARTDalvik好比是一辆可折叠的自行车,平时是折叠的,只有骑的时候,才需要组装起来用.ART好比是一辆组装好了的自行车,装好就可以骑了. ...

  6. Android 5.1 Camera 架构学习之Camera初始化

    Android Camera 采用C/S架构,client 与server两个独立的线程之间(CameraService)使用Binder通信. 一 CameraService的注册. 1.手机开机后 ...

  7. Android Studio tips and tricks 翻译学习

    Android Studio tips and tricks 翻译 这里是原文的链接. 正文: 如果你对Android Studio和IntelliJ不熟悉,本页提供了一些建议,让你可以从最常见的任务 ...

  8. 干净的架构The Clean Architecture

    干净的架构The Clean Architecture 这是著名软件大师Bob大叔提出的一种架构,也是当前各种语言开发架构.干净架构提出了一种单向依赖关系,从而从逻辑上形成一种向上的抽象系统. 我们经 ...

  9. Android群英传笔记——第一章:Android体系与系统架构

    Android群英传笔记--第一章:Android体系与系统架构 图片都是摘抄自网络 今天确实挺忙的,不过把第一章的笔记做一下还是可以的,嘿嘿 1.1 Google的生态圈 还是得从Android的起 ...

随机推荐

  1. Polynomial Library in OpenCascade

    Polynomial Library in OpenCascade eryar@163.com 摘要Abstract:分析幂基曲线即多项式曲线在OpenCascade中的计算方法,以及利用OpenSc ...

  2. String,StringBuffer与StringBuilder的区别??

    转自http://blog.csdn.net/rmn190/article/details/1492013 String 字符串常量 StringBuffer 字符串变量(线程安全) StringBu ...

  3. Web APi之手动实现JSONP或安装配置Cors跨域(七)

    前言 照理来说本节也应该讲Web API原理,目前已经探讨完了比较底层的Web API消息处理管道以及Web Host寄宿管道,接下来应该要触及控制器.Action方法,以及过滤器.模型绑定等等,想想 ...

  4. Cmd Markdown编辑器简明语法手册

    标签: Cmd-Markdown 1. 斜体和粗体 使用 * 和 ** 表示斜体和粗体. 示例: 这是 斜体,这是 粗体. 2. 分级标题 使用 === 表示一级标题,使用 --- 表示二级标题. 示 ...

  5. Netty介绍

    Netty是由JBOSS开发的高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输等协议的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Li ...

  6. js 对cookie 的操作

    <!DOCTYPE html> <html> <head> <script> function setCookie(cname,cvalue,exday ...

  7. 搭建SSH详细步骤及相关说明

    因为手里已有相关jar,为方便我搭建的是:Struts2.0+Hibernate3.3+Spring3.0,数据库:MySQL 如果想搭建最新的,在官网上下载最新jar即可. 这里会对比MyEclip ...

  8. canvas 图片拖拽旋转之一——坐标转换translate

    引言 对canvas中绘制的图片进行旋转操作,需要使用ctx.translate变换坐标系,将图片旋转的基点设为坐标系的原点,然后ctx.rotate旋转. 这个时候,因为canvas坐标系发生了旋转 ...

  9. spring boot 调试 - 热部署

    maven gradle Maven: 命令行方式: mvn spring-boot:run -Drun.jvmArguments="-Xdebug -Xrunjdwp:transport= ...

  10. Nancy之基于Self Hosting的补充小Demo

    前面把Hosting Nancy with ASP.NET.Self Hosting Nancy和Hosting Nancy with OWIN 以demo的形式简单描述了一下. 这篇是为Self H ...