本篇要回答的问题:为什么说"架构图不是架构"?架构的核心产出到底是什么?为什么我们应该少谈框架、多谈业务,别让框架绑架业务、别用实现替代业务?
上一讲我们用伤害值与耦合度公式量化了架构优劣,其中"接口与业务的匹配性"被标为"不可计算、靠主观判断"。本讲正是要把这件最重要却最易被忽视的事讲透:架构是共识确认的过程,接口才是架构设计的核心。
架构是共识确认的过程
回顾架构师三大技能(理需求、读代码、抽象系统),其中两件最难做好。很多人爱画架构图,画完就以为架构做完了,下一步去编码——这有什么问题?
| 问题 | 后果 |
|---|---|
| 架构图不精确、有歧义 | 团队没有精确共识,不同模块"牛头不对马嘴" |
| 风险被隐藏到联调时刻 | 里程碑临近才匆忙联调,动作走形——追求的不再是好坏而是打补丁 |
类比:不精确的架构 = 建筑设计师只画了张没有尺寸和细节的效果图就分头开工,最后拼接全靠老天爷。
| 更精确的架构方法 | 说明 |
|---|---|
| 定义每个模块的接口 | 用代码表达,精确无歧义;架构图只是辅助说明接口间关联 |
| 过一遍所有用户故事 | 用伪代码/流程图确认模块接口能串起来正常工作 |
| 概要设计阶段就写框架代码 | 用真代码(非伪代码)串一遍用户故事——代码即文档 |
关键判断:在概要设计阶段就用真代码把用户故事串一遍,等于把联调风险提前消除;剩下的只是各模块个体好坏,与组织能力无关。所以模块的接口,是架构设计的核心。
别让框架绑架业务
| 架构两侧 | 对应物 | 性质 |
|---|---|---|
| 接口 | 代表用户需求 / 业务 | 稳定 |
| 架构图 | 代表框架 / 技术 | 易变 |
关键判断:抓住稳定的东西,比追逐变化更重要。 框架重要,但不要让它反客为主、溢出模块边界。
框架体现的是"需求泛化能力",需要随时间迭代逼近理想。如果框架不满足需求又不迭代、硬加功能,会发生:代码逃逸出框架,把系统搅得支离破碎。大框架的最大挑战是要提前预测所有需求——但这很难。
许式伟给出的反向建议:
连接性的代码越少越好。 连接性代码 = 把两个子业务系统连接成大业务场景的代码;若有大业务场景,应抽象出新的更大范畴的业务系统,而非写连接代码。
洞见:每个模块都是一个业务(模块泛指函数/类/接口/包/子系统/网络服务/桌面程序)。抽象符合业务自然语义的接口,远比抽象泛需求的框架容易,因为业务语义是稳定的。
SAX vs DOM:关注框架 vs 关注业务
以 IO 系统读盘的两种模型对比"框架思维"与"业务思维":
| 模型 | 机制 | 体现业务? | 评价 |
|---|---|---|---|
| SAX | 基于事件(StartDocument/StartElement/Characters…) | 否 | 典型框架思维:通用但简陋,与需求方诉求不匹配,缺文档无法正确使用,放弃了"精确"这一最大优点 |
| DOM-抽象树 | Node/Nodes 通用接口(Childs/Name/Type/Text) | 否 | 接口简洁,但和 SAX 同病:不体现业务 |
| DOM-具体业务 | Document/Paragraph/Span 等领域接口 | 是 | 看似冗长,但可脱离文档零心智负担使用——这才是该追寻的方式 |
别用实现替代业务
核心箴言:比框架(架构图)更重要的是数据结构,比数据结构更重要的是接口。
为什么数据结构比框架重要?因为业务数据结构是实现机制的灵魂,从共识确认角度比框架更重要的共识。"用实现替代业务"的典型反面案例:
| 反面案例 | 问题 |
|---|---|
| 定义了数据结构但不抽象业务逻辑 | 直接让使用方操作成员变量,或一堆 get/set |
| 用 ORM 操作数据库 | 直接操作数据结构,忽略定义业务接口 |
总结
今天的内容核心指向一点:
架构就是业务的正交分解。每个模块都有它自己的业务。
架构三步曲"需求分析→概要设计→详细设计",背后都直指业务的正交分解,只是逐步从模糊走向精确无歧义。
先把"是什么"回答清楚
| 概念 | 一句话说明 |
|---|---|
| 架构是共识确认 | 共识需精确无歧义,架构图做不到,接口才行 |
| 接口 vs 架构图 | 接口=业务(稳定),架构图=框架(易变) |
| 代码即文档 | 概要设计阶段用真代码串用户故事,提前消除联调风险 |
| 连接性代码 | 连接子业务的代码,越少越好;应抽象更大业务系统 |
| 优先级链 | 接口 > 数据结构 > 框架(架构图) |
一句话速记
别画完架构图就以为架构做完了——架构的核心是精确无歧义的业务接口;抓住稳定的业务语义,别让易变的框架反客为主、也别用实现机制替代业务抽象。
几条值得记住的判断
- 接口是架构设计的核心,架构图只是辅助。
- 抓稳定(业务)比追变化(框架)更重要,连接性代码越少越好。
- KISS 的简单是业务语义准确,不是接口外观简洁(SAX 反例)。
- 接口 > 数据结构 > 框架,别用实现替代业务。
思考题
找你最近设计的一个接口:把方法名遮住只看签名,团队同事能否"零文档"地猜出它在做什么业务?如果不能,它大概率是"框架思维/实现思维"的产物——试着照 DOM-具体业务的方式,把它改写成体现业务自然语义的接口。
