[软件架构模式]-分层架构(Layered Architecture)

分层架构模式是最常用的架构模式,也被成为N层架构模式。大部分架构师、设计者、开发者都熟知该模式。它与传统的IT通信和组织结构十分匹配,因此大部分业务应用开发自然而然选择它。

模式描述

分层架构模式内部的组件被组织成水平的分层,每一层执行特定的角色。尽管分层架构模式没有指定分层的数量和类型,大部分都会分成四层:展示层(presentation)、业务层(business)、持久层(persistence)、数据库层(database)。某些情况下,业务层和持久层会合并成一个业务层,尤其是当持久化逻辑嵌入在业务层组件中。因此,小型应用可能只有三层,而大型的以及更复杂的应用可能包含五层甚至更多层。

分层架构模式的每一层对应着应用的特定角色和职责。例如,持久层负责处理用户交互和浏览器通信逻辑,业务层负责执行特定的与请求相关的业务规则。架构中的每一层将需要完成的工作进行抽象,来满足特定的业务请求。例如,展示层不需要知道也不需要关系如何获取用户数据,它只需要将信息以特定的格式展示到界面上。相似的,业务层不需要关心如何展示数据和数据从哪来,它只需要从持久层获取数据,对数据进行业务逻辑处理(计算、聚合等等),并将结果向上传递给展示层。

[软件架构模式]-分层架构(Layered Architecture)_第1张图片
图1 分层架构模式(layered architecture pattern)

分层架构的一个特性就是关注分离(separation of concerns)。层中的组件只负责本层的逻辑。例如展示层只处理展示的逻辑,业务层只处理业务逻辑。这样对组件进行分类使得在架构中易于构建具有有效的角色和职责的模块,同样易于开发、测试、管理和维护,得益于清晰的组件接口和组建的有限的作用域。

关键概念

注意在图1-2中,架构的每一层被标记为封闭的(closed)。这是分层架构模式中最重要的一个概念。封闭的层意味着,一个请求在层与层之间移动时,它必须经过它下面的层才能到达下下一层。例如,展示层产生的请求必须先经过业务层再经过持久层才能最终到达数据库层。

[软件架构模式]-分层架构(Layered Architecture)_第2张图片
图2 封闭层和请求访问流程(closed layers and request access)

为什么不允许展示层直接访问持久层或数据库层呢?毕竟,在展示层直接访问数据库层比将数据库读取信写信息层层传递更快啊。这个问题的答案在于一个关键的概念:隔离层(layers of isolation)。

层隔离概念意味着架构中某一层内的变化不会影响其他层内的组件,变化被隔离在该层内的组件之间,或许也会影响关联的层(如包含SQL语句的持久层)。如果允许展示层直接访问持久层,那么持久层中改变SQL语句会同时影响业务层和展示层,使得组件之间有很多相互依赖,应用过于紧耦合。这样的架构将会非常难以改变。

隔离层概念也意味着层与层之间是独立的,因此只知道少量的或者完全不知道其它层的内部工作原理。为了理解这个概念的强大和重要性,可以考虑将展示层从JSP改成JSF时需要做的工作量。假设展示层和业务层之间的契约保持一致,那么在转换展示层时,业务层完全不受影响,与展示层所用的UI框架类型完全无关。

虽然封闭的层促使了层隔离,使得架构架构内的变化是独立的,但是有时将一些层开放也是有意义的。例如,需要添加一个包含通用服务组件的共享服务层让业务层的组件调用时(如字符串处理类和日志类等),创建一个服务层通常是个好主意,因为架构上来说共享服务被限制在业务层调用。如果不将其独立成一个层,那展示层也能调用这些共享服务,导致访问限制难于管理。

在这个例子中,新的服务层应该放在业务层之下,这样展示层就不能直接访问它了。然而,这导致一个问题,现在业务层需要经过服务层才能到达持久层,这完全是没有意义的。这是分层架构的一个由来已久的问题,通过在架构内创建开放的层来解决。

如图3中所示,服务层标记为开放的(open),意味着请求可以跨过该开放层直接访问下一层。例子中,业务层可以不经过服务层而直接到达持久层,这样是更合理的。

[软件架构模式]-分层架构(Layered Architecture)_第3张图片
图3 开放层和请求流程(open layers and request flow)

利用层开放和封闭的概念有助于定义架构的层和请求流之间的关系,也为设计者和开发者提供了必要的信息以了解架构中各层的访问限制。没有合适的确定架构中每一层是开放还是封闭,通常会导致架构紧耦合且脆弱,难以测试、维护和部署。

案例

假设用户需要获取客户信息,如图所示。黑色箭头表示请求流动到数据库来获取客户数据,红色箭头表示请求流回到界面并显示数据。例子中,客户信息包括客户数据和订单数据。

Customer Screen用于接收请求并展示用户信息,它不知道数据在哪,怎样获取,设计几张数据库表。只要它接收了获取某个用户信息的请求,它就将请求传递给Customer Delegate模块。该模块知道业务层哪个模块能处理请求,如何访问该业务层模块,以及需要的数据(契约)。业务层的Customer Object负责聚合该业务请求所需的所有数据(在例子中就是获取客户信息)。它调用持久层的数据访问对象Customer Dao和Order Dao分别获取客户数据和订单数据。这两个数据访问对象执行SQL语句,获取相应的数据,将数据回传给业务层的Customer Object。一旦Customer Object接收到数据,它将数据进行聚合再回传给Customer Delegate,再回传给Customer Screen展示给用户。

[软件架构模式]-分层架构(Layered Architecture)_第4张图片
图4 分层架构案例

注意事项

分层架构模式是个可靠的通用模式,对于大部分应用它是个很好的开始,尤其当不知道哪种结构适合使用时。从架构角度选择该模式后,也有一些注意事项。

第一个要注意的是被称为污水池反模式(architecture sinkhole anti-pattern)。该反模式描述的是这样的场景,请求流穿过架构的很多层,每一层只有少量的甚至没有业务逻辑。例如,假设展示层响应用户的请求获取客户信息,展示层将请求传递给业务层,业务层什么也不做,仅仅将请求直接传递给持久层,持久层执行SQL语句获取数据。数据在回传过程中没有经过任何的处理。

每个分层架构都可能会有一些场景落入污水池反模式。然而关键是分析这样的请求占了多少比例。通常80-20定律可用来分析是否落入了污水池反模式。当反模式的比例比较大时,你或许考虑将某些层开放,这时要注意缺乏层隔离,会使得以后修改时比较困难。

另一个要注意的是分层架构会使应用变得庞大,即使把表示层和业务层分成了单独的部署单元。这对某些应用不需要考虑,但是也会带来一些部署的隐患,如健壮性、可靠性、性能和可伸缩性。

模式分析

下表展示了分层架构模式的通用架构特性的评级和分析。

整体灵活性

评级:低

分析:整体灵活性是快速响应环境变化的能力。尽管层隔离特性可以将变化隔离在层内,在分层结构中做一些改变也是费时费力的,因为这种模式大部分实现的整体性和通常出现的组件之间的紧耦合。

易于部署

评级:低

分析:取决于如何实现该模式,尤其是大型应用,部署将会是很大的问题。某个组件的小改动可能就需要重新部署整个应用(或者大部分)。部署需要计划或规划好,在非工作时间或周末实施。因此,分部架构模式导致不能持续集成,降低了部署的灵活性。

可测试性

评级:高

分析:因为组件是属于某一层的,测试时其它层可以被模拟或直接去掉,因此该模式相对很容易测试。开发者在隔离测试业务层时可以模拟一个展示层,也可以在测试展示层时使用模拟的业务层。

性能

评级:低

分析:尽管有些分层模式的性能还不错,但是它的特征决定了无法带来高性能,因为每个请求的处理都要穿过很多层。

可伸缩性

评级:低

分析:由于这种模式倾向于导致紧耦合,且模式的整体实现性导致难以扩展。可以把每个层分成单独的物理模块部署,或者把整个应用复制多个节点,但总体粒度太过宽泛,难以扩展。

开发容易度

评级:高

分析:分层架构在开发上相对比较容易。因为大家都很熟悉这种架构,且不难实现。因为大部分公司开发项目时都是通过层来区分技能的,分层结构模式成为大部分商业应用开发公司的首选。公司的组织架构和软件架构之间的关系被称为Conway's law

参考资料:

Software Architecture Patterns

colobu.com

你可能感兴趣的:([软件架构模式]-分层架构(Layered Architecture))