令人尖叫的架构

原文:https://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html

想像一下,你正在看一栋大楼的蓝图。建筑师为你准备了一份修建大楼的计划文档,那你从这些计划文档中能知道些什么呢?
如果你看的计划书是针对单个家庭住户的话,那么你可能会看到一个前门,一个通向客厅或者是餐厅的门厅。靠近饭厅很可能离厨房有一段很短的距离。也许厨房的旁边是扇子区,也可能是一个卧室。当你看着这些计划,你毫无疑问的就会想到你正在看的是一套房子。该架构就叫做“房子”。

或者,如果你在一座图书馆的架构时,在这个图书馆里,你很可能看到一个宏伟的入口,一个出入检查区域,阅读区,小型会议室和一排排用于放书的书架。这种架构就叫做“图书馆”。

因此,你的应用架构重点是什么呢?当你看到顶层的目录结构和在最高级别的包的源文件时,重点是医疗保健系统,或者是会计系统,或者是库存管理系统?还是Rails, 或者 Spring/Hibernate, 或者ASP呢?

架构的主题

回过头来去读Ivar Jacobson关于软件架构一书《面向对象软件工程(Object Oriented Software Engineering)》。这本书的副标题是:一种用例驱动方法(A use case driven approach)。在这本书里Ivar明确指出,软件架构是支持系统用例的结构。就像一栋房子或者是一座图书馆的计划主要关注的是这些建筑的用例,因此,一个软件应用也应该重点关注应用本身的用例。

架构并不是框架(也不应该是)。架构不应该由框架提供。框架是要使用的工具,而架构并不是。如果你的架构是基于框架,那么就不能根据你的用例。

架构的目的

好的架构主要关心用例的原因是可以让软件设计师能够安全的描述结构来支持这些用例,而不用关心框架,工具和工程环境。再回到房子的计划上,建筑设计师首先关心的是确保这个房子是可使用的,而不是确保这个房子是用什么样的砖来修建。事实上,建筑设计师必须精心设计计划来确保房主可以决定使用砖、石或者是雪松的情况得到满足。

一个优秀的软件架构允许可以推迟框架、数据库、web服务器和其他环境问题以及工具的约定。不需要立即决定用Rails、Spring、Hibernate、Tomcat或者MySql,当然直到最后的项目。一个好的架构可以很容易地改变这些主意的决定。并且强调用例,从外部考虑中来让他们解耦。

Web工程又是什么?

Web工程是一个架构吗?交付在网络上的你的系统真的就决定了你的系统架构吗?当然不是!Web只是一种展示或者发布的机制,并且你的应用架构也应该这么认为。事实上,你的应用通过Web来展示只是一个细节,不能决定你的系统结构。并且,你的应用通过Web这些事情你应该延后考虑。所以,你的系统应该忽略该如何来发布该项目的事情。你可以作为一个控制台应用程序、Web应用程序或者客户端应用程序,甚至是Web服务应用程序,对于基本架构无需过分复杂和变动。

框架只是工具

框架是非常强大和非常有用的。框架开发者往往很相信他们的框架,他们写如何利用自己框架的例子就能说明这一点。谁写的框架,其他一些写框架的开发者也对框架深信不疑。他们展示使用该框架的方式。通常情况下,这就是一个无所不包,无所不在,框架至上的思维。当然这不是你想要采取的立场。

当我们带着一双疲惫的眼睛看着每个框架时。我们抱以怀疑态度可能会有帮助,但是代价又怎样呢?我应该如何使用它,我该如何保护自己的框架免受它的影响。我该如何维护我的架构所强调的测试用例?如何防止自身的框架被这样的架构接管呢?

可测试架构

如果你的系统架构是基于用例的,如果你保持你的所有框架在同一个公平等级上。那么你应该能够不用任何替代框架来完成所有用例的单元测试。您应该不需要为了运行你的测试运行Web服务器。你不需要连接数据库来运行你的测试。您的业务对象应该是普通对象,不依赖与框架、数据库或其他复杂逻辑。你的用例对象应该和你的业务对象保持一致。所有的测试用例再一起也是可以立即可测试的,跟框架无关。

结束语

你的架构应该告诉读者这是一个系统,而不是你在系统中使用的框架。如果你构建一个医疗保健系统,当新的程序员看到该系统的源码是,他们的第一映像应该是“这就是一个医疗保健系统”。这些新的程序员应该先知道所有的系统用例,而不是先知道系统是如何实现的。他们可能过来说,“我们看到一些东西像是Model,但是View和Controller在哪儿呢?”,而你应该说,“噢,在这个时候你不需要去关心这些细节,在后面我们将会展示给你”。