软件架构之分层架构理解
分层架构特定场景:
分层架构是一种很常见的架构模式,它也叫N层架构。分层架构适用于一个集成不同功能的系统,当我们需要把很多不同的代码集起来的时候,这种模式提供了最合理的结构。能让我们的代码有足够的灵活性去应对需求改变。当系统本身不负责或者可预期的修改很少时,则不适合用分层架构,因为这样可以增加很多不必要的代码,陷入过度设计的泥坑。不过分层架构模式是一个稳定的通用模式,这使得它成为大部分应用程序的首选,特别是当你不确定使用哪个架构的时候。没有任何一种架构模式是万能的,所以每个模式都必须有“适应场景”。而模式本身的内容,就是通过“模式定义”和“模块关系”两个层面的规定来表现出来。
分层架构解决的问题:
当软件需求变更之后,基本上是对软件代码的修改。而软件代码的修改却是程序员们最头疼的事情。因为一些大型系统,它的代码根本完全看不懂,即便是了解了部分细节后,着手修改的时候,也会碰到牵一发而动全身的问题。因为有些功能的修改,需要修改整个系统的很多部分,导致了无穷的BUG。另外就是在紧迫时间内,对于代码的修改往往只能依赖有限的一个或几个程序员,只有他们对系统最熟悉。但是,会面临工作量巨大的问题,几乎无法让更多的程序玩参与进来。假如,熟悉的程序员离职,就有可能代表了整个系统的无法维持。即便是系统能分割给几个人负责,在“集成”几个部分代码的时候,其调试和排错工作,又常常是很持久的,因为那些从来没有协作过的代码,隐藏着大量的误解和不兼容性的问题。这一切的根源只是一个最简单的事实,就是系统对于“代码耦合”的结构问题。糟糕的代码耦合让整个系统变得难以理解,难以修改,难以分工,难以集成。而分层架构就是来解决这个耦合问题的。在这个模式中,请求流只是简单的穿过层次,不留一点云彩,或者说只留下一阵青烟。比如说界面层响应了一个获得数据的请求。响应层把这个请求传递给了业务层,业务层也只是传递了这个请求到持久层,持久层对数据库做简单的SQL查询获得用户的数据。这个数据按照原理返回,不会有任何的二次处理,返回到界面上。每个分层架构或多或少都可能遇到这种场景。关键在于这样的请求有多少。80-20原则可以帮助你确定架构是否处于反污水模式。大概有百分之二十的请求仅仅是做简单的穿越,百分之八十的请求会做一些业务逻辑操作。然而,如果这个比例反过来,大部分的请求都是仅仅穿过层,不做逻辑操作。那么开放一些架构层会比较好。不过由于缺少了层次隔离,项目会变得难以控制。
分层架构的解决方案:
分层架构里的组件被分成几个平行的层次,每一层都代表了应用的一个功能。一般情况下,结构大多分成四层:展示层,业务层,持久层,和数据层。有时候,业务层和持久层会合并成单独的一个业务层,尤其是持久层的逻辑绑定在业务层的组件当中。因此,有一些小的应用可能只有3层,一些有着更复杂的业务的大应用可能有5层或者更多的分层。例如:展示层负责处理所有的界面展示以及交互逻辑, 业务层负责处理请求对应的业务。架构里的层次是具体工作的高度抽象,它们都是为了实现某种特定的业务请求。例如:展示层并不需要关心怎样得到用户数据,它只需在屏幕上以特定的格式展示信息。 业务层并不关心要展示在屏幕上的用户数据格式,也不关心这些用户数据从哪里来。它只需要从持久层得到数据,执行与数据有关的相应业务逻辑,然后把这些信息传递给展示层。分层架构的一个突出特性是组件间关注点分离。
分层架构中的每一层都着特定的角色和职能。它们中的每一层都有着特定的角色和职能。架构里的层次是具体工作的高度抽象,它们都是为了实现某种特定的业务请求。分层的模式的规定非常简单有效:①每个模块必须属于某个层次,提供给“第N+1层”(上层)服务;同时委派任务给“第N-1层”的模块。②任何一个模块。都不得逆层次调用:属于第N层模块的,不得调用,第N+1层或者以上层次的模块。③任何一个模块,都不得跨层调用:属于第N层的模块,不应该调用第N-2层或者更下层的模块。以业务逻辑特征建模,使用分层模式,往往需要我们在大脑里对问题领域进行层次抽象,这种抽象是可信赖的原则,就是按照业务逻辑去做。比如现实业务中有一个角色,我们就建立一个角色的模块,如果我们有一个场景,就以此为名建立一个这样的模块。以业务逻辑建立的模块,本身也会让系统更容易被理解,因为在代码里能找到和现实中一一对应的概念。多亏了组件分离,让我们更容易构造有效的角色和强力的模型。 这样应用变的更好开发,测试,管理和维护。
分层架构的实例:
实例1:
比如,存在一个复杂功能的多人在线社区系统,它的服务器端是我们需要重点讨论的对象。这个产品的服务器端必须满足多样功能:如,玩家移动到不同的场景中,玩家移动到不同的场景中,玩家可以换上不同的服装,可以互相加好友并且可以互相聊天,同时还有广播频道的聊天功能,每个玩家还有终极的资料库和背包,另外还有各种运营活动。
在最初的开发过程中,我们需要针对每一个需要开发的功能,建立一个模块。这些模块通过单独和客户端、数据库的操作,完成所需功能。如果要开发新的功能,就重写一个这样的模块。这种架构在一开始的时候就有效的,但是随着产品的功能被不断的开发出来,模块的数量也哎增多,但是就潜藏了一个问题。
这个问题的爆发,就是随着任务系统的功能的增多而出现的。因为任务系统本质上是很多其他模块功能的功能支持。如需要玩家去某个场景,获得了某个东西,然后添加了一个好友,或者换了某个时装,发一句消息等等。这样的任务功能实现,被迫要修改很多个模块的代码,因为每个模块都只有最基本的“自由使用”功能的代码,编程接口都仅仅是面向客户端的,而数据结构都是直接SQL到数据库的。这种需要组合的功能需求,以及获得功能的结果状况,都是其接口上没有写的。这导致了非常复杂的,持续的代码修改。因为任务的内容是时常会变化的。所以这个时候,我们就需要重构整个架构。把架构从一字排开的设计,修改成可以多个层次互相调用的模块。这些模块之间的接口,有面向客户端的也有面向其他模块的,这样我们就能直接调用那些现成的功能,组合开发出更复杂强大的功能。不管任务系统如何变化,我们都可以不用重写那些已经实现的功能,这让整个系统成为可以应对这种需求变化的关键。这就是一个分层架构的实例。
实例2:
想象一个场景,用户发出了一个请求要获得客户的信息。在这个例子中,用户信息由客户数据和订单数组组成(客户下的订单)。用户界面只管接受请求以及显示客户信息。它不管怎么得到数据的,或者说得到这些数据要用到哪些数据表。如果用户界面接到了一个查询客户信息的请求,它就会转发这个请求给用户委托(Customer Delegate)模块。这个模块能找到业务层里对应的模块处理对应数据(约束关系)。业务层里的customer object聚合了业务请求需要的所有信息(在这个例子里获取客户信息)。这个模块调用持久层中的 customer dao 来得到客户信息,调用order dao来得到订单信息。这些模块会执行SQL语句,然后返回相应的数据给业务层。当 customer object收到数据以后,它就会聚合这些数据然后传递给 customer delegate,然后传递这些数据到customer screen 展示在用户面前。
优点:
1.结构简单,容易理解和开发
2.不同技能的程序员可以分工,负责不同的层,适合大多数软件公司的组织架构
3.每一层都可以独立测试,其他层的接口可以模拟解决。
缺点:
1.一旦环境变化,需要代码调整或增加工能时,通常比较麻烦和费时
2.部署比较麻烦,即时只修改一个小地方,往往需要整个软件重新部署,不容易做持续发布。
3.软件升级时,可能需要整个服务停止。
4.扩展性差,用户请求大量增加时,必须一次扩展每一层,由于每一层内部是耦合的,扩展会很困难。