软件架构设计
子系统的设计
在软件设计的过程中,往往需要对系统的结构层次进行分析,从中抽取出系统的设计框架,通过框架来指导整个软件设计的流程。而一个良好的系统框架也是决定整个系统的稳定性、封闭性、可维护性的重要条件之一。
复杂的系统,最好先按业务领域横向拆分成可独立部署的子系统,每个子系统内部再按技术和业务纵向拆分成不同的模块。
举例来说,按照一般的模块化或者功能拆分方法,我们可以将一个完善的电商系统分解为商品、库管、订单、支付、财务、结算、配送、搜索、CRM、虚拟货币、优惠票券、短信、邮件、活动等子系统。而子系统可以再次按照模块或者功能细分,比如订单系统可以按商品品类或者活动类型或者线上线下等维度拆分。支付系统可以按照内外部支付方式、支付和风控策略、支付模式(如跳转或直连等)等不同维度进行划分。
子系统设计准则
-
分而治之,划分模块
子系统还可以拆分子系统,服务还可以拆分子服务,这里涉及到一个粒度的问题,非常考验设计者的水平和经验,需要准确把握,否则很容易过度设计 -
分层
如果真正理解分层的含义,在很多情况下,多层不如经典三层 -
保证隔离,划清界限
不要过多假设,不要拖泥带水,任何模块或服务只做它该做的事情。实现隔离的最佳方法,就是面向接口编程,而不是针对具体实现编程
Programming to an Interface, not an Implementation -
多态
如果一定要复用类,请优先使用对象的组合而非继承 -
提取变化剧烈的点,定期重构,核心业务逻辑必须单元测试
UI 变化最大,其次是业务逻辑,很多时候 UI 变化会直接影响后端业务逻辑,所以,接口设计要向 UI 和业务逻辑倾斜,基础框架和服务相对稳定,无需过度设计
模块的设计
系统模块划分过程中,要充分遵照当前系统的框架结构。模块的划分要和系统的结构层次相结合,根据系统层次对各个模块也进行层次划分。如果系统的模块划分和框架结构相违背的话,则会导致数据混乱,接口复杂,模块耦合性过高等问题出现。
进行模块划分时,很多情况下不能清晰的把握每个模块的具体内容。往往会从需求归类或数据统一的角度上来设计模块。这种设计理念是对的,但如果只是单纯从这几个方面进行模块设计,会导致在模块划分上出现一些问题。
比如设计的某一个模块,虽然数据接口统一,但内部实现的功能非常多,单一模块的规模过大,包含的内容过多,会导致程序实现难度增加,数据处理流程变得复杂,程序维护性降低,出错范围不易确定等问题出现。同时,由于模块实现的功能丰富,则必然会导致接口也变得繁多,那么与其他模块之间的独立性就得不到保证,严重影响对程序的理解。
在设计模块的时候,需要遵循每个模块功能单一、接口简单、结构精简的原则。确保每个模块的规模不要太大,接口尽量单一简化。这样可能会导致模块数量比较多,但能够确保模块的独立性,且不会影响系统的整体框架结构。
模块划分的意义:
- 功能完整独立,数据接口简单
- 程序易于实现,提高软件开发速度的同时能兼顾软件质量
- 程序实现逻辑更加清晰,可读性强,易于理解和维护
- 多人合作开发分工更明确,容易控制
- 系统运行可方便地选择不同的流程
- 易于测试和维护
- 有利于限制错误范围
- 抽象出可公用的模块,可维护性强,以避免同一处修改在多个地方出现
- 能充分利用可以重用的代码
- 基于模块化设计优秀的系统,方便的组装开发新的相似系统,甚至一个全新系统
模块划分准则
- 高内聚低耦合
- 规模适中
大模块分解不充分;小模块使用开销大,接口复杂。 - 功能单一明确
最好做到模块与目标的一一对应。方便单个模块的调试。 - 接口简单一致
设计应该使得信息传递简单并且与模块的功能一致。 - 尽量保证单入口单出口
避免内容耦合,易于理解和维护。 - 功能可预测
相同的输入应该有相同的输出,否则难以理解、测试和维护。 - 联系尽可能少
对于必须的联系都应该有明确的说明,
模块化的实现
抽象: 抽出事物的本质特性而暂时不考虑它们的细节
信息隐蔽: 一个模块内包含的信息(过程和数据)对于不需要这些信息的模块来说,是隐蔽不可访问的。
按照功能划分
在模块设计过程中大多基于功能来划分。这样做可以让相似的功能需求得到明确划分,同时有利于功能分解,任务分配等。
按照任务需求划分
按照任务需求进行模块划分是一种基于面向过程的划分方法,这样做能够清晰的了解系统的开发流程。对于任务的分工、管理,系统功能接口的制定都有良好体现。
按任务需求进行模块划分,可以先将任务需求根据系统框架分出系统等级。通过任务需求的等级划分对模块划分起到引导作用,同时,依照系统结构层次再来进行模块划分。
按任务需求进行模块划分的主要步骤如下:
- 分析系统需求,得出需求列表
- 对需求进行归类,并划分出优先级
- 根据需求对系统进行模块分析,抽取出核心模块
- 将核心模块进行细化扩展,逐层得到各个子模块,完成模块划分
很多情况下,在划分任务需求时,有些需求和多个模块均有联系,此时,通过需求来确定模块的划分就不能够降低模块间的耦合。而且有些模块划分出来后,里面涉及的数据类型多种多样,显然这个时候根据系统所抽象出来的数据模型来进行模块划分更加有利。
按照数据模型划分
在系统进行模块划分之前,往往都会有一个数据模型的抽象过程,根据系统的特性抽象出能够代表系统的数据模型。根据数据模型来进行模块划分,可以充分降低系统之间的数据耦合度。按照数据模型进行模块的划分,降低每个模块所包含的数据复杂程度,简化数据接口设计。同时,对于数据的封装可以起到良好的作用,提高了系统的封闭性。
抽象数据模型的模块划分方案是一种基于面向对象的思想进行的。这种思想的特点就是不以系统的需求作为模块的划分方法,而是以抽象出系统的数据对象模型的思想对模块进行划分。而利用这种思想进行模块划分的主要好处能够接近人的思维方式对问题进行划分,提高系统的可理解性,可以从较高层次上对系统进行把握。
按照数据模型进行模块划分的主要步骤如下:
- 根据系统框架抽象出系统的核心数据模型
- 根据核心数据模型将系统功能细化,并将数据模型与视图等剥离,细化数据的流向
- 依据数据的流向制定模块和接口,完成模块划分