Files
vibe-coding-cn/docs/philosophy/software-engineering-truths.md
2026-06-01 00:48:27 +08:00

10 KiB

软件工程的朴素真理

软件工程不是把代码写出来,而是在变化中持续交付可靠价值。

软件工程的核心,不是写代码,而是管理复杂性。

代码只是结果。真正困难的是:需求会变化,人会误解,系统会膨胀,历史包袱会累积,边界会模糊,成本会被低估。

软件工程不是把复杂问题变成复杂代码,而是尽量把复杂问题变成可理解、可维护、可演进的系统。

一、关于代码

1. 代码是写给人读的,顺便让机器执行

机器不在乎变量名叫 a1 还是 user_discount_rate,但人会在未来反复阅读、修改、排查这段代码。

代码首先是一种沟通媒介,其次才是机器指令。

可读性比聪明感重要。没人会长期欣赏只有你自己能看懂的代码。

2. 清晰比聪明重要

聪明的代码可能让人佩服一分钟,清晰的代码能让团队少痛苦几年。

调试通常比写代码更难。如果代码本身已经写得过于“聪明”,未来排查问题的人会付出更高代价。

3. 命名是编程中最难的事之一

一个好名字抵得上一段注释,一个坏名字会制造无数误解。

命名困难,往往说明概念还没有想清楚。

4. 最好的代码,是不存在的代码

能不写的代码,永远是最好的代码。

代码越多,维护成本越高,出错面越大。删除代码常常才是真正的进步。

少即是多,不是偷懒,而是克制。

5. 重复代码不一定坏,错误抽象更坏

抽象是有代价的。

好的抽象减少复杂性,坏的抽象制造复杂性。没有被真实使用验证过的抽象,往往只是提前制造复杂度。

过早抽象,很多时候比适度重复更糟。

二、关于复杂度

6. 软件工程的核心是管理复杂性

软件开发本质上,是把业务世界里的混乱逻辑,转化为可运行、可理解、可维护的数字逻辑。

业务本身有多复杂,系统最终就会有多复杂。

工程能力不是消灭所有复杂度,而是让复杂度有边界、有位置、有解释。

7. 复杂度不会消失,只会转移、隐藏或命名

你可以通过架构、抽象、封装、平台化来移动复杂度,但很难真正消灭复杂度。

如果一个系统看起来简单得不可思议,复杂度很可能被推给了用户、运维、调用方,或者藏在某个尚未暴露的角落里。

8. 简单不是简陋,而是克制

简单不是少写几行代码,而是少让人记住东西。

好的设计不是堆更多功能,而是减少不必要的概念、状态、分支和例外。

真正的简单,是让正确的事情容易发生,让错误的事情难以发生。

三、关于需求

9. 需求永远不会完整

用户往往知道自己不满意什么,却未必能准确描述自己真正需要什么。

很多失败项目,不是因为程序员不会写代码,而是因为一开始就没有搞清楚要解决什么问题。

10. 需求不清,技术越强,偏得越快

需求不清时,技术能力越强,越可能把错误的方向实现得又快又复杂。

最贵的 bug,通常不是写错了代码,而是理解错了问题。

11. 变化是常态

软件不是在稳定世界里运行的静态产物。

市场会变,用户会变,组织会变,依赖会变,监管会变,基础设施也会变。

所以软件设计不能只追求“第一次做对”,还要考虑未来如何修改、扩展、替换和回滚。

四、关于维护

12. 上线不是结束,而是开始

软件不是一次性交付物,而是一项长期债务。

上线只是软件开始接受现实检验的第一天。维护、扩展、排障、迁移、兼容,才是成本的大头。

13. 不动的代码也会腐烂

即使一行代码都不改,系统也可能逐渐失效。

依赖会过时,环境会升级,接口会废弃,业务规则会变化,安全风险会积累。

不维护的系统,迟早会出问题。

14. 技术债不是罪,假装没有技术债才是罪

为了赶进度牺牲质量,有时是现实选择。

但技术债必须被看见、被记录、被评估。债可以借,但要知道借了多少,利息是什么,什么时候还。

“以后再重构”通常意味着“以后也不会重构”。

五、关于质量

15. 测试不是为了证明代码正确

测试不能证明系统没有 bug,但能阻止很多旧 bug 复活。

它最大的价值,是让修改不那么可怕。

没有测试的系统,越成功越难改;越难改,越容易变成负担。

16. 性能问题要靠测量,不要靠感觉

过早优化是万恶之源。

先让它跑起来,再让它正确,最后才是让它快。

大多数性能问题不是靠猜出来的,而是靠监控、profiling、压测和真实数据定位出来的。

17. 安全不是一个功能,而是一种默认假设

系统最脆弱的地方,通常不在算法,而在边界。

输入、权限、网络、并发、时间、状态、依赖、异常路径,才是事故高发区。

安全的基本假设应该是:任何输入都可能有问题,任何边界都可能被突破。

18. 稳定不是没有故障,而是故障可控

稳定系统靠的不是永远不出问题,而是出问题时能够被发现、被定位、被隔离、被恢复。

日志、监控、告警、追踪、降级、限流、回滚,都是系统稳定性的一部分。

日志不是给程序看的,是给凌晨三点处理事故的人看的。

六、关于架构与权衡

19. 没有银弹

没有任何语言、框架、架构、平台或工具能解决所有问题。

换语言不一定能解决性能问题,引入新框架不一定能解决组织问题,使用 AI 写代码也不等于解决了需求定义和工程责任。

技术只是手段,不是答案本身。

20. 软件工程本质上是权衡

软件世界里很少有绝对最优,更多是当前条件下的相对合适。

速度、质量、成本、灵活性、稳定性、安全性、复杂度,往往互相牵制。

架构设计不是寻找完美方案,而是在多个不完美选项中,选择团队当前最能承担的代价。

七、关于团队

21. 软件工程是团队运动

再厉害的独行侠,也比不上一个沟通顺畅的团队。

代码是媒介,协作才是核心。

团队里的隐性知识越多,系统风险越大。没有被写下来、讲清楚、传递出去的知识,都会在未来变成成本。

22. 系统的形状,往往反映组织的形状

沟通混乱的团队,很难产出边界清晰的软件。

职责不清、目标不一、协作低效,最终都会反映到系统里,变成混乱的模块、模糊的接口和难以维护的依赖关系。

23. 文档不是装饰品

文档不是为了证明你写过什么,而是为了让别人少猜。

尤其是记录“为什么这么做”的文档,通常比解释“代码做了什么”更有价值。

代码能说明系统当前怎么运行,但文档能解释当时为什么做出这个选择。

八、最终总结

软件工程的朴素真理是:

技术只是手段,解决问题才是目的。

优秀的工程师,不是写出多复杂的代码,而是能用尽可能简单、清晰、可靠的方式解决复杂问题。

每一行代码,都是未来要承担的责任。

每一个抽象,都是未来要维护的承诺。

每一个系统,都会在变化中接受检验。

所以,软件工程的本质不是“把代码写出来”,而是:

在变化中持续交付可靠价值。