系统设计原则与架构模式归纳总结
做设计这么多年,我越来越觉得——没有原则的设计,就像没有地图的导航。你可能会到某个地方,但大概率会绕远路。这一章,我们来聊聊那些真正被验证过的设计原则和架构模式,把它们串起来,形成你自己的决策框架。
一、设计原则:你的“少踩坑”指南
设计原则不是教条,是前人用血泪换来的经验。我自己刚入行时也爱炫技,代码写得“很聪明”,结果维护起来自己都看不懂。后来才明白,好的设计是让别人(包括未来的你)能快速理解、安全修改。
1. SOLID 原则(面向对象设计的五个基石)
| 原则 | 一句话说人话 | 我踩过的坑 |
|---|---|---|
| 单一职责 | 一个类只做一件事 | 我曾把订单处理和邮件发送写在同一类里,改订单逻辑时误发了一堆测试邮件…… |
| 开闭原则 | 对扩展开放,对修改关闭 | 早期项目每次加新支付方式都要改核心类,后来改用策略模式,真香。 |
| 里氏替换 | 子类必须能替换父类 | 有次继承了一个基类,子类重写方法时抛了不同异常,上线直接挂。 |
| 接口隔离 | 不要强迫调用方依赖它不需要的方法 | 一个巨型接口,实现类里塞满了空方法,看着都难受。 |
| 依赖反转 | 依赖抽象,不依赖具体实现 | 以前用 new 关键词创建所有对象,后来换成依赖注入,测试方便多了。 |
我的习惯:每写一个新类,问自己三个问题——这个类的职责清晰吗?将来可能怎么变?能不能用接口把它隔离起来?
2. 其他经典原则
- DRY(Don't Repeat Yourself):重复代码是万恶之源。我以前一个项目中三个地方写了几乎一样的SQL,改一个漏两个,数据对不上被投诉。
- KISS(Keep It Simple, Stupid):能简单就别复杂。你想想看,复杂的代码出bug概率是指数级增长的。
- YAGNI(You Ain't Gonna Need It):不要为未来不确定的需求提前设计。我曾经疯狂抽象通用框架,结果项目上线后根本没用上。
注意:原则之间有时会冲突。比如DRY和YAGNI就可能打架——抽象得太早可能违反YAGNI,不抽象又会违反DRY。这时候要靠经验判断,没有银弹。
二、架构模式:不同场景的“最佳实践”
设计原则是微观层面的指导,架构模式则是宏观层面的组织方式。我个人把常用模式分成三大类,下面这张图能帮你快速建立印象。
三、架构模式对比(选型参考)
这张表帮你快速判断不同模式的适合场景。嗯,为什么我特别强调“场景”?因为我见过有人在只有3个接口的项目里硬上微服务,结果运维成本比业务代码还多。
| 模式 | 适合规模 | 团队要求 | 典型缺点 |
|---|---|---|---|
| 分层架构 | 小~中 | 2~10人 | 层与层耦合,改一层可能牵动多层 |
| 微服务架构 | 中~大 | 每个服务2~5人 | 分布式事务、服务间调试困难 |
| 事件驱动 | 中~大 | 需要中间件经验 | 最终一致性、消息丢失处理 |
| CQRS + 事件溯源 | 大 | 强领域驱动设计团队 | 学习曲线陡、数据存储量爆炸 |
我建议:如果项目还没到10万行代码,老老实实用分层架构。别被“微服务”这个词冲昏头脑。我曾经在一个小团队里强行拆分微服务,结果每个服务只有几百行代码,却要维护一套CI/CD和监控……后来合并成模块化单体,消停多了。
四、从原则到架构:一个实际决策示例
假设我们要设计一个订单系统。需求:支持多种支付方式、订单状态流转、库存扣减、发送通知。
- 首先用原则判断:单一职责告诉我们支付逻辑、订单状态、库存、通知应该解耦。
- 架构模式选择:如果团队小、业务也相对内聚,用分层架构 + 策略模式处理支付即可。如果将来要对接几十个第三方支付,可以考虑微服务收拢。
- 编码落地:每个模块用接口隔离,依赖注入让测试更容易。嗯,别忘了DRY,但不要提前抽象YAGNI的部分。
你可以看到,原则和模式不是各自独立的。原则指导你“怎么拆”,模式指导你“怎么摆”。结合起来,就能减少很多后期返工。
我曾经犯过的错:在一次重构中,我同时用策略模式 + 工厂模式 + 观察者模式,代码看起来“很优雅”,但团队成员看不懂。后来我改成简单策略模式 + 配置文件,反而维护成本更低。记住:模式是工具,不是目的。
五、小结
这一章,我们聊了设计原则(SOLID、DRY、KISS、YAGNI)和核心架构模式(分层、分布式、事件驱动)。核心就一句话:用原则约束微观代码,用模式组织宏观结构。每个决策都要结合团队规模、业务复杂度、未来变化频率来定。
我个人习惯:每次开始设计新模块时,先画一张简单的架构草图,把模块、接口、依赖、数据流标出来。画完再问自己——这个设计违反了哪条原则?有没有更简单的模式可选?答案往往就出来了。