一本八百页的砖头,到底想说什么
大一那年,教材科发了一本砖头。
八百页。封面印着"软件工程"四个字,压在《数据结构》和《操作系统》上面的时候,你甚至觉得它会压弯书架。你翻开目录——过程模型、需求工程、系统建模、架构设计、软件测试、演化、项目管理……每一个词都是中文,但它们连在一起,像一团揉乱的线头。
你在考试前背了三天。瀑布模型五个阶段。螺旋模型的四个象限。敏捷宣言的四句话。UML 有几种图?九种。每种画什么?记不住。但你背下来了,考了八十五。
然后你去实习。
第一天你就发现——没人画用例图。没人提 CMMI。Jira 里的任务流转跟书上写的任何流程都对不上。你坐在工位上,脑子里背过的那些东西像隔夜的茶水,凉了,没味了。
你开始怀疑:那本八百页的砖头,到底讲了个啥?
它不是方法论菜单——它是决策坐标系
很多人读完这本书,记住的是一堆名字。瀑布、增量、螺旋、敏捷、RUP、Scrum、XP——像餐厅菜单一样列在那里。考试的时候选对就得分。
但书其实不希望你记住它们。
这本书的序言里,其实已经把答案说了——这本书的目的不是推荐某一种方法,而是让你理解不同方法的适用场景和权衡。换句话说——它不给你答案。它给你一个坐标系。
什么叫坐标系?坐标系不告诉你"往哪走"。它告诉你——你现在站在哪。你的项目是需求清晰还是模糊?团队是五个人还是五百人?交付周期是一周还是一年?你回答出这些问题,坐标系就告诉你:你可能更适合敏捷的这半边,而不是瀑布的那半边。
背菜单的人永远在问"我们应该用什么流程"。有坐标系的人知道——你应该先看自己站在哪。
这才是《软件工程》第一部分「软件过程」真正的意图。它不是教你流程,是教你判断。
过程——为什么一本讲"怎么做"的书,先教"怎么组织做"
那它为什么要把「过程」放在第一章?
不是巧合。
你一个人写代码,不需要过程。打开编辑器,写,跑,改,提交。过程是你和你的大脑之间的事,不需要文档,不需要审批,不需要对齐。
但三个人呢?他们开始互相等。十个人呢?有人不知道别人在改什么。五十个人呢?一个需求漏掉了,三十个人的代码白写了。
Sommerville 把过程放在最前面,不是因为他觉得过程最重要——是因为规模一旦上去,不成体系的"做"会立刻坍塌。瀑布模型被骂了几十年,但你要理解它为什么被发明——不是因为当时的人傻,是因为当时的软件在磁带上交付。一次交付的成本是邮寄一盘磁带。发货之前改一行代码——不可能。所以它的逻辑是:想清楚所有东西,再动手。那是约束下的理性选择。
增量模型、螺旋模型、敏捷——每一个的出现都不是因为"这个比上一个好",而是因为"那个时代的约束变了"。互联网时代,需求等不起三个月。云时代,部署成本接近零。于是增量交付出现了,于是持续交付出现了,于是 DevOps 出现了。
你把书里这些模型按时间排开,看到的不是一个进化树。看到的是一张约束→方案的对应表。约束在变,方案跟着变。
这就是过程的本质——不是固定流程,是响应约束的结构。
需求——你以为你懂了,其实你没有
过程定了之后,第一个真正棘手的问题来了:你到底要做什么?
听起来像废话。合同上不是写着吗?PRD 不是贴着吗?
但你见过多少项目,做到一半发现做的事根本不是用户想要的?见过多少功能,开发了三个月,上线没人点?见过多少争论——产品说"这是需求",开发说"这不是需求",吵了一个小时才发现两个人对"需求"的定义就不是一回事?
书里把需求拆成了好几个层次:用户需求、系统需求、功能需求、非功能需求。你第一次读的时候觉得这是凑字数。后来你在工位上跟产品经理吵过三次架之后,忽然理解了——不拆层次,你甚至不能正确地吵一架。
Sommerville 花了两章讲需求,但最锋利的一句话藏在里面:需求不是"说出来"的,是"引出来"的。用户嘴上说的和实际需要的,在大多数情况下不是同一件事。你需要访谈、观察、原型、场景——你用一切手段去逼近真相,但你永远只能逼近,不能抵达。
有一个在教材之外、但在行业里反复被引用的数字:软件项目中 60% 到 70% 的失败根因,最终追溯到需求阶段的问题。不是代码写错了。是从一开始,所有人都在为一个错误的问题写正确的答案。
所以书里讲需求工程,讲的不是"怎么写好一份 PRD"。讲的是——你怎么确保你在做对的事,而不是把事情做对。这两者之间的差距,就是一个项目的生死。
架构与设计——从"能跑"到"能活"
需求告诉你做什么。架构告诉你这件事长成什么样。
书里把软件设计拆成两层:架构设计(高层)和详细设计(低层)。但你读完会发现,真正拉开工程师差距的,不是你会不会画类图——是你有没有意识到架构是一份契约。
什么叫契约?就是一旦定下来,改它的成本大到你会想离职。
举个书里反复暗示但没明说的例子:你选择了微服务,你就同时选择了网络延迟、分布式事务、运维复杂度。你选择了单体,你就同时选择了部署耦合、模块边界模糊、技术栈捆绑。你以为你在做技术选型——其实你在做约束的永久性交换。每一个架构决策,都在用未来的某种灵活性去换现在的某种便利。
Sommerville 讲架构模式——MVC、分层、管道-过滤器、事件驱动——但他真正的潜台词是:没有正确的架构,只有和你的约束匹配的架构。
你再看一遍教材,你会发现他在架构那章花了很多篇幅讲"质量属性"——性能、安全、可维护性、可扩展性。这些词散落在字里行间,但把它们拼起来,就是一句话:架构不是为"能跑"设计的,是为"能活三年"设计的。
能跑只要一天。能活需要你在第一天就想到第三年的某个凌晨三点不会有人改不动代码。
测试——不是为了证明它"能用",是为了证明它"不会死"
书讲到这里,你已经有了过程、有了需求、有了架构和设计。按理说,照着做就行了。
但在这个世界上,你画的图纸和盖出来的楼之间,永远有一座桥没搭上。
这就是测试那一章站的位置——它是最后一道防线。Sommerville 用了一百多页讲测试:单元测试、集成测试、系统测试、验收测试、回归测试、alpha、beta……你合上书,脑子里可能只剩下两个字:验证。
但测试的真正哲学,埋在书里一个不起眼的角落里——测试不是为了证明软件能用。是为了证明它不会在某个你没想到的地方死掉。
这两个目标看起来差不多,其实完全相反。前者让你只测 happy path——输入是对的,输出也是对的,测试通过,交差。后者让你专挑边角——空输入传进去会怎样?并发打到极限会怎样?在断网三秒后又重连那一刻,中间件状态是什么?
书里教了黑盒和白盒,等价类和边界值。但那些都是术。道只有一句话——你测的永远不够,所以把你有限的测试资源,花在最可能出事的地方。
有一个数据在软件工程的所有教材里反复出现:bug 被发现的越晚,修复成本越高——高到指数级。需求阶段改一个错误假设,零成本。上线之后改一个逻辑 bug——十倍。凌晨三点生产事故——一百倍。
测试不是质量的保证书。测试是一份风险评估报告。
演化——软件是活的,书的后半本就是讲这个
测试通过了。上线了。
故事结束了吗?
Sommerville 用了一整章告诉你:结束了才刚开始。 书里那章叫"软件演化"——但我觉得它应该叫"为什么你写的那段代码三年后还在这家公司"。一个典型的商业软件,90% 的总生命周期成本花在上线之后的维护上——不是开发,是维护。不是写新的,是改旧的。
你也许觉得这部分枯燥——配置管理、版本控制、变更管理、遗留系统。但你回头想想——你职业生涯里最痛苦的那几次 debug,是不是都是在改别人三年前写的代码?是不是都是因为需求变了,但设计没跟着变?
《软件工程》把演化放在后面,不是因为它不重要——是因为它是前三部分(过程、需求、设计)的自然结果。过程是松散的→设计没跟上→演化阶段变成补窟窿。书上写的每一项演化技术——重构、逆向工程、再工程——都是在替你填前人留下的坑。
但你也可以不让后人填你的坑。
这就是演化那一章真正想说的——软件工程不是"一次做对",是"一直能做下去"。
那本书的真正读法
好了。现在你知道这本书在讲什么了。
它不是一本教你画 UML 的手册。不是一本介绍敏捷和 Scrum 的科普。不是一本让你背模型名字然后去考试的题库。
它是一张地图。上面画着从一个人写代码,到一群人做软件的全部地形——每一段路在哪会翻车、每一个岔路口选了什么就退不回、每一块沼泽看上去是平地踩上去才发现陷脚。
这本书真正的读法,不是从头翻到尾。
是你下一次坐在会议室里,产品经理说"这是需求",你说"等一下——我们确认一下这是用户需求还是系统需求"。是你下一次写设计文档的时候,你不在第一页贴 UML 图,而是在第一页写"这段代码如果三年后要改,应该只动一个模块"。是你下一次测一个接口的时候,你没有只传正确的参数——你还传了空字符串、零、负数、两万个字符。
是你遇到问题的时候,忽然想起书里有一段,好像讲过。
去翻。
它不是答案。它是让你知道答案在哪。
夜雨聆风