架构设计入门:分层与组件
一、什么是软件架构
软件架构是系统的高层设计:由哪些部分(组件、模块、层)组成、它们如何划分职责、如何协作、依赖关系如何。它回答的是「系统长什么样、为什么这么长」——不涉及具体某行代码,但决定了后续开发、扩展和维护的边界。好的架构让「改哪里、加什么」有章可循;差的架构会让每次改动都像在雷区里走。
架构通常包含:结构(有哪些层、哪些组件)、职责(每块负责什么)、依赖与接口(谁调谁、通过什么约定)、关键决策与约束(例如「数据层不直接暴露给前端」)。下面从最常用的分层架构说起。
二、分层架构:表现层、业务层、数据层
分层架构把系统按「职责类型」切成几层,每层只依赖下层、不跨层调用。典型三层:表现层(Presentation)——界面、接口、接收输入与展示结果;业务层(Business / Domain)——业务规则、流程、领域逻辑;数据层(Data / Persistence)——存储、查询、持久化。依赖方向自上而下:表现层调业务层,业务层调数据层;下层不知道上层的存在。
分层的好处:职责清晰——改界面不动业务、换数据库主要动数据层;可替换——业务层不依赖「具体哪种 DB」,只依赖数据层接口;可测试——业务层可以 mock 数据层做单测。注意:不要出现「表现层直接调数据层」或「数据层调业务层」的逆向依赖,否则分层就形同虚设。
三、组件与模块的划分
除了「按层切」,还可以按功能域或业务边界切分成组件(Component)或模块(Module)。例如订单模块、用户模块、支付模块、通知模块——每个模块内部可以再分层,模块之间通过明确的接口协作,避免互相直接捅内部实现。划分原则仍是高内聚、低耦合:同一模块内职责相关,模块间依赖少、接口稳定。
组件可以对应到一个部署单元(如微服务)、一个包/命名空间、或一个库,视规模而定。关键是要有边界:对外只暴露接口,内部实现可独立演进;依赖方向一致,避免循环依赖。
四、架构决策的可见性与文档化
架构里有很多「为什么这么做」的决策:为什么选这三层、为什么订单和支付拆成两个模块、为什么数据层用仓储模式…… 若只留在个别人脑子里,换人或过半年就说不清。所以要把重要架构决策记录下来,方便以后复盘、新人理解、以及避免重复争论。
常见做法是ADR(Architecture Decision Record):每条决策一篇短文,包含背景、决策、理由、后果。例如:背景是「需要支持多种支付渠道」;决策是「引入支付抽象接口,各渠道实现该接口」;理由是「便于扩展、便于测试时 mock」;后果是「新增渠道只需加实现类、不改调用方」。ADR 不必写得很正式,能说清「当时为什么这么选」即可。
理由: 可替换存储实现(MySQL / 内存 / 测试用假实现);业务层单测可 mock 仓储。
后果: 新增存储方式只需实现 OrderRepository;业务层代码不碰 SQL。
架构图(分层图、组件图)和 ADR 一起,构成「架构的可见性」:图回答「长什么样」,ADR 回答「为什么这样」。建议把架构文档放在项目里、随代码一起维护,而不是散落在邮件或脑子里。
一句话: 软件架构是系统的高层结构、职责与依赖。分层架构把表现层、业务层、数据层分开,依赖自上而下。组件与模块按功能域划分,通过接口协作、高内聚低耦合。架构决策用 ADR 等形式记录,保证「为什么这么设计」可见、可追溯。
五、小结
软件架构描述系统由哪些部分组成、职责如何、如何协作与依赖。分层架构典型为表现层、业务层、数据层,依赖单向向下;每层职责清晰、便于替换与测试。组件与模块按功能域划分,通过接口协作,保持高内聚低耦合。架构决策应文档化(如 ADR:背景、决策、理由、后果),使设计可见、可追溯。下一章讲设计原则:SOLID 与高内聚低耦合,把「怎么设计类和模块」的原则说细。