设计规约
设计规约将架构设计原则落地为可执行的工程规范,涵盖 UML 建模指导、面向对象设计原则、可扩展性设计等核心内容。
提示
阿里巴巴系统设计规范与UML建模指导
强制规则
系统设计必须遵守的规范:
存储方案和底层数据结构的设计获得评审一致通过,并沉淀成为文档。
在需求分析阶段,如果与系统交互的User超过一类并且相关的User Case超过5个,使用用例图表达。
如果某个业务对象的状态超过3个,使用状态图表达并明确状态变化的各个触发条件。
如果系统中某个功能的调用链路上的涉及对象超过3个,使用时序图表达。
如果系统中模型类超过5个,并且存在复杂的依赖关系,使用类图表达。
如果系统中超过2个对象之间存在协作关系,并且需要表示复杂的处理流程,使用活动图表示。
推荐的架构设计目标
- 确定系统边界:确定系统在技术层面上的做与不做
- 确定系统内模块之间的关系:确定模块之间的依赖关系及宏观输入与输出
- 确定指导后续设计与演化的原则
- 确定非功能性需求:安全性、可用性、可扩展性
面向对象设计原则
单一职责原则
类在设计与实现时要符合单一原则。随着系统演进,很多时候会忘记类设计的初衷。
里氏替换原则
不得已使用继承的话,必须符合里氏代换原则——父类能够出现的地方子类一定能够出现。
依赖倒置原则
系统设计阶段,尽量依赖抽象类与接口,有利于扩展与维护。低层次模块依赖于高层次模块的抽象。
开闭原则
系统设计阶段,注意对扩展开放,对修改闭合。交付的代码在极端情况下是不可修改的。
DRY原则
共性业务或公共行为抽取出来公共模块、公共配置、公共类、公共方法等,在系统中不出现重复代码。
UML建模指导
| 场景 | 推荐图例 | 说明 |
|---|---|---|
| 需求分析 | 用例图 | User Case > 5个 |
| 状态管理 | 状态图 | 状态 > 3个 |
| 调用链路 | 时序图 | 调用对象 > 3个 |
| 类结构 | 类图 | 模型类 > 5个 |
| 协作流程 | 活动图 | 协作对象 > 2个 |
状态图示例
订单状态流转:
[待付款] → [已付款] → [待发货] → [已发货] → [已收货]
↓ ↓ ↓ ↓
[已取消] [已取消] [已取消] [已取消]时序图示例
用户 → 控制器: 提交订单
控制器 → 服务层: 创建订单
服务层 → DAO层: 保存订单
DAO层 → 数据库: INSERT
数据库 → DAO层: 返回结果可扩展性本质
可扩展性的本质是找到系统的变化点,并隔离变化点。
世间众多设计模式其实就是一种设计模式——即隔离变化点的模式。极致扩展性的标志,就是需求的新增,不会在原有代码交付物上进行任何形式的修改。
设计文档的价值
- 明确需求
- 理顺逻辑
- 后期维护
- 次要目的:指导编码
注意:代码即文档的观点是错误的。代码的深度调用、模块层面上的依赖关系网、业务场景逻辑、非功能性需求等问题需要相应的文档来完整呈现。
适用场景
| 场景 | 应用规范 | 原因 |
|---|---|---|
| 新项目启动 | 存储方案评审 + UML 建模 | 提前识别设计风险 |
| 复杂业务流程 | 状态图 + 时序图 | 明确状态转换和调用链路 |
| 团队协作开发 | DRY 原则 + 依赖倒置 | 降低耦合,提高可维护性 |
| 系统重构 | 可扩展性设计 + 单一职责 | 隔离变化点,降低修改风险 |
FAQ
Q: 什么时候需要画 UML 图? A: 阿里规范给出了明确阈值:User Case 超过 5 个画用例图,状态超过 3 个画状态图,调用对象超过 3 个画时序图,模型类超过 5 个画类图,协作对象超过 2 个画活动图。不是所有设计都需要 UML,简单功能直接编码即可。
Q: DRY 原则和过度抽象的界限在哪? A: DRY 消除的是"重复的业务逻辑",而非"相似的代码结构"。如果两段代码恰好结构相似但业务含义不同,强行抽象会导致一个业务的修改影响另一个业务。判断标准:如果修改一处逻辑时必须同步修改另一处,才是真正的重复,需要抽象。
Q: 代码即文档为什么是错误的? A: 代码只能表达"怎么做",无法表达"为什么这么做"。业务背景、设计决策、取舍权衡、非功能性需求(性能指标、安全要求)等信息无法从代码中获取。深度调用链、模块间的依赖关系网也需要架构文档来呈现。