blog / Save File
拆与不拆:模块拆分的判断依据
从职责定义、调用方分析、依赖关系和变更频率四个维度,建立模块拆分的判断框架。
在开发过程中,我们总会遇到一个经典难题:一个模块内部的一些逻辑,到底是应该提取出来成为独立的模块,还是继续保留在内部?拆或不拆,往往不是非黑即白的选择,而是对架构设计理解深度的体现。
不拆的考量
在 1024 实训营中,我作为几个模块的设计者,最初的思维比较僵化且杂乱。对于 session 的设计,我第一反应是直接塞进 context 里;对于 memo 的设计,同样也想直接塞进去。问题是:session 和 memo 是不是 context 的一部分?答案是组装 context 的时候确实要用到它们,但仅凭这一点就能往里塞吗?显然不能。
如果仅仅因为”被使用”就粗暴地归入同一个模块,最终只会得到一个职责不清、边界模糊的巨大单体。
拆分的哲学
拆分不是目的,而是手段。拆分的底气,来源于对架构设计的清晰判断和对模块职责的深刻理解。
那么,为什么最终我决定拆了?
从架构层面来看:如果 context 里塞了太多东西,它会变成什么样?冗杂、膨胀,且承担了多个业务职责。一个模块一旦承担了过多的职责,就会变得难以维护、难以测试、难以扩展。这违背了单一职责原则(SRP)——每个模块应该只有一个改变的理由。
如何判断?
一、考察并定义这个模块
明确模块的职责,帮助你决定它的业务边界。在决定要不要拆之前,我确实静下心来认真思考了:context 这个模块到底是干嘛的?
知其然,然后知其所以然。明确了业务范围,才能快速定位它的职责,进而判断哪些东西属于它,哪些东西应该剥离出去。
二、分析准备拆出的业务,是谁在用?
当一个模块被多个不同的调用方使用,且这些调用方对它的需求各不相同,这就意味着拆分时机到了。具体可以问自己几个问题:
- 这个逻辑是否服务于单一的业务场景?
- 如果把它抽出来,会不会让调用方和使用方的关系更清晰?
- 它是否有独立的生命周期和变化原因?
三、考察拆出后的依赖关系
拆分不是一刀切。你需要审视被拆出的模块与原有模块之间的依赖关系:
- 是否存在循环依赖?
- 拆出后,新模块是否能独立演进?
- 接口是否足够抽象,能够稳定地对外提供服务?
四、从变更频率出发
如果某个内部逻辑的变更频率明显高于或低于父模块,那就是一个强烈的拆分信号。变化速度不一致的代码放在一起,会让稳定的部分被频繁改动波及,增加回归测试的成本。
总结
拆与不拆,没有标准答案,但有判断依据:
| 维度 | 不拆 | 拆 |
|---|---|---|
| 职责范围 | 单一且内聚 | 承担了多个业务 |
| 变更频率 | 与父模块一致 | 与父模块不一致 |
| 被调用方 | 仅被父模块内部使用 | 被多个模块引用 |
| 独立演进 | 不需要独立演进 | 需要独立生命周期 |
架构设计不是一蹴而就的,而是在不断权衡中逐步演进的。拆与不拆的选择,本质上是对内聚性与耦合度的平衡。保持模块的内聚性,降低模块间的耦合度,这才是架构设计的核心追求。
Comments