构建之法——现代软件工程(第四版)

978-7-115-69685-4
作者: 邹欣
译者:
编辑: 李莎
分类: 其他

图书目录:

详情

AI 时代,软件工程迎来新的变化和机会,也面临诸多新的课题和挑战。本书作者基于在微软产品团队、微软亚洲研究院、CSDN 及智能驾驶初创公司的一线实战经验,以及在国家级人工智能学院—北京中关村学院的实际授课实践,总结出让学习者在 16 周内掌握实用软件工程技术的教学知识体系。该体系立足于软件工程教学实践,同时吸纳了产业最前沿的人才培养需求,力图为 AI 时代软件工程的人才培养贡献有益素材。 在此基础上,本书严格参照 ACM/IEEE-CS/AAAI《计算机科学课程指南 2023》中软件工程的核心知识单元,融入了知识-技能-品行胜任力模型及社会、伦理与职业要求。本书坚持“做中学”的教学理念,以及“在开源社区中建设,在开源社区中教学”的原则。使用本书作为教材,全部教学过程可以在公开代码托管平台(Gitee)进行。作者一直认为,可运行的项目代码、实时更新的文档和公开的协作记录是软件工程最好的实战素材。因此,本书不是一本静态的教材—各章节配有持续更新的线上资源。本书前三版在豆瓣等平台收获大量好评,自2012 年起,围绕本书的教学实践和讨论,已经形成了活跃的教学社区,并延续至今。这也为第四版的内容更新、理念升级提供了有力的支撑。 本书适合作为高等院校软件工程相关专业的教材,也适合软件开发自学者、创业者作为行动的指导。

图书摘要

版权信息

书名:构建之法:现代软件工程(第四版)

ISBN:978-7-115-69685-4

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

版  权

著    邹 欣

责任编辑 李 莎

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315

内 容 提 要

AI时代,软件工程迎来新的变化和机会,也面临诸多新的课题和挑战。本书作者基于在微软产品团队、微软亚洲研究院、CSDN 及智能驾驶初创公司的一线实战经验,以及在国家级人工智能学院——北京中关村学院的实际授课实践,总结出让学习者在16周内掌握实用软件工程技术的教学知识体系。该体系立足于软件工程教学实践,同时吸纳了产业最前沿的人才培养需求。

在此基础上,本书严格参照 ACM/IEEE-CS/AAAI《计算机科学课程指南2023》中软件工程的核心知识单元,融入了知识-技能-品行胜任力模型及社会、伦理与职业要求。本书坚持“做中学”的教学理念,以及“在开源社区中建设,在开源社区中教学”的原则。使用本书作为教材,全部教学过程可以在公开代码托管平台(Gitee)进行。作者一直认为,可运行的项目代码、实时更新的文档和公开的协作记录是软件工程最好的实战素材。因此,本书不是一本静态的教材——各章节配有持续更新的线上资源。本书前三版在豆瓣等平台收获大量好评,自2012年起,围绕本书的教学实践和讨论,已经形成了活跃的教学社区,并延续至今。

本书适合作为高等院校软件工程相关专业的教材,也适合软件开发自学者、创业者作为行动的指导。

推荐序 AI时代,重新找到自己的位置

认识邹欣老师,已经20多年了。

最初共事于微软研究院,那时我们都还年轻,每天讨论的是技术,是未来。后来又在北京中关村学院重新并肩,他带着近30年一线工程与教学经验的积累走进课堂,讲氛围编程(Vibe Coding),讲AI时代的软件工程,推广“做中学”的教学理念;我则试图在这片教育改革的试验田上,回答一个问题:在AI改变一切的时代,我们究竟该培养什么样的人?

这本书是邹欣老师边教学、边摸索、边反思写下的。书中用大量的真实案例,讲述软件工程师如何从“写代码的人”成长为“洞察需求、系统思考、坚守底线与引领团队的人”。书中不少内容在一般教材里是几乎见不到的,例如第7章重在破解工程理念与实践脱节的痛点,自带产业一线的鲜活质感;第11章回应了每个年轻工程师心里最深的困惑——AI时代该如何重新找到自己的位置;第12章将用户体验延伸至人机边界,第16章讲创新、讲护城河,这些都是未来工程师必须思考的问题。

我见过很多优秀的年轻人因为AI的到来而陷入迷茫,我想这本书可以为他们答疑解惑。邹欣老师在书中写道:AI可以替代工程师90% 的常规能力,但它同时能将剩余那 10% 的独特能力放大1000倍。这个判断,我深以为然。真正让一个工程师立得住的东西是对复杂问题的判断力、对用户真实处境的理解、在压力下对工程质量底线的坚守——这是AI替代不了的,也是AI时代最有价值的。

在北京中关村学院,我们一直在尝试把这个判断变成真实的教育实践。北京中关村学院是“教育-科技-人才”一体发展的试验田,使命是培养AI时代的领军人才。我们没有传统高校的历史包袱,没有学科之间的高墙,有的是“极经典、极前沿、极实战”的培养方案和“极基础、极应用、极交叉”的科研理念。我们把“在不确定世界中定义和解决问题的能力”作为遴选和培养学生的标准:同学们加入学院后,第一时间进入真实的科研项目,在解决产业真问题的过程中学习成长,在创新创业进程中实现自己的价值。我们鼓励学生把AI用到极致,用AI的杠杆放大自身的能力和生产力。同时,我们引导学生不断思考:当AI成为日常工作、学习中不可或缺的一部分时,自己该选择做什么、为什么做、怎么做才能获得最大的产出?在此过程中要坚守什么,如何才能保有自己的独特价值?

我们正站在一个前所未有的历史节点。有人恐慌,有人茫然,但也有人选择把自己走过的路、踩过的坑、悟到的事,怀着极大的诚意写成一本书,分享给每一个还在寻找方向的人。邹欣老师就是这样的人,这本书就是这样一份礼物。“我构建,故我在。”相信这本书一定能陪伴每一位读者在AI时代坚定地走下去。

刘铁岩
北京中关村学院院长
2026年5月于北京

专家评论

作者深谙软件工程实践,持续深耕于软件产业界和软件教育界,不仅针对软件工程学科的特点诠释了“做中学”的教育理念,而且结合“软件定义一切”及人工智能时代的特点展示了当前软件工程学科快速发展给软件工程教育带来的新机遇和新变化!这是一本理念与实践相结合、特色鲜明的软件工程图书。

毛新军 国防科技大学教授,教育部软件工程专业教指委委员

这是一本“非常规”的软件工程教科书。不同于传统教科书以经典知识体系为主线的内容铺排,这本书以“做中学”为指导,将软件工程思想和方法融入风趣生动的场景化叙述之中,潜移默化地塑造读者的工程思维。此外,本书将软件工程的技术性与管理性内容有机结合,使学生可以全面理解和掌握不同层次的软件工程思想和方法。

彭鑫 复旦大学计算与智能创新学院副院长、教授

“我构建,故我在。”这是邹欣老师写在这本书中的工程师宣言,也是我读完这本书后内心最深的共鸣。AI可以替代工程师90% 的常规能力,同时能将剩余那10% 的核心能力放大 1000 倍,而这10% 正是本书“做中学”理念所着力锻造的:从需求洞察到系统架构,从TDD实践到团队协作,从个人成长到职业精进。在大模型驱动研发的软件工程3.0时代,代码不再是瓶颈,能定义问题、驾驭AI、构建系统的工程师才是稀缺的。这本历经4版、沉淀作者近 30 年一线经验的教材,既是大学课堂的基石,更是每一位工程师在AI时代重新认识自身价值的“镜子”。

朱少民 同济大学特聘教授,《软件工程3.0》作者

软件开发方法的工程特性非常强,产业界有这方面的“第一手”体验。因此,当邹欣老师作为微软亚洲研究院的资深软件工程师撰写出《构建之法》,并在清华大学、北京航空航天大学等高校授课时,选课的学生给出了非常高的评价,这也给国内的软件工程教学带来了一股清新的气息。

进入智能时代后,邹欣老师持续探索大模型带来的软件开发范式变革,并加入了北京中关村学院,成为同时具有头部企业与知名院校工作经历的复合型专家。我通读了他重新修订的这本书(第四版),非常赞赏书中独特的实战视角,奇妙的虚实案例,以及穿插其间的微软历史“典故”。相信这些都会激发读者的思考与创新。

王千祥 华为云智能化研发首席专家,曾任北京大学教授

AI已能写出大部分代码,那软件工程师的价值何在?本书给出了一个直击本质的回答:AI可以替代我们90% 的常规能力,也能将剩余那10% 的核心能力放大1000倍。那10% 的能力是什么?是对复杂系统的全局思考、对用户需求的深层洞察,以及在不确定中持续学习与引领团队的能力。本书不教你被动应对AI浪潮,而是帮你主动把AI变成自己的“超级放大器”。如果你正为职业前景焦虑,或不知如何调整教学方向,这本书会是你的压舱石与航海图。

茹炳晟 腾讯研究院特约研究员,复旦大学CodeWisdom团队首席技术专家

在AI技术的浪潮之巅,拨开氛围编程的迷雾,重塑软件的《构建之法》,邹欣老师的经典力作再出新版。第四版深度融入了作者在软件工程中的丰富实战经验和在AI时代的深度思考。这本教材历经多年真实的教学检验,完美阐释了“做中学”的软件工程教学理念。

谢勰 @算法时空

前  言

《构建之法——现代软件工程》的第一版出版于2014年。此后,我与读者一同走过10余年的迭代之路:2015 年推出第二版,2017 年推出第三版,一直在持续进行小幅更新与内容补充。我很早就开始在网上推广“做中学”(Learning by Doing)的教学模式。陆续有50多所院校加入了网上教学平台,我们开创了“用公开的博客和代码交作业,所有进度和成绩公开,业界工程师和助教协助教学”的模式,取得了不错的效果。

2021年,我的职业生涯进入了一个全新的阶段。当年,我离开了工作近25年的微软,加入CSDN担任研发副总裁。在两年多的任职期间,我负责创建了一系列与程序员职业发展相关的社区,并主导开发了诸多实用功能。在北京和长沙,我结识了不少程序员朋友,与他们一起深入探讨如何开展各类软件工程项目,以及如何规划和拓展自己的职业生涯。我还在湛庐平台上开设了一门面向职场人的语音课程——职场突围课。

2023年,我加入Momenta,专注于提升公司软件产品和开发流程的质量。我们致力于将智能驾驶软件的验证与确认(Verification & Validation,简称V&V)能力提升至国际标准要求。我意识到,我仍需回过头去仔细学习传统行业严谨稳妥的V&V流程和行业质量标准。同时,我们也要说服汽车行业的一些“百年老店”:用现代化和AI驱动的方法,即使不能满足传统质量标准的每一个过程性细节要求,我们的质量和效率依然能够符合甚至超越这些标准。为此,我曾连续 50 周,每周往返于北京与上海,甚至多次前往德国斯图加特,与世界领先的汽车制造商展开深度沟通与合作。最终,我们的软件通过了严格的V&V审核,成功部署到量产车辆上。

在Momenta工作之余,我和几位老师合作翻译了《深度学习:基础与概念》一书。我希望这本书能帮助大家领会深度学习的底层原理,系统了解应用这一人工智能核心技术能做什么、不能做什么,并夯实其背后的数学基础,这也是我对自身知识体系的一次及时补充和巩固。

2025 年 5 月,我正式加入北京中关村学院,负责智能创新中心的工作。我带领一支软件工程师与IT工程师团队,致力于将学院打造成一个真正“智能”的学府,在教书育人、科研转化等方面做出新的贡献。在这里,我和同事们一起讲授现代软件工程及氛围编程(Vibe Coding)等课程。本书(第四版)融入了我这几年的新职业体验,以及在北京中关村学院教学与实践的总结与提炼。

我们正处于 AI 迅猛发展的时代。每一周、每一个月,都有令人惊叹的新技术与新应用涌现。与此同时,软件工程师也普遍感受到前所未有的挑战与焦虑:“我们的职业还有多少保障?我们是否会被AI全面替代?”许多计算机与软件工程专业的教师也在担忧:“当AI几乎什么都能做时,我们的教育还能教给学生什么?”

下图展示了许多人的担忧:AI 工具从代码编写工作的细节开始,逐步承接软件工程师的大部分工作。这股 AI 浪潮能使软件工程师大大提升工作效率,但其来势汹汹,看似也可以“淹没”他们。

(图中的洪水由AI生成)

因此,这本书,以及我在北京中关村学院持续推广的“做中学”教学实践,正是对这些问题最直接、最诚恳的回答。我坚信:AI 可以替代我们作为软件工程师 90% 的常规能力,但它同时能将我们剩余那 10% 的独特能力放大1000倍。因此,在AI时代,软件工程师依然大有可为。关键在于,我们如何主动培养和打磨那10% 的独特能力——包括对复杂问题的系统性思考、对用户真实需求的深刻洞察、对工程质量与职业道德的坚守,以及在不确定环境中持续学习、迭代与领导团队的能力。只有这样,AI才能真正成为我们的“超级放大器”,而不是替代者。

在本书写作过程中,我得到了众多社区朋友的宝贵支持与反馈。许多社区中的工程师,用他们实实在在的实践,向我展示了 AI 在软件生命周期每个阶段所带来的渐进式创新与颠覆性创新。在此,我向每一位参与讨论、提出建议、分享实践的开发者、学生、教师致以衷心的感谢。虽然这是一本纸质书,但它的许多内容早已通过公众号、GitHub/Gitee仓库、视频号以及活跃的微信群等在网上广泛流传。我们于线上线下进行持续交流,实现教学相长,形成了一个生动的学习共同体。

AI 在不断演进,作为一名工作近 30 年的软件工程师,我对于所有问题并没有“标准答案”。但我对未来充满乐观,因为“我构建,故我在”。我们依然需要也必须不断构建新的解决方案,去满足人类在各个领域不断变化发展的需求。本书正是我通过“构建”来回答自己、回答同行、回答这个时代疑问的一次努力。希望本书能陪伴你,在 AI 时代继续坚定地走下去——成为那个驾驭AI、创造价值、引领团队的人。

邹欣
2026年4月于北京中关村

书中人物介绍

软件开发本是一件很愉快、很有意思的工作,可为什么许多同学觉得软件工程特别乏味呢?一个很重要的原因是,教材只是干巴巴地讲述理论和原则,不重视“人”这个重要因素。因此,我在写第一本软件工程图书《移山之道:VSTS软件开发指南》时,就创设了一个虚拟环境:王屋村软件学院、移山公司和一些人物(阿超、果冻、小飞、小李等),希望通过人物的对话和活动,把软件工程的丰富内容生动地展现出来。本书也沿用了其中的一些人物,并且扩展了他们的故事。他们当中有大学在校生,也有刚工作几年的技术人员等,读者可以从他们身上看到自己生活中熟悉的形象。

致  谢

常言道,一个人走得快,一群人走得远。在写这本书的过程中,我能走到今天,全靠很多人在不同阶段给了我实实在在的帮助。

首先要感谢人民邮电出版社的各位编辑老师,感谢你们一直以来的支持和帮助。特别是陈冀康老师多次参加各种交流活动,持续推广这本书及相应的教学理念。

感谢CSDN总裁蒋涛先生支持我在CSDN产品和社区做各种尝试。感谢Momenta CEO曹旭东,以及同事卜弋天、范飞龙、卞曹明、陈晓辉、Jelly Gu、Bugless Xie、陈汉腾、王智华、陈刚、许佐荣、胡翔等。我们曾经反复讨论在智能驾驶领域如何提升软件工程水平,很多想法后来都得到落地实践。特别是范飞龙博士,他把理论付诸行动,证实了在大型复杂的智能驾驶软件开发过程中快速达到合规的工程质量是可行的。

感谢北京中关村学院院长刘铁岩博士的大力支持,让我们能全力推动AI驱动的复合型人才培养模式。也感谢同事李剑、刘鑫、邹猛、吴衍标、燕宇飞、王一博等老师的帮助,以及学生们给我的真诚反馈,我受益良多。

感谢各位老师在课程实践中给我的启发,尤其要感谢福州大学汪璟玢老师、福州大学至诚学院张栋老师的支持。我曾经四次去福州讲课,其中一次交流时想到的“pop-quiz”点子,现在已经成为我教学实践中很重要的一环。

感谢北京航空航天大学高小鹏老师、罗杰老师,谢谢你们为软件工程先进理念在北京航空航天大学计算机学院的落地提供了宝贵的支持。深切怀念北京航空航天大学老校长李未老师,他的风范长存,我永远铭记。

感谢广大的“社区”朋友。在“构建之法”相关的微信群、软工教师群、飞书反馈群、Datawhale交流群、Gitee、微博、湛庐等“社区”里,大家一起深入讨论软件工程的问题,不少很有见地的想法已经写进了本书正文和附录。虽然很多新老朋友这几年大部分时间只是在网上交流,但他们从不同的角度帮助了我,在此一并感谢:于仕琪、朱少民、彭鑫、毛新军、杨晓春、陶建辉、许式伟、高博、红薯、GeniusVczh、宝玉、鸭哥、曾挥、大史、马驰、陈冰、孟宁、孙志岗、余晟、徐寒、鲍捷、Cary、李建盛、郑如滨、戴旸、陈漪、yeka36、王路敏、赵萌等。

最后,感谢我的家人。他们虽然不太理解为什么我每次宣称“完稿”不久就又开始动手修改,但一直都在默默支持我。这份理解和包容,是我能坚持写完这本书的重要力量。

再次感谢所有一路相伴的朋友。

资源与支持

资源获取

本书提供如下资源:

本书源代码、PPT课件等线上资源;

异步社区7天VIP会员。

要获得以上资源,您可以扫描下方二维码,根据指引领取。

提交勘误信息

作者、译者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区(https://www.epubit.com),按书名搜索,进入本书页面,单击“发表勘误”,输入勘误信息,单击“提交勘误”按钮即可(见下图)。本书的作者、译者和编辑会对您提交的勘误信息进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

与我们联系

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们。

如果您所在的学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接通过邮件发送给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

关于异步社区和异步图书

“异步社区”是由人民邮电出版社创办的IT专业图书社区,于2015年8月上线运营,致力于优质内容的出版和分享,为读者提供高品质的学习内容,为作译者提供专业的出版服务,实现作译者与读者在线交流互动,以及传统出版与数字出版的融合发展。

“异步图书”是异步社区策划出版的精品IT图书品牌,依托于人民邮电出版社在计算机图书领域三十余年的发展与积淀,面向IT行业以及各行业使用IT的用户。

第1章 概论

理论是灰色的,而生命之树常青。——歌德

1.1 软件 = 程序 + 软件工程

几乎所有的程序员都知道“程序=数据结构+算法”这句名言,它出自计算机科学家、图灵奖得主尼克劳斯·维尔特1976年的经典著作《算法+数据结构=程序》(Algorithms+Data Structure= Programs),这个清晰明了的公式强化了算法与数据结构作为计算机科学核心基础的地位。

但是在实际的学习和工作中,也有不少人产生了疑问:

我用C语言实现了二叉树的遍历算法。在这里,二叉树是数据结构,遍历的实现细节是算法,C程序就是结果。但是这个程序有什么实际用处呢?在Java和其他一些编程语言中,似乎没有指针,那我可以不用了解二叉树吗?

我成了一名职业程序员,但是我发现所有的算法别人都已经实现了,我只要调用就可以。似乎我们公司的软件与数据结构、算法的关系都不大。那我当初辛辛苦苦学习的数据结构和算法有用吗?如何区分好的程序员和差的程序员呢?

我上班后,发现以前同事写的程序真是垃圾,根本看不懂,无法维护。我要推翻重写!后来一个老员工笑嘻嘻地告诉我,我们现在看到的程序,就是去年的新员工愤怒地推翻重写之后的结果,大家反映还没有以前的版本好用呢!

现在,许多AI编程工具能做的事情越来越多,错误率越来越低,而且不知疲倦。既然如此,不仅数据结构和算法,连深度学习原理本身,对软件开发还有什么意义?那么,能让软件工程师持续成长并创造出真正有价值的“程序”与“软件”的关键能力,究竟是什么呢?

我们先讲一个故事。

移山公司程序员阿超的宝贝儿子上了小学三年级,老师让家长每天出30道四则运算题目给孩子做,每道题目要有两个运算符。阿超想写一个小程序来做这件事,具体实现办法有很多:

Excel、C/C++、Java、C#、VB、UNIX Shell、Lisp、JavaScript、Perl、Python,还可以用AI编程助手等工具来生成……

(请大家估计写好这个程序需要的时间。)

这本书的读者用自己最擅长的工具,一袋烟的工夫就搞定了。

阿超的程序一下就输出了好多份不同的题目。老师看了作业之后,对阿超赞许有加。别的老师闻讯也想要类似的程序,让二年级到四年级都能用,并附带一些小小的要求,例如:

题目避免重复。

可定制数量和打印样式。

可以控制下列参数:

是否有乘除法 | 是否有括号 | 数值范围 | 加减有无负数 | 除法有无余数 | 是否支持分数(真分数、假分数……)  | 是否支持小数(精确到多少位)  | 打印中每行的间隔

阿超的儿子兴高采烈地回家来给老爸汇报,并说“老师明天就想要!”阿超有些挠头,原来就是随手写了个程序,现在怎么来了一些用户,还带来了不少需求?

(现在请读者估计做好这个软件需要多长时间。)

阿超熬夜做出了一个初始版本,来不及全面测试了,就交给了老师。他后来每天都改进并发布一个新版本,过了几天学校提议把这个程序放到学校的网站上,还提出一点点要求:支持二元一次方程,能开根号,可以生成期中、期末考试的试卷;当然,还要能自动判断对错,网站永远是可以用的,至少早上五点到晚上十二点要能访问。

阿超叹了一口气,心想:“这是多么复杂的一个工程啊!如果有一天晚上网站打不开了,我是不是还要负责修理服务器?”电话突然响了,学校领导说,英国的学校知道了这个好东西,也要用!不过没关系,只要保证网站二十四小时能用,并且界面和作业的内容都能顺畅切换中英文就行了。明天能上线吗?后续你可以招两个人在英国和你一起工作……

这里我们看到客户们对阿超的需求从一个简单的程序,扩展到一个要满足各种功能的应用软件,再扩展到一个能保证全天多语言服务质量的软件服务,而且还有远程工作的协调问题。

(请估计做好这个软件加上内部的支持系统需要多长时间。)

阿超的网站很受欢迎,因为是阿超的算术练习程序,所以网站得名“超算”。风险投资专家建议“超算”融资后进军线上授课和作业辅导市场,同时还要有人在网站上投放广告。阿超受宠若惊,正在考虑是否要辞职创业。但他忽然发现出现了很多竞争对手,有的用人工智能技术扫描学生的作业本,马上就可以提供答案;又忽然听说有政策规定不能做这样的软件,就赶紧去研究相关的政策文件。

(请估计阿超还有多少时间写程序。)

从阿超的经历我们看出,一个简单的程序要演变为一个成功的“软件”,必然经历一系列复杂的工程活动,上面的故事展现了软件工程的一些概念。我们总结一下:程序,就是一行行的代码。它们是建立在数据结构上的一些算法,这些代码传统上是程序员输入的,但也可能是由 AI 工具生成的。程序还要对数据进行操作,这些数据有些是静态的(例如软件的图标、提示信息),有些是动态的(例如程序生成的随机数字、程序通过网络下载的数据、用户的文字或语音输入等)。一个复杂的软件不但要有合理的软件架构(Software Architecture),还要有各种文件和数据来描述各个程序文件之间的依赖关系、编译参数、链接参数,等等。

软件团队每天都在修改各种源代码。有些时候,我们要为某个需求写一些特殊功能,不久后又要把这些功能再合并回主要版本。有些程序要配置不同的界面,运行在多语言的操作系统上。这些都属于源代码管理(Source Code Management)范畴。我们还通过一系列的工具、流程和文档来保证程序的正确性,这些工具(也是软件)、流程和文档应该达到很高的质量,才能确保软件在持续的改进、集成、发布过程中的质量。这些工作称为持续集成和持续部署(Continuous Integration & Continuous Deployment),其中质量保障(Quality Assurance)的具体验证过程叫软件测试(Software Testing)。工程师开发了复杂的软件工程系统来组织各种工具链,把上面提到的各种工作高效地完成。

一个软件或者服务要有人买,就得找到客户。客户有各种需求,软件团队要从需求分析(Requirement Analysis)开始,把合适的需求梳理出来,然后逐步展开后续工作。大多数情况下,分析需求的人和实现需求的人并非同一批人。

一个好的软件,即使功能和同类软件区别不大,也会让人感觉非常好用。这就是软件的用户体验(User Experience)。软件还要处理不同语言、不同地区的用户对界面和功能的不同需求,这叫软件的国际化和本地化(Globalization & Localization)。

软件团队的人员也会流动,新的成员要尽快读懂已有的程序,了解程序的设计,这叫程序理解(Program Comprehension)。软件在运行过程中还会出这样或那样的问题,团队的新老成员要时不时给软件打一个补丁,或者维护众多的服务,一起修复各种各样的问题,这叫软件维护(Software Maintenance)或者服务运营(Service Operation)。这一系列过程就是软件生命周期(Software Life Cycle),在这个生命周期中,有人得负责软件项目管理(Project Management)。

一个软件企业总要养活自己,也有很多种赚钱的方式:

有的交钱买断;

有的“先试用再交钱”,有些软件也提供试用版、免费版和正式版,还有的类似期刊订阅,每年交钱;

有的不但免费,连源代码也一并奉送,但是要求获得源代码的开发人员遵守某种协定;

有的送硬件,但是软件要收钱;

有的送软件,但是硬件要收钱;

也有的“免费用,但是要看提供的广告”(“超算”的用户在做题前要看1分钟广告吗?);

还有的“免费用,虽然程序不是我写的,但如果有问题,给我钱,我就来提供咨询……”;

现在还出现了“模型即服务”(Model-as-a-Service),直接把AI模型的能力通过API提供给其他开发者甚至普通用户,通过其消耗的资源来计费,或是提供订阅服务。

可以看到,软件企业的商业模式也会影响软件的需求,例如,对云服务和API的支持会成为“模型即服务”团队的重要需求。当然也有在用户不知情时就安装软件,然后用户怎么也卸载不掉的情况。2010年,业界还出了一桩怪事:A公司要挟用户必须卸载B公司的软件,然后A公司的软件才能运行……这些商业模式,有的合情合理也合法;有的看似合情合理,但不合法;有的不合理,但相关法律法规彼时还未落地,如上文提到的对教辅软件的规定,又如对打车软件的种种监管规定等。在相关法律法规完善之前,软件行业更需依托既定行规——以基本的职业道德规范来约束从业人员的行为。

上面这些和软件开发活动(构建管理、源代码管理、软件设计、软件测试、项目管理)相关的内容是软件工程的核心部分。广义的软件工程也包括用户体验、用户界面设计(User Interface Design)等。所以,一个推论是:

软件 = 程序 + 软件工程

在AI时代,上面等式的右边还要加上“数据”和“模型”。在此之上,我们还有推论:

软件企业 = 软件 + 商业模式

当然,软件企业还需要多方面的支持工作,例如人员的招聘、绩效评估、升迁淘汰等。弄清楚这些概念,是进行所有与程序、软件企业等相关的讨论的基础。

现在回头看本节开头提出的疑问,答案就很清楚了,程序(算法、数据结构)是基本功,但是在算法和数据结构之上,软件工程决定了软件的质量和软件是否解决了用户的需求,商业模式决定了一家软件企业的成败;软件从业人员和软件企业的道德操守则会极大地影响软件用户的利益和行业的发展。那么,究竟是软件的哪些固有特性,使得我们必须引入工程化的方法来解决这些问题呢?

1.2 为何需要软件工程

正是因为软件具备了一些不同于物理实体的特殊性,才使得单纯的个人手工开发难以应对这些特殊性所带来的挑战。在阿超的故事里,我们看到了一个简单的程序如何演变成一个必须用工程方法来管理的复杂系统。那么,“软件工程”中的“工程”二字究竟意味着什么?

人们把下面的活动称为工程

创造性地运用科学原理,设计和实现建筑、机器、装置等实体或规划其生产过程;或是在实践中使用一个或多个上述实体;或是实现这些实体的过程。

在古代,人们协作建成的帕特农神庙、罗马水道、长城等工程奇迹,背后无不蕴含着大量的计划、计算,以及严密的协作与经年累月的劳作。这些系统的有序的可量化的核心特质,在土木工程、机械工程、化学工程等工程学科中一脉相承。

因此,当软件开发涉及多人、多目标且需在约束条件下交付可靠成果时,就必然从个人技艺上升为一门工程学科。它要求我们像建造一座大厦一样,去系统地处理复杂性、应对不确定性,并管理整个创造过程。

接下来,我们将从三个层面理解软件工程的必要性:软件的固有难题、产业成熟度的对比,以及软件工程的目标。

1.2.1 软件的固有难题

软件是可以运行在计算机及电子设备中的指令和数据的有序集合。软件有各种分类方法,具体如下。

按功能层次和目标:系统软件、中间件、支撑软件、应用软件、插件、驱动软件、模型即服务(Model as a Service)……

按应用领域:操作系统、数据库软件、开发工具、办公软件、设计软件、工程软件、教育软件、游戏软件……

按分发模式:企业自研软件、商用软件、开源软件、免费软件、共享软件。

按行为意图:良性软件、灰色软件、恶意软件。

在AI时代,说不定还有:“古法全手工敲入的软件”、AI自动生成的软件……你觉得这么划分有必要吗?

软件和人类制造出来的其他产品相比,有许多共性,也有一些特殊性。它们都是为了满足人们的某种需求。随着技术的进步,很多需求变得越来越容易满足,例如,现在人们旅行的方便程度和速度是几百年前所不可想象的。另一些事情,像怀孕生小孩,几千年来的确变得相对容易了,但还是需要“十月怀胎”。我们知道许多计算机硬件的能力大致以每两年提高一倍的速度发展,而软件开发的流程却没有这样的提速过程,开发成本也没有下降,为什么?软件开发过程有哪些特殊的难题?学者总结了下面五点。

1.复杂性(Complexity)

软件可以说是人类创造的最复杂的系统。大型软件(操作系统、办公软件、搜索引擎)有超过百万行的源代码。而软件工程师凭肉眼通常一次只能看到30~80行源代码(相当于显示器的一屏),他们的智力、记忆力和常人差不多,在过去的几十年中并没有大提高。软件的各个模块之间存在各种显性或隐性的依赖关系,随着系统的成长和模块的增多,这些关系的数量往往以几何级数增长。各个软件之间还存在复杂且抽象的依赖关系。有些工程师的工作是用工具解决问题,如用Python输出几十道四则运算题目;有些工程师则要制造“制造工具的工具”——制造计算机语言的编译器和解释器,以及能编辑程序的集成开发环境;还有的工程师要制造“多人高效协作系统”,让成百上千的工程师能一起协作。现在,AI工具可以取代这复杂的生态系统中的很多初级制造环节,在很多局部的确提高了效率,但是AI工具解决复杂性问题了吗?还是也引入了新的挑战?

2.不可见性(Invisibility)

软件工程师能直接看见源代码,但源代码不是软件本身。软件以机器码的形式高速运行,每秒运行几万行代码,还可能在多个CPU/GPU核上同时运行,工程师“看”不到源代码具体如何在用户的机器上执行。软件出现错误时,工程师能看到程序在出错的一瞬间留下的一些痕迹(错误码、大致的目标代码位置等信息),甚至能听到用户愤怒地抱怨“程序崩溃了”“App闪退了”,但程序出错的过程几乎无法完整重现。当工程师回过头来看源代码时,它们还是安静地排列在屏幕上。

不可见性还体现在:一个看似简单的函数调用,所产生的副作用我们看不见;很多变量和模块之间的依赖关系,我们也不能全面了解。例如,Linux内核有超过2700万行代码,它们都是开源的,对所有人都“可见”,但没人能全部了解所有代码的意义。AI系统使这种不可见性变得更为严峻。开发者不仅无法直观地追踪执行路径,更难以解读大模型内部海量参数的权重分配与决策边界。即便只是微调一个看似无关的提示词,应用也可能产生荒谬的输出。这种黑盒般的“推理”过程,让开发者在定位和修复问题根源时举步维艰。

3.易变性(Changeability)

软件的一个显著特征是易于修改,这远非硬件可比。软件的这种特性使得人们自然地对其抱有两种期待。

功能拓展:期望软件能在不变的硬件基础上,通过修改来增加新功能或改变行为。

环境适配:期望软件能通过调整,自动适应新的硬件平台或运行环境,包括有害的环境因素。

然而,系统的复杂性决定了“变更”的代价。“易于修改”并不等同于“易于正确地修改”。例如,对于纸飞机,修改失败可以一笑置之;但对于航天飞机,修改失败意味着巨额的费用开销,甚至危及人员生命。软件的修改同样如此,一处看似微小的变动,可能通过复杂的依赖关系引发难以预料的连锁反应,导致系统行为异常、稳定性下降或引入新的安全漏洞。这正是易变性带来的核心挑战:修改的低成本与确保修改正确性的高难度之间的矛盾

一个成熟的物理系统,如民航客机的喷气式发动机,其设计哲学是通过极致的物理稳定性和冗余来规避风险。它必须追求“不变”的可靠性,因为一枚硬币或一只飞鸟的撞击可能导致物理结构的失效,这种物理损伤是瞬时且灾难性的。

而一个成熟的软件系统,其设计哲学恰恰相反——通过极致的、受控的迭代能力来管理风险,如同一个互联网服务接口,其韧性建立在逻辑之上。很多网络服务的公开接口每天承受数亿次恶意攻击,但不会因此“磨损”。相反,维护它的工程师通过持续的分析、打补丁和发布更新——也就是安全地系统地进行变更——来维持和增强系统的可靠性。

因此,软件工程的核心任务之一,就是为软件的“易变性”构建安全的轨道,将其从个人技艺层面的随意性,提升为工程学科层面的可控能力。

4.服从性(Conformity)

软件无法孤立运行,它必须服从所处的整个生态系统——包括硬件与操作系统,并延伸到商业逻辑与社会规则。

例如,金融 App 必须服从动态调整的利率监管要求与反洗钱相关法规;游戏则要同时服从主机性能与未成年人防沉迷相关规定。而最典型的例子,莫过于如今用户首次打开 App 时必须面对的隐私政策同意页面——这一设计,正是用户隐私保护、商业需求、法律合规与工程实现四方协调的体现:法律将选择权交还用户,商业在合规前提下开展数据应用,而技术则以标准化流程落实要求,最终由用户在知情的基础上做出自主选择。

5.非连续性(Discontinuity)

许多软件系统没有线性的输入输出关系,输入的微小变化可能引发输出不成比例、不连续的跃变,带来巨大的副作用

软件领域的一个经典的漏洞是缓冲区溢出:向一个固定大小的缓冲区多写入1字节的数据(微小的输入变化),可能导致程序崩溃、安全漏洞被利用,甚至造成完全不成比例的灾难性后果(巨大的输出变化)。这种非连续性使得软件测试和调试变得极其困难,因为很难通过有限的测试用例穷举所有可能引发系统状态跃变的“边界条件”。

除了以上这些由软件本质决定的特性,软件还有其他特性:

新的程序设计语言、软件工具和软件开发平台不断出现,包括高效率的AI编程工具;

存在许多不同的软件开发流程;

软件团队中存在许多不同的角色;

软件既可以存储在磁带上,也可以存储在CD/DVD上,还可以存储在云端服务器上,通过无线网络安装和更新;

AI工具可以自动测试软件,甚至可以自动写部分程序。

但是这些非本质、临时的特性并不能决定软件工程的本质问题。软件的那些本质特性让“做一个好软件”变得很难,同时也让软件工程有它独特的挑战和魅力。例如,有人发明了一种新的程序设计语言,或者又出现了一个新的软件开发流程,或者流程和语言都不重要了——就像最近推崇氛围编程(Vibe Coding)的开发者所主张的那样,或者网上出现了一个程序员技术社区……正是因为这些“非本质”的方面变化太快,才常常让人们误以为软件工程的大难题已经解决了。其实,这些进展并不能改变软件工程的根本难题,这也是著名的没有银弹(No Silver Bullet)论断所阐述的道理。那么,软件工程的根本难题是什么呢?现在特别时髦的AI自动编程工具是“银弹”吗?这是我们在后续章节中要深入讨论的话题。

1.2.2 产业成熟度的对比——对比从纸飞机开始的航空航天业

和其他产业相比,软件产业还是一个年轻的产业,它在发展过程中经历了不同的阶段。我们将其与发展历史更长的航空航天业作对比,见表1-1。

表1-1 从玩具到航空航天的发展

1.玩具阶段

100个小孩里有99个叠过纸飞机。

“设计/制造纸飞机”的过程,看起来技术含量不高,但是也有很多窍门。有些小孩在放飞纸飞机前,会用嘴对着纸飞机哈一口气,这里面也许有深奥的道理,也许只是迷信。在跟着这些纸飞机奔跑、欢呼的时候,这些小孩心里一定有“我长大了,要开飞机在天上飞”的想法。纸飞机、航模飞机和真飞机一样,都体现了某些基本的理论。

纸飞机——玩具阶段

2.业余爱好阶段

多年以后,很多人还有“在天上飞”的想法。有人居然就实现了:肯特·库奇,一位美国俄勒冈州的居民,在2007年用一百多个氦气球和一把椅子飞上了天。他说,“当你夏天躺在草地上的时候,看到白云飘过,你有没有幻想能跳到云朵上面?”所以他有一天忍不住就要实现他的梦想。

“飞屋”——业余爱好阶段

3.探索阶段

和上面提到的偶尔“疯狂”的行为比起来,另外一些人能持续疯狂好几年。1903年冬天,经过几年的努力,莱特兄弟在寒风凛冽的美国北卡罗来纳州海滩上试飞了他们的飞机。它飞了36.5米,历时12秒。几次试飞之后,大家还来不及在飞机前面合影留念,一阵狂风吹来,把飞机吹了几个跟头,大部分重要部件损坏了。

莱特兄弟的飞机——探索阶段

4.成熟的产业阶段

现在,航空航天业已发展成为一个巨大的产业。以民航业为例,全球每天有上千万人在这个行业工作,从飞机的硬件到控制导航的软件,再到机场等相关领域,更多的人每天都感受到它带来的便利和种种苦恼。

商用飞机和航空航天业——成熟的产业阶段

5.复杂系统的挑战

20世纪60年代,以美国的阿波罗登月计划为代表,人类的航空航天事业达到了一个高峰。面对将宇航员送上月球这样史无前例的复杂系统挑战,人们发现,单纯地“写程序”已经远远不够,必须用系统化、工程化的方法来确保软件的可靠性。因此,1968年,“软件工程”这个名词被首次正式提出,旨在用工程的纪律来应对日益复杂的软件开发流程和高质量要求。

复杂系统的挑战

6.新一代的创新

在航空航天业平稳发展了几十年后,新的创新浪潮再次涌现。在低空,无人机可以送快递、撒农药,或者用于战场;在更高空,SpaceX的星舰火箭在早期试飞中,爆炸或故障是大概率事件。但是大家仍然为每次发射而欢呼,这是为什么?

追求新范式,在失败中探索

我们从纸飞机谈到了民航业,再到航空航天业,这跟程序、软件、软件工程、软件产业有什么关系呢?我们可以做个类比,见表1-2。

表1-2 航空航天业和软件业的类比

航空/航天

软件

影响(如果成功/失败会如何)

玩具/基本知识:纸飞机/航模

写程序练习数据结构/算法,用新的语言尝试编写“Hello World”程序

影响仅限于自身,如果尝试失败,人们的兴趣会减弱。这类知识的应用也有比赛,如航模比赛、程序算法比赛,但是比赛后,这些算法高手写的程序的可维护性怎样?有人会拿着程序去发布商业软件吗

爱好者的尝试:气球+沙滩椅升空

用 JavaScript、Python、Ruby写网站

气球升空成功,当地晚报会报道此事。程序能跑起来,自己的博客也会吸引一些读者。失败之后呢?没关系,爱好者很快会捡起新的爱好

先行者的探索:莱特兄弟飞行

钻研新技术,应用新技术,在软件行业创新

即使第一个版本的飞机只飞了 36 米,明白人还是看到了其划时代的意义。很多软件原型也是这样。如果探索失败了,会怎么样?对于大部分创业者来说,如果还有资金和机会,他们会继续创新

成熟的工业:民航业

银行软件系统、互联网搜索引擎、电子商务系统、Windows操作系统

软件的发布会影响一个公司、相关行业及从业人员。很多人进入成熟的航空公司或软件公司就是为了获得一份稳定的工作。一个重要软件的失败会导致一个公司遭受挫折或失败,让很多人失去工作

新一代的尝试:快速试错,在成本等方面有颠覆性创新

以大语言模型为代表的AI工具,正在重塑教育、科研等各个行业,包括软件开发本身

社会对探索性失败容忍度高,鼓励创新;快速试错可加速技术成熟,但也需要注意伦理与安全边界

为何大家对SpaceX火箭的爆炸欢呼?这是因为SpaceX项目当前处于“探索阶段”,其目标是快速迭代、验证核心技术,因此社会对其失败的容忍度更高。这与敏捷开发、原型验证等软件工程实践有异曲同工之妙——在可控范围内不断冒险探索,以换取更快的创新速度;也与当前大语言模型研发中“训练-评估-迭代”循环模式的精神内核一致;却与已经进入成熟产业阶段的民航客机对零风险的追求截然不同。

在成熟的航空工业中,一个飞机发动机从构思、设计、制造到最后运行,不知道会涉及多少人、多少工序、多少流程、多少相关知识的验证。我们无法想象,某个商用发动机在飞行时出现问题,最初的设计师会爬进引擎中敲敲打打,然后探出脑袋说:“继续飞吧,我搞定了。”然而,在软件行业中,很多软件工程师往往以这样的行为而自豪。

一个成熟的产业一定是足够安全的,这里有两个案例。

2008年7月24日,澳洲航空公司的30号航班在一万米高空飞行。突然,飞机货舱区域的一个氧气瓶发生爆炸,飞机外壁被炸开一个洞。机组人员采取了一系列紧急措施,将飞机安全降落在附近的机场,机上所有乘客安全离开。

2009年1月15日,全美航空公司的1549号航班在起飞后撞上飞鸟,引擎出现故障,在三分钟内,机长把飞机降落在哈德森河面上,所有乘客安全撤离,无人伤亡。

试想我们的程序正在高速运行,突然发生了一个异常,程序能否安然退出,并保证用户的数据不被破坏?

1.2.3 软件工程的定义

软件工程的现代定义主要来自IEEE/ACM联合发布的《软件工程知识体系指南》,软件工程是把系统的、有序的、可量化的方法应用到软件的开发、运营和维护上的过程。软件工程包括下列领域:软件需求分析、软件设计、软件构建、软件测试和软件维护。

人们在开发、运营、维护软件的过程中形成了很多技术、做法、习惯和思想。软件工程把这些相关的技术和过程统一到一个体系中,叫“软件开发流程”。软件开发流程旨在提高软件开发、运营、维护的效率,并提升软件的质量、用户满意度、可靠性和可维护性。

光有各种流程的思想是不够的,我们还要有一系列的工具来保证这些思想能够在实践中有效地运作。软件工具有很多,有工程师自行开发的工具,有软件团队独有的工具,也有许多公开的软件工具,还有一些集成的系统工具,例如VS Code,以及公开的代码分享和管理平台,例如GitHub和Gitee等。近几年,随着AI技术的发展,我们又有了众多的AI自动编程工具、AI自动界面设计工具,等等。拥有了这些流程和工具,软件工程最终要达成的目标是什么?是追求绝对的完美吗?

1.3 软件工程的目标:在约束条件下创造“足够好”的软件

1.3.1 Bug、Feature和“足够好”

什么是好的软件?一些同学认为,所谓好的软件,就是没有缺陷(Bug)的软件;所谓软件工程,就是把软件中的Bug都清除掉的过程。这的确抓住了软件工程的一个要素。和软件打交道的专业人士都知道软件有“Bug”,Bug的多少直接反映一款软件的开发效率、用户满意度、可靠性和可维护性。

用户满意度:用户在使用软件时发现了很多问题,影响了用户使用软件的效率。

可靠性:某个软件经常崩溃,某个操作系统时不时死机,某个网站往往在大家最需要的时候登录不上去。

可维护性:某个软件太难维护了,按下葫芦起了瓢,修复了一个问题,另一个问题又出来了。也没有足够的文档,维护人员表示需要更多的资金和时间来维护这个软件,甚至建议推倒重写。

软件流程的质量:软件团队和开发流程的问题太多,导致团队成员无法互相协作,按时交付软件。这也可以说是软件团队的Bug。

历史学家们说计算机系统的第一个故障(Bug)是由一只误入计算机的蛾子引起的,如图1-1所示。因此,大家把软件的缺陷称为Bug。如图1-2所示,AI把“河里的三文鱼”理解成了“在河中的鱼肉切片”,这种缺乏常识的“一本正经的胡说八道”,则形象地揭示了AI时代Bug的新特征——程序本身没有崩溃,但其“字面级正确”的输出完全违背了用户的真实意图。

图1-1 Bug的历史(蛾子下方的文字:First actual case of bug being found)

图1-2 AI生成的“河里的三文鱼” (该图是2022年左右的AI“文生图”类工具基于 “salmon in the river”提示词的输出)

什么是Bug呢?简单地说,软件的行为和软件设计者或用户期望的不一样,就叫Bug。是否真的是Bug,取决于开发者、用户的不同角度。

例如,用户下载了某公司的软件,结果第二天发现计算机中莫名多了好几个新软件,而且这些软件卸载也很困难。这是Bug,还是用户应该感激的福利?

很多人认为有Bug就是质量不合格,没有Bug就是质量完美,其实这也未必。软件学院的小李同学穿了一条新潮的牛仔裤,她的同学果冻看到后就善意地上前提醒:你裤腿上有两个破洞,肉都露出来了,赶紧去退货!这是故障(Bug),还是功能(Feature)?

我们在大街上看到很多不同品牌的汽车,这些汽车出厂时都通过了行业的质量标准。但是不同的人对这些汽车的“好”的认可度相差甚远,这正说明了“足够好”是一个相对的概念。市面上有这么多不完美的软件产品,软件团队为什么还要把这些不完美的软件发布出来呢?软件工程的核心是权衡(trade-off),软件项目管理的核心任务,就是要在时间、成本等多种约束条件下做权衡,决定一个软件在什么时候能“足够好”,从而可以发布。

1.3.2 如何衡量“足够好”

如果开发团队说软件“足够好”了,接收方如何验证呢?在汽车、航空等行业,软件的质量是非常关键的,这些行业都有行业标准或者国家标准作为评判依据,简要总结如下。

(1)确认(Validation):“软件行为满足用户要求,用起来没错,体验好”→通过海量真实测试和仿真测试。软件功能完备,体验好,满足压力测试和各种合规测试。

(2)验证(Verification):“软件是用正确的方法开发的,代码合规”→通过严格的静态测试和动态测试。

所有代码通过单元测试,代码的复杂度符合标准,等等。

软件的需求、设计、测试、发布等各项工作可以双向追溯。

(3)功能安全性(Function Safety):“万一发生意外情况,有兜底机制,不会造成严重财产损失和生命危险”,本章前面提到的飞机的安全功能,就属于这一类要求。

开发团队要通过故障分析和冗余设计等手段来提高功能安全性。(软件测试和质量保障的相关内容详见第13章和第14章。)

说到商用软件和爱好者写的程序的区别,我们还可以看看下面这个例子。

假设一架民航飞机上有一个功能需求,用户使用它的概率是百万分之一,你还要实现这个功能吗?你会选择:

(1)根本不考虑;

(2)如果没时间实现这个功能,就算了;

(3)实现了,但是不用告诉用户;

(4)实现了,而且不厌其烦地告诉用户如何使用。

这个功能是什么呢?谜底是:

飞机的安全功能

乘坐飞机时,乘务人员不厌其烦地给你介绍飞机有几个应急出口,以及如果氧气罩自动掉下来,应该怎么做;你身下的坐垫是可以漂浮的,飞机还可以在水面上降落,撤离飞机的时候应该怎么跳到逃生滑梯上……但是,有多少人使用过这些“功能”?如果你买了一张特便宜的机票,登机时,乘务人员说:

为了节约成本,本次航班既没有那些安全设备,也没有安全培训——反正大家都不会用到……

你还敢坐吗?

1.3.3 AI时代的“足够好”

最近几年,AI技术能在很大程度上帮助程序员实现各种基本的功能,这当然是一件大好事。但这也给“足够好”的标准引入了新的挑战。这些挑战包括:AI生成的代码可能缺乏确定性,即相同的输入不一定每次都产生相同的输出;缺乏透明度,难以理解其决策逻辑;更严重的是,代码表面看似有效却在实际测试的边界条件中失败。此外,AI还可能带来“质量幻觉”,使开发者过度依赖AI生成的测试结果,而忽视其深层缺陷。

鉴于这些风险,人类必须确保AI生成的代码与业务意图对齐,并考虑代码的可维护性、安全性、伦理与合规性。

在学校里,一门软件工程课程的项目验收标准是什么?本书所倡导的教学与培训目标是:引导读者通过理论学习和具体项目实践,达到以下三个方面的要求。

(1)研发出符合用户需求的软件。

能够通过实际工作收集、分析并提炼用户需求,并在软件发布后依据真实数据验证这些需求是否得到有效满足。需求应源于实际,而非自我设想的“伪需求”,或盲目跟从、缺乏实证的所谓“常见需求”(如脱离真实使用场景、缺乏用户基础和数据支撑的“图书馆管理系统”)。

(2)遵循一定的软件流程,在预定时间内发布“足够好”的软件。

最终提交的软件不应是少数同学仓促熬夜完成的应急之作,而应经历规范的软件开发过程,依靠团队全体成员的协作,在一个较长周期(如一个学期)内逐步迭代完成,并有详细的迭代记录。优秀的软件产品绝不是靠个别人临时突击实现的。

(3)能够证明所开发的软件具备可维护性与可持续演进的能力。

用户需求分析文档与设计文档、测试文档对应,核心功能设计文档与软件实际行为相符;源代码完整且可追溯每一次修改记录;具备完整的Bug修复记录;关键模块有可正常运行的单元测试及压力测试脚本等。

若能达到上述要求,即可视为已初步掌握软件工程的核心实践能力。要在实践中应用这些能力,还需要了解软件工程所涵盖的广阔知识领域。

1.4 软件工程的广阔天地:知识领域与内涵

软件工程不仅仅是编写代码,它更是一个涉及技术、管理、过程与约束的综合性学科。为了系统地掌握它,我们需要一张“知识地图”。那么,软件工程师究竟需要具备哪些知识?这些知识又如何构成一个有机的体系来应对现实世界的挑战呢?为了系统地回答这个问题,学术界和产业界共同构建了软件工程的知识体系(Body of Knowledge)。这个体系随着技术演进和实践积累不断丰富发展,在2022年,IEEE发布的SWEBOK V4.0就是其中一份权威指南。它界定了软件工程的 18 个知识领域。为了方便读者理解,我们把这些知识领域提炼为相互支撑的三大支柱。让我们通过“超算”项目的演进,看看这三大支柱如何共同支撑起在约束条件下交付“足够好”的软件产品的能力。

支柱一:核心生命周期——构建“正确”的软件

核心洞察:这是一个将模糊的用户需求转化为可靠软件的“创造流”。

超算”项目的实战例子

需求:老师随口说“最好能看出学生的进步”,这需要分析为“系统需记录并可视化每个学生的答题历史与正确率趋势”。

设计:如何实现“避免题目重复”?是每次生成时查全部记录(简单但慢),还是预生成题库再分配(复杂但快)?这个设计决策将对性能产生深远影响。

构建与测试:你写好了自动批改功能,但通过一个测试用例发现——当题目“1÷3”的答案是“0.33333...”时,系统因浮点数精度问题误判学生的答案为“0.333”。若缺乏测试,这个Bug就会引发用户投诉。

维护:假设后续要求符合规定“禁止超纲教学”,你需要修改代码,为每道题打上“知识点”标签,并增加筛选规则。

AI时代的新思考:你可以让AI根据“小学四年级分数概念”生成100道初始题目,但你必须审核这些题目是否符合教学大纲。AI是副驾驶,你仍是机长

支柱二:支撑性基础——确保“好用”与“耐用”

核心洞察:光把功能做出来还不够。当用户从1个(阿超的儿子)变成1000个(全校学生)时,支撑性基础决定了软件是会崩溃还是会持续稳健运行。

超算”项目的实战例子

软件架构:最初的“一个文件处理所有请求”的架构,在期末考试周全校同时在线时会瞬间崩溃。你必须改进软件架构才能支撑高并发访问。

质量:如何保证网站“永远可用”?你需要建立监控和告警机制,在服务器宕机时能第一时间通知你,而不是事后接到抱怨电话。

安全:网站上线后,你必须考虑提交的答案是否包含恶意脚本,以及数据库中的学生信息是否会泄露。这些安全措施在个人程序中无须考虑,但在软件产品中至关重要。

AI时代的新思考:如果你用一个AI应用生成“个性化推荐题目”,如何测试这个AI应用的推荐是否准确?如何防止恶意用户通过特殊输入“骗”AI生成不良内容?支撑AI的系统,其本身需要更坚固的支撑。

支柱三:过程与约束——在现实世界中“高效”协作

核心洞察:软件是由人在特定的经济、社会和团队约束下开发的。

超算”项目的实战例子

配置管理与协作:当你和英国的程序员同时修改“中英文切换”功能时,版本控制系统能防止你们互相覆盖对方的工作,并能清晰地合并代码。

项目管理:教导主任要求“明天上线英国版”,你如何评估这是个不切实际的目标,并和他协商出一个可行的发布计划?这是项目管理的核心。

工程经济学:是买两台便宜的服务器自行投入很多时间来做备份,还是直接使用更贵的云服务?这个成本决策关乎网站的稳定性和公司的现金流。

专业实践:竞争对手提出“共享题库”的合作,你能直接把对方网站上的题目爬取过来用吗?这涉及法律与伦理。

AI时代的新思考:使用AI编码助手生成的代码,其版权归属可能存在争议。在项目计划中,如何为“AI生成代码后的深度调试”这个新任务估算时间?管理AI,已成为软件工程管理的新维度

通过“超算”项目的演进我们可以看到,从“能跑的程序”到“够用的软件”,再到“成功的服务”,每一次飞跃都依赖这三大支柱的协同加固。

软件工程教会我们的,正是在正确的时间,运用正确的知识,去解决这些必然会出现的问题。这种系统性的思维框架,也体现了软件工程与其近亲——计算机科学的联系与区别。

1.5 软件工程与计算机科学

计算机科学(Computer Science)研究哪些领域,它们又是怎么分类的呢?综合ACM/IEEE文献对这个领域的分类和我自己的体会,我认为可以分类如下。

1.计算机科学理论与基础(Theoretical Computer Science & Foundations)

这个领域回答了“计算的本质是什么?哪些问题可以通过计算解决?解决这些问题需要多少资源?我们如何用严谨的数学方法来描述和验证计算过程?”这当然包括了广泛的数学基础。

2.核心计算机系统(Core Computer Systems)

这个领域回答了“计算机硬件是如何设计和工作的?如何高效地管理计算机的资源(如CPU、GPU、内存)?计算机之间如何可靠地通信?以及如何让多台计算机协同工作来处理复杂任务?”

3.软件工程与信息管理(Software Engineering & Information Management)

这个领域回答了“如何系统地、高效地、高质量地开发和维护大型复杂软件?如何有效地存储、组织、检索和管理海量数据,并确保其安全和完整性?”

4.人工智能与智能系统(Artificial Intelligence & Intelligent Systems)

这个领域回答了“如何让计算机学习、推理、理解、感知和决策?如何构建能够展现智能行为并解决复杂认知问题的系统?”

5.交叉应用(Interdisciplinary Applications)

这个领域回答了“如何设计直观、高效、愉悦的计算机界面和体验,使人与计算机能够无缝互动?以及如何将计算机技术应用于其他科学、工程和社会领域,以解决现实世界的多样化问题?”

分析计算机科学和软件工程的各个子领域,我们可以看到,计算机科学中的理论研究部分,大多可以从形式上证明,与数学、离散数学、数理逻辑密切相关;计算机科学中与实践相关的部分,都和数据以及其他学科相关联;软件工程则和人的行为、现实社会的需求息息相关。软件工程的研究目标(高效率的软件开发、运营和维护)中都有“人”出现,这些“人”可以是项目需求的提供者,可以是软件的开发人员,还可以是软件的用户。这一特征与计算机科学的其他子领域明显不同。其实,在任何科学领域,都有偏理论的子领域和偏应用的子领域(例如数学与应用数学),当偏应用的子领域得到长足发展之后,就会更多地被大家所熟知,甚至成为一门独立的学科,但这并不说明它们有优劣之分。

计算机科学家托尼·霍尔比较过计算机科学和软件工程的不同侧重点(见表1-3)。

表1-3 计算机科学和软件工程的不同侧重点

计算机科学

软件工程

发现和研究长期的、客观的真理

短期的实际结果(具体的软件会过时)

理想化的

对各种因素的折中

确定性,完美,通用性

对不确定性和风险的管理,足够好,具体的应用

各个学科独立、深入研究,做出成果

关注和应用各个相关学科的知识,解决问题

理论的统一

百花齐放的实践方法

强调原创性

最好的、成熟的实践方法

形式化,追求简明的公式

在实践中建立起来的灵感和直觉

正确性

可靠性

计算机科学理论的进展会帮助软件工程(例如对程序正确性的分析);软件工程的进展(更好的工具,更多的应用领域)会帮助计算机科学家更有效地进行实验和探索。理论方面的不足或错误,也会对实践造成深远的影响。托尼本人反省,他在20世纪60年代设计Algol W语言时引入了对空变量的引用(Null Reference),这对后来的编程语言影响很大,他估计这个设计给工业界造成的损失应该在10亿美元以上。

我国高校大多设有计算机类相关院系。大学生在考虑研究生方向时,对于计算机科学相关专业的导师,可以问“您在研究计算机领域哪些长期的、客观的真理?”对于软件工程相关专业的导师,则可以问“您在研究软件工程领域哪些最前沿、最有实际价值的实践方法?”

1.6 总结:软件工程师的宗旨

最近非常火热的人工智能,和软件工程有关系吗?当然!人工智能研究的一个重大挑战,就是计算机程序能否在国际象棋中打败人类。从20世纪60年代开始,就有很多研究人员从理论和“智能”的角度出发进行研究,并取得了一定进展,但是离最终胜利还很远。1985年,还是研究生的许峰雄这样想:

我们从一个不同的方向去逼近这个问题。我们——至少我自己——把这个问题看成一个纯粹的工程问题。

历史证明,这种从工程的角度出发,用“蛮力”提高计算速度的工程方法远远甩开了同时代的各种“智能”方案。1997年,许峰雄带队设计的“深蓝”计算机战胜了国际象棋大师加里·卡斯帕罗夫。

时至2016年,AlphaGo在先进算法的基础上,利用多种工程手段,大大提高了策略选择和价值判断的效率,把围棋AI从“穷举”提升到“智能决策”的高水平,以4 : 1的比分打败了人类顶尖棋手。

2025年初,DeepSeek团队利用各种工程手段,把GPT对话工具的训练成本和推理成本降低至少一个数量级,让广大用户能低成本地享受到前沿的AI智能服务。这是工程和AI算法携手改进的又一个例子。

软件工程和计算机科学的其他领域也有很多交叉。软件和软件工程的早期开拓者有不少曾从事硬件设计、计算机工程等领域的工作,他们带来了相应领域的不少思想和术语。软件工程的“工程”二字意味着其和许多工程领域的学科,以及管理学科有很大的关系。软件工程和机械工程、航空工程等工程学科一样,也包含工程理论、质量控制论等原理。软件团队开发和维护软件的行为,就和质量控制论中的PDCA(Plan-Do-Check-Act)模型有很深的联系。所有这些和“工程”相关的学科都有共性,但它们和各种“科学”的学科还是有区别的。正如专家所归纳的:

哲学家的宗旨是:我思,故我在。

科学家的宗旨是:我发现,故我在。

工程师的宗旨是:我构建,故我在。

人类要生存,人类文明要向前发展,离不开思考、发现、构建。笔者曾在微软和其他科技公司的研发团队工作了近三十年,参与过很多项目,这些项目各有特点。

Build To Learn:开发软件、构建系统的目的是做进一步的实验,试图发现客观规律或探求某种方法的优劣。这类项目经常是科研论文的基础。很多同学的“编程大作业”就属于这一类型。

Build To Show:为了突出展现某个技术的作用,开发一些以演示为目的的软件。这类项目很吸引眼球,经常获得新闻报道,但是功能未必全面。

Build To Serve:为了服务特定范围的目标用户而构建工具等,有时以公开API的形式发布,供其他研发人员使用。

Build To Win:以在市场上赢得用户为目标而开发软件。这类项目也是种种科学发现、技术突破重要的试金石。

最近这几年,AI似乎是大家学习、展示和制胜的关键,但是,从前面“深蓝”、AlphaGo和DeepSeek的案例来看,在AI这个高度“科学”的领域,突破和应用往往离不开强大的工程能力。虽然AI模型本身是科学家研究的成果,但将其部署、优化、扩展并服务于大众,仍然需要深厚的软件工程功底。AI时代的许多项目兼具多重属性,例如开源一个大语言模型,既是Build To Show(如展示技术实力),也是Build To Serve(如为社区提供工具),其最终目标更是Build To Win(如建立生态和行业标准)。我们不必担心“AI会取代传统软件工程”,而应投入到最适合自己的项目类型中去,发挥自己的能力,去求知探索、去引领制胜!

(注解、讨论和练习,请扫描本书封底的二维码获取)

相关图书

SDD实战:规范驱动开发之道
SDD实战:规范驱动开发之道
Agent Skills开发实战像搭积木一样构建智能体
Agent Skills开发实战像搭积木一样构建智能体
Agent设计模式 图解可复用智能体架构
Agent设计模式 图解可复用智能体架构
AI科研绘图:Nano Banana极速实战指南
AI科研绘图:Nano Banana极速实战指南
Skills+OpenClaw:从零打造个性化AI助理
Skills+OpenClaw:从零打造个性化AI助理
Codex快速入门:Harness工程落地
Codex快速入门:Harness工程落地

相关文章

相关课程