<audio id="audio" title="01 | 到底应该怎样理解软件工程？" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ae/d7/ae41f11ef249a3a63ea7315bad3334d7.mp3"></audio>

**你好，我是宝玉，我今天分享的主题是：什么是软件工程？**

当有人问你什么是软件工程，你会想到什么？

也许你会想到软件，会想到建筑工程，也许对此还没有什么概念。不要紧，在回答这个问题前，我们先来看看软件工程和我们的日常生活有哪些关系。

作为一个程序员，你的日常大致是这样的：早上被手机的闹钟叫醒，然后坐地铁去上班。在路上你会打开微信和朋友闲聊几句，刷刷微博，还会用Youtube看看视频充充电；上班的时候，你打开Mac电脑，用VS Code写程序，用Chrome看网页，下班后再玩几局守望先锋游戏。

你发现了没？在这一天的日常生活里面，软件无处不在。手机操作系统软件、闹钟App、微信、微博、Youtube、Mac OS、VS Code、Chrome、守望先锋，这些都是软件，你的日常生活已经和这些软件密不可分。

## 软件是怎么被创造出来的？

那么你有没有想过，这些软件是怎么来的呢？

首先，它们的诞生都是有人想要造一个东西。这其中的很多故事你都耳熟能详：张小龙创造微信、乔布斯创造iOS、暴雪想做一款不一样的射击游戏……他们首先有着这样的意图，然后，他们立项做这样的产品。

每一款软件项目背后，都有很多人在参与。你无法想象微信这样复杂的App靠张小龙自己可以开发出来；你也不会相信iOS是乔布斯一个人设计出来的；像守望先锋这种游戏的背后，有成百上千的游戏策划、美术设计、程序开发人员。

从立项到第一个版本的发布，每个成功的软件都需要有计划、有步骤地进行，什么时候发布第一个版本、第一个版本有什么样的功能、什么时候发布第二个版本、第二个版本有哪些地方要改进，这些都是研发过程中需要考虑的问题。

比如，守望先锋是在2013年立项，他们计划做一个基于职业的 MMO 游戏，他们先花了几个月的时间做了第一个Demo演示，只有四个英雄和一个张地图。

<img src="https://static001.geekbang.org/resource/image/a0/9e/a04f39349e6f3de9c10781f8da8f779e.jpeg" alt="" title="图片来源：The treasures of the Overwatch Archives panel at Blizzcon">

然后，他们要在 2014 年的“暴雪嘉年华”发布这个游戏的试玩版，包含12个英雄和4张地图。

<img src="https://static001.geekbang.org/resource/image/ae/e1/ae4a7ceadb1163240508a5d125a092e1.jpeg" alt="" title="图片来源：The treasures of the Overwatch Archives panel at Blizzcon">

最终这个游戏在2016年5月正式发布了。这样从立项一步步到最终发布，历时三年，中间经过了诸多环节。

类似的例子还有微信，2010年11月20日立项，2011年1月21日第一版上线，当时的功能还非常简陋，只能发送文本消息和照片。之后才是一个个版本的迭代，直到你现在看到的微信。

**像这种有人参与、有计划、有步骤地造一件产品，我们通常称为“工程”。**

所有工程的本质，就是要做出有用的产品，比如造房子的建筑工程、造火箭的航天工程。像网红“手工耿”一样专搞无用发明的情况，我们是不能称为“工程”的。

在软件领域，对应的就是“软件工程”，这些我们日常使用的软件背后，都是基于软件工程的方法在开发、运行和维护的。

## 如何摆脱“软件危机”？

也许有人会认为，不用软件工程，我一样可以开发软件出来。这确实没有错，因为如果一个人没有学过建筑工程，他也是可以造一个房子出来，只是造出来大概会是这个样子：

<img src="https://static001.geekbang.org/resource/image/57/52/57222a73010237e5ab069351b535df52.jpg" alt="">

我们知道，不按照建筑工程造房子，是会出事故甚至死人的。而在软件工程的历史上，也是真的有造成过很大损失、甚至还有人为之丧命的事件存在。

OS/360操作系统是上世纪60年代最复杂的软件系统之一，也是第一个超大型的软件项目，一共有1000名左右的程序员参与了项目的研发，花费了5000个人年，最终无法运行。项目负责人佛瑞德·布鲁克斯后来写了一本软件工程的经典书籍《人月神话》，承认在他管理这个项目的时候，犯了很多错误，造成了价值数百万美元的损失。

如果是说OS/360还只是造成了经济损失的话，Therac-25事件就是真的导致了人员死亡。Therac-25是加拿大原子能有限公司（AECL）所生产的放射线疗法机器，在1985年到1987年之间，在美国及加拿大，至少有六起和Therac-25相关的医疗事故是因为程序bug，导致部分病患受到比正常剂量高一百倍的辐射，因而造成患者重伤甚至死亡。

发生这些惨痛的事，原因却并不难理解。

在计算机刚发明出来的时候，计算机的能力非常有限，只能接收简单的指令和运算，不需要软件工程也可以开发出简单的软件。

但是，当软件的规模越来越大，复杂度不断增加，软件项目开发维护过程中的问题就逐步暴露出来：**软件产品质量低劣、软件维护工作量大、成本不断上升、进度不可控、程序人员无限度地增加。**所以在60年代，“软件危机”的概念被提出来。

为了摆脱软件危机，1968年秋季，北大西洋公约组织的科技委员会召集了近50名一流的编程人员、计算机科学家和工业界巨头，讨论和制定对策。在那次会议上第一次提出了“软件工程”（software engineering）这个概念。

从此诞生了一门新兴的工程学科：**软件工程，它是为研究和克服软件危机而生。**

在这次会议上，同时也提出了“软件工程”的定义：

> 
<p>为了经济地获得在真实机器上可靠工作的软件而制定和使用的合理工程原则。<br>
（Software engineering is the establishment and use of sound engineering principles in order to obtain economically software that is reliable and works efficiently on real machines.）</p>


1993年，电气电子工程师学会（IEEE）给出了一个更加综合的定义：

> 
<p>将系统化的、规范的、可度量的方法用于软件的开发、运行和维护的过程，即将工程化应用于软件开发中。<br>
（Software Engineering: (1) The application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software; that is, the application of engineering to software. (2) The study of approaches as in (1).）</p>


如果你去搜索一下“软件工程定义”，你还能找到很多其他定义，这里就不一一列举。我们没必要花太多时间在这些字面解释上，关键是要抓住这些定义的本质：**就是要用工程化方法去规范软件开发，让项目可以按时完成、成本可控、质量有保证。**

## 软件工程的演化史

对比传统的工程学科，和软件工程最接近的就是建筑工程了。设想一下建一座房子：首先要先立项、设定预算，然后画设计图，再是施工，施工完成后，由专业人士进行质量检查，质检合格后入住。

**开发软件本质上也是像盖房子一样，是从无到有创造的过程。工程化的方式，就是你分步骤（过程），采用科学的方法，借助工具来做产品。**

于是参考建筑工程，整个软件开发过程也被分成了几个阶段：需求定义与分析、设计、实现、测试、交付和维护，这也就是我们常说的软件项目生命周期。

当然，各个阶段都会有人的参与，于是产生了软件项目里的各种角色：项目经理、产品经理、架构师、程序员、测试工程师、运维工程师。而对这整个过程的管理，我们通常称之为“项目管理”。

同时，也很自然就衍生出一套最基础的过程模型：瀑布模型。

<img src="https://static001.geekbang.org/resource/image/88/d4/88e84f12bc09d3d2a0f5c25e22c50ed4.jpg" alt="">

瀑布模型的诞生，在当时是有非常重大的意义的，让软件开发从无序到有序，让大家更好的分工协作，同时每个阶段又衍生出各自的方法学和工具，例如需求分析、软件测试等等。

然而瀑布的特性决定了它只能从上往下流，而且从上到下走完整个周期很长，所以一旦出现了需求的变更，将会非常痛苦，很多事情需要重头再来。

于是基于瀑布模型，又衍生出V模型、原型设计、增量模型、螺旋模型等模型，试图改善瀑布模型存在的一些缺陷。这些改进模型的发展趋势上就是缩短项目周期，快速迭代。

这样到了90年代，各种轻量级开发方法例如Scrum、极限编程等也不断被提出。到了2001年，这些轻量级开发方法一起组成了敏捷联盟，其后敏捷开发如同星星之火，逐渐形成燎原之势。

<img src="https://static001.geekbang.org/resource/image/3b/3f/3b66yy913ee9d30676f9b81145b65a3f.jpg" alt="">

近些年，云计算、微服务这些新技术的产生，也对软件工程产生了影响。云服务让分工更细，很多企业可以将运维、服务器维护、DBA、甚至某些独立服务交给云服务商；微服务让大团队变成小团队，每个小团队可以更专注于细分领域，减少相互之间的依赖。 ​

## 一个公式

当你大致了解整个软件工程的演变发展史，你会发现，软件工程的知识，都是建立在软件项目的过程，或者说软件项目生命周期之上的。

**基于软件过程，我们有了角色分工，有了对过程的管理和工具，对过程中每个阶段细分的方法学和工具。**

现在，如果再回头看看我们的问题“什么是软件工程？”其实可以总结为：软件工程就是用工程化的方法来开发维护软件。也可以说软件工程就是用一定的过程，采用科学的方法，借助工具来开发软件。

如果用一个简单的公式表达，那就是：**软件工程 = 过程 + 方法 + 工具。**

## 总结

今天，我和你一起追溯了一下软件工程的起源，你知道了软件工程学科的产生，就是为了解决软件危机。也见证了整个软件工程的演变历史，从瀑布模型到敏捷开发。

从1968年提出软件工程到现在，正好是50年。在2002年，我最开始学软件工程专业的时候，还只有瀑布模型、需求分析、系统设计等这些传统软件工程内容，但是经过十几年的发展，在软件项目中，敏捷开发、持续集成、微服务等这些新兴内容已经开始在软件项目中占据越来越重要的位置。

可以预见，未来软件工程领域还会有新的概念、新的知识诞生。但是万变不离其宗，只要你抓住软件工程的本质，无论将来如何变化，你总能很快掌握新的知识内容。

**而软件工程的核心，就是围绕软件项目开发，对开发过程的组织，对方法的运用，对工具的使用。**

## 课后思考

当然，每个人对于软件工程的理解也是不同的，你理解的软件工程是什么样子的呢？欢迎在留言区留言讨论。

感谢阅读，如果你觉得这篇文章对你有一些启发，也欢迎把它分享给你的朋友。
