架构分解
4.1 架构分解
http://www.ibm.com/developerworks/cn/rational/1312_wanggb_arch/index.html
架构分解是架构设计过程中非常关键的一步。除了识别架构元素,对大规模的软件系统,分解还是解决非功能需求的重要手段。比如解决可伸缩性、可用性、可管理性等问题,在架构的多个层面进行了分解:
- 在应用层面,按照功能或 SOA 服务进行分解,将系统垂直拆分为多个应用池(应用池中的服务是无状态的)。每个应用池中有多个应用(水平拆分),可以独立灵活地进行伸缩。
- 在数据层面,对数据进行垂直拆分(分库)和水平拆分(数据分片 DB Sharding);
将分布式事务拆分成多个本地事务独自提交,避免分布式事务。
1、为了正确的进行分解,需要遵循一些分解原则:
低耦合、高内聚:“分解的主要难点在于怎么分。分解策略之一是按容易求解的方式来分,之二是在弱耦合处下手,切断联系”。在弱耦合处下手,切断联系。太精辟了!高内聚、低耦合也是软件设计的基本原则,软件设计中的很多设计原则其实都可以认为它的派生或具体化,如单一职责原则、依赖倒置原则、模块化封装原则,这些原则在架构分解中也是适用的。
层次性:分解通常是先业务后技术,循序渐进,先逻辑后物理,从上到下逐级进行分解展开:
系统->子系统->模块->组件->类。
正交原则:和物理学中的正交分解类似,架构分解出的架构元素应是相互独立的,在职责上没有重叠。
抽象原则:架构元素识别,在较大程度上是架构师抽象思维的结果,
架构师应该具备在抽象概念层面进行架构构思和架构分解的能力。
稳定性原则:将稳定部分和易变部分分解为不同的架构元素,稳定部分不应依赖易变部分。
根据稳定性原则,将通用部分和专用部分分解为不同的元素;
将动态部分和静态部分分解为不同的元素;将机制和策略分离为不同的元素;
将应用和服务分离。
复用性原则:就是对知识的重用.重用类似系统已有的架构设计、设计经验、成熟的架构模式。或参考模型、设计模式、领域模型、架构思想等, 因为它们已经在不同的层次上分解识别出了许多架构元素,或者指出了一些分解方向,对我们的架构分解具有借鉴和指导作用。
例如 IBM SOA 解决方案参考模型对 SOA 服务化具有重要的指导意义,
我们可以参照它对系统进行初步的架构分解。
2、架构分解的过程模型:
对复杂的系统,特别是前人没有做过的新系统,通常难以一下子设计出合适的架构。在架构设计的初期,通常都要经历一个不断探索的阶段。在架构设计过程中,架构分解是必不可少的的关键步骤。如何进行架构分解?从哪里入手开始进行分解?我们需要有一个架构分解的过程模型来指导分解过程,启发和探索架构分解的维度和线索,提高架构分解的效率。
架构分解过程模型如下图 所示,是一个迭代的模型。通过这个迭代的分解,从无到有、从粗到细、从模糊到清晰,一步步精(细)化、丰富架构。迭代的过程也是一个否定之否定的过程,随着分解的逐步推进或系统的架构演化,后面的分解除了会识别出新的架构元素,也可能会对先前识别出的架构作出调整。
依次在 4 个域中进行架构分解,基本顺序是先业务后技术,通过多维度多层次的分解将关注点分离。
A 业务域分解:先从业务域进行分解,狭义的业务域具有商业的概念,从这个概念来看,有的系统没有业务域,但如果宽泛一点来看,业务域就是问题域(问题空间),问题域总是存在的。首先是从系统需求入手,寻找业务域中的分解维度,将架构从业务域层面进行大尺度(大粒度)的分解。在业务域中进行分解,通常采用的分解维度是根据业务主题,将系统分解为多个子系统,每个子系统聚焦于一个独立的业务主题,子系统间具有清晰的边界。例如对某零售系统,我们可以根据业务主题维度进行架构分解,初步划分出:主数据子系统、采购子系统、货品管理子系统、会员子系统、销售子系统、营运子系统、订单中心子系统等。对业务域分解不应只局限于基于业务主题的分解,根据具体情况,还可能有其他的分解维度。一个通用的发现分解维度的方法是试着从领域模型和需求分析文档中寻找名词和形容词,将文档中的核心概念(名词和形容词)作为分解的候选分解维度或分解线索。在业务域的分解中,我们要和业务(行业)专家密切交流,多研究业务架构、适当考虑企业战略,这样可在一定程度上保证架构分解的合理性。
B 业务功能域分解:通过对业务流程和用例进行分析,根据功能职责,进行垂直和水平分解,识别出业务功能或业务服务,将它们归类到子系统中相应模块中去。对业务域功能域分解,一个通用的方法是试着通过动词来将子系统拆分为多个服务;另一个是根据资源类型(名词)来将系统拆分为服务,每个服务负责实现对应资源上的一组操作。例如根据资源类型(会员、商品等),对电商系统,可分解识别出会员查询服务和会员管理模块、商品服务等。这两步的架构分解都是纯业务上的,不涉及技术,但要这两步分解出的架构元素要映射到技术域中去实现,或用来帮助架构师推导出技术域的对应架构元素。
C 技术域分解:是从技术角度对系统和模块进行分解。在该阶段,通常会选取关键的需求(包括功能需求和非功能性需求)和已分解出的模块或子系统,结合当前的 IT 技术(技术框架、架构模式、参考架构、中间件、业务平台)和架构思想、架构经验、开发人员的技能以及系统的上下文环境等,进一步进行架构分解。例如很多系统采用 MVC、多层架构模式、SOA、事件驱动架构等技术或思想进行技术域中的架构分解。对电商交易子系统的订单流程,考虑到要需要灵活支撑多种交易流程和解耦流程层与业务逻辑层的需要,按照 IBM SOA 的参考架构可以分拆出流程层、服务层等,在流程层中采用流程引擎技术。在技术域分解中,对功能需求,横切(分层)竖割是一种常用的分解手法。
对非功能需求,可将性能、伸缩性、可用性等作为维度对系统进行分解,
在非功能需求分解战术中将专门说明这些维度的分解技术(称为战术)。
在业务域和业务功能域中分解出来的架构元素,考虑到技术实现,在映射到技术域时,可能要对架构元素进行修改或作一些微调,业务域和业务功能域中分解出的架构元素通常会进一步分解为技术域中的多个架构元素。
例如在业务功能域分解出的会员查询服务模块,在技术域中分解时,考虑到有多个不同类型的调用方会使用该服务,并且这些调用方需要的查询接口差异较大,调用频率等也不一样,那我们可能会对每个调用方拆分出独立的查询接口模块,这样也避免了胖接口,相关的 DAO 类也是在技术域中新产生的。
在从模块分解到类的过程中(假设有些模块要分解到类级别),需要进行静态和动态的分析以便识别出类元素。
首先是根据业务域需求,建立领域模型,识别出领域(概念)类,再将领域类映射到技术域中的设计类(实体类),也就是领域类可帮助我们识别推导出部分设计类。再基于具体用例,进行鲁棒分析和序列图设计,考虑技术上的实现和采用的技术架构,例如采用一些技术框架和类库或工具类,如 ibatis 框架,就会识别出另一些设计类(边界类、控制类)或引入一些新的设计类,这些引入的类可能直接来自框架或类库,或是继承框架中的类(成为框架类的子类)。
通常设计过程不会就此结束,考虑到开发维护和设计质量等因素,
我们会运用一些设计原则(如高内聚低耦合、单一职责、信息专家等)、设计模式、重构模式等对设计进行进一步的优化,这时又会产生识别出一些设计类,通常在这一步会对我们的设计进行一些修改和调整,例如采用工厂方法设计模式,会引入工厂方法类,我们的序列图就要修改。这样我们最终完成了一个完整的设计。
因为要考虑技术域,所以对整个分析设计来说,它是源于业务但要高于业务。
在技术域的分解中,对公共的技术需求应全盘考虑,抽象出底层的公共技术基础设施,例如定时任务在许多子系统中都存在,此时可能会规划一个定时任务框架和定时任务执行系统。也可能会采用一些成熟的框架和中间件技术,如消息中间件、ESB 等。
技术域的分解通常是比较复杂的,这一方面来源于问题域的本质复杂性,特别是各种非功能性需求的复杂性,需要架构师掌握应对这些需求的常见模式。另一方面也是由于 IT 新技术的日新月异,要求架构师对技术敏感,与时俱进。
要注意的是,当在技术域分解中碰到困难时,可以再回到业务域中去寻找答案和线索。例如为了解决某计费系统中的性能和可伸缩性问题,可在业务域中寻找名词和形容词,发现可以根据付费类型(预付费和后付费)将系统初步分拆为预付费系统和后付费系统。对网络通讯系统,可以根据请求消息中的某些属性对消息处理系统进行拆分或根据客户端类型等进行拆分。
D 涉众域分解:全面考虑各类涉众在架构层面的关键需求,特别是非功能需求,例如性能需求、可伸缩性需求等,进一步对系统进行分解。
涉众域分解包括了前面说的业务域分解、业务功能域分解、技术域分解,通常涉众域分解和它们有部分是重叠的,例如在技术域和涉众域中都有性能方面的架构分解。涉众域分解保证我们的分解是完备的,没有遗漏。在涉众域的分解过程中,很可能会产生新的子系统,例如考虑用户的性能方面的需求,可能会分解出分布式数据缓存子系统(也可能在技术域分解中就已经考虑到了)。涉众域分解的一个可能的维度是根据涉众类型,基于他们的关注点来进行架构分解,试着为某类涉众划分出对应的子系统或模块(架构元素),例如考虑到前台涉众和后台涉众的用户类型、关注点差别较大等因素,可能会将系统划分为前台系统和后台系统两大类。
对第三方涉众(外部系统),考虑到接入认证授权、安全性和互操作性,可能会分解出网关子系统。
为何首先从业务域开始分解,其实很好理解,我们开发一个系统肯定是为了解决业务问题,是为业务服务的,不可能脱离业务去设计一个空洞的无目标的系统和架构。
4.2、架构分解的粒度
多维度多层次分解到什么粒度才停止?这个没有统一的标准,通常要能进行并行开发,能指导后续的详细设计。
需要根据具体的产品或项目来定,有的到模块级别就行,对关键的部分,可以到类级别。
4.3、架构分解的时机
架构分解的时机通常就是架构改造演化的时机。当架构出现腐化和臭味,已经难以满足关键涉众的关键需求,例如用户的响应速度越来越慢已经接近临界值,并且根据预见,响应速度还有可能继续较低;开发人员越来越难以维护,这个时候可以考虑进行架构演化,对架构进行改造。当然如果能提前预见系统的问题,经过慎重评估后,在问题发生之前,提前一段时间进行架构演化也是可以的。要注意的问题是不要过度分解,过早分解,这样做除了增加成本,还可能带来风险。例如很多系统在建设初期,考虑到规模较小和快速上线,通常都是一个整体的系统,不会进行大的架构分解,以后随着需求和规模的逐渐增加,会逐步进行架构改造和架构分解。