关于软件工程
软件工程这门课很少讲“代码怎么写”。它的基本假设是:你已经具备一定的开发能力、熟悉技术栈、理解计算原理。它不是不关心技术细节,而是把视角提升到工程层面,关注如何系统化地构建可靠、可维护、可交付的软件系统。对于开发经验不多的学生,它可能显得抽象;但对真正做项目的人来说,它非常实用。
软件项目的成败,往往不只取决于技术是否精湛、代码是否优雅。软件工程要我们关注那些容易被忽略的因素:客户真正想要什么、团队如何协作、风险如何控制、时间和预算如何平衡。它会反过来让我们重新思考已经掌握的技术该怎么用、什么时候用。
另外,软件种类繁多,客户也各不相同。如果有人声称软件工程有“唯一最好的方法”并贬低其他方法,那其实脱离现实。软件工程已经发展出很多方法论,它们各有适用场景。我们既要掌握多种方法,也要学会根据项目特点做选择。这也是软件工程想教会我们的核心能力之一。
虽然方法很多,但总有一些基本原则适用于大多数软件项目。下面先回答几个基础问题,建立整体框架。
什么是软件
软件(Software)是一系列按照特定顺序组织的计算机数据和指令的集合。一般来说,软件被划分为系统软件、应用软件和介于二者之间的中间件。软件包括在计算机上可以运行的程序,以及与程序相关的文档。简单来说,软件就是“程序 + 文档”的集合体。软件产品可针对特定客户开发,也可以为通用市场开发。
什么是工程
- 狭义上的工程:以某组设想的目标为依据,应用有关的科学知识和技术手段,通过一群人有组织的活动,将某个或某些现有实体(自然的或人造的)转化成具有预期使用价值的人造产品的过程。
- 广义上的工程:一群人为了达到某种目的,在一个较长的时间周期内进行协作活动的过程。
软件工程显然属于后者:多人协作、目标明确、周期较长、强调过程管理。
什么是软件工程
IEEE 在 1993 年给出定义:
软件工程将系统化的、规范的、可度量的方法应用于软件的开发、运行和维护的过程,即将工程化应用于软件中。
可以从三个层面理解这个定义:
- 方法层面:使用系统化、规范化、可度量的方法,而不是凭感觉写代码。
- 过程层面:覆盖软件从开发、运行到维护的整个生命周期。
- 目标层面:把工程化的思想引入软件领域,让软件开发成为可控、可预测、可改进的活动。
软件工程的本质
- 关注于大型软件产品的构造
- 控制软件的复杂性
- 提高开发软件的效率
- 在开发软件过程中合作
- 满足用户的需求
- 由具有一种文化背景的人替具有另一种文化背景的人创造产品
软件工程的目的
课本上给出的答案是:软件工程的目的是支持专业化的软件开发,而不是个体编程。
但随着时代发展,独立开发者和小团队也越来越多。他们也会运用软件工程的思想和方法。因此也可以这样理解:
软件工程的目的是支持复杂软件系统的持续开发与演化。
软件工程的重要性
个人和社会越来越多地依赖于先进的软件系统。长远来看,运用软件工程方法和技术去开发软件系统,比单纯为个人程序项目写程序更便宜、更可控。
软件工程技术的两个明显特点
- 强调规范化:有标准、有流程、有约束。
- 强调文档化:把设计、决策、需求、接口等写成可交流的文档。
什么是好的软件?
好的软件通常具备以下特点:功能性(Functionality)、可用性(Usability)、可维护性(Maintainability)、可靠性(Dependability)、安全性(Safety)、可接受性(Acceptance)和高效性(Efficiency)。
高质量的代码固然重要,但它只是手段,不是软件工程的最终目的。很多工程师容易陷入“用技术手段解决一切问题”的思维,但真正遇到软件故障时,问题的根源往往不在代码本身,而在需求、设计或沟通阶段。忽视前期阶段,问题只会越滚越大。
课本定义是:好的软件应具有用户所需的功能与性能,而且应该可维护性、可依赖性、可用性。
课本还给出了好的软件的重要属性:可接受性、可依赖性和信息安全性、效率、可维护性。
可以简单记忆为:好用、可信、安全、可维护、用户愿意用。
软件的开销
即便有 AI 辅助,软件开发依然是一项昂贵的活动。它消耗金钱、时间、精力和其他资源。我们之所以觉得软件开发“便宜”,往往是因为与硬件开发相比,软件修改更方便、开发更快捷。但这并不意味着可以忽视软件的开销。
软件工程真正关心的是软件的开发成本和维护成本,而不是软件的复制成本。 软件复制成本很低,但开发和维护成本可能非常高。
Client、Customer 和 User 的区别
在考虑开销时,必须弄清楚“谁付钱、谁决定、谁使用”。
| 角色 | 英文 | 含义 |
|---|---|---|
| 客户/委托方 | Client | 软件开发团队为谁创建软件,谁就是客户。客户提供资源,期望获得产品回报。 |
| 购买者/顾客 | Customer | 决定是否购买已完成的软件产品的人。 |
| 用户 | User | 实际使用软件的人。有时 Customer 和 User 是同一个人。 |
这三个角色可能分离,也可能重合。技术人员和他们往往有不同的评判标准。因此,软件工程的目标不是单纯构建“技术上成功”的软件,而是要搞清楚客户真正想要什么,并在此基础上做出取舍。
此外,组织变动也会带来不确定性,增加开销。例如客户变更、团队成员变动等,都需要纳入考虑。
考虑这些因素,是因为我们真正的目的是用更少的开销构建出更好的软件系统。
软件开发的风险
软件开发过程中,团队可能在某个或多个阶段出现问题,导致项目失败。常见问题主要有三类:
- 功能风险:软件无法按预期工作,Bug 过多。
- 成本风险:开发开销超出预算。
- 进度风险:无法在预期时限内交付。
这些问题可能单独出现,也可能组合出现。
风险不仅影响项目,也影响团队和公司
软件开发失败可能导致公司破产。软件没按预期工作、开销过大、延期交付,都会给公司带来巨大经济损失。大多数软件需要团队协作,有时甚至需要多个团队合作,软件还可能建立在他人或他团队的基础之上,这些都会引入更多风险。
因此,团队合作是软件开发的基本技能。即便个人开发者越来越多,协作理念依然适用:你也要和“过去的自己”“未来的自己”合作。而且个人的风险承受能力远低于公司或团队。
项目规模扩大、团队扩大、基于遗留项目开发,都会让风险进一步增加。
软件工程的核心问题之一:将风险最小化
要降低风险,首先要确保真正理解客户想要什么。开发团队需要主动与客户沟通,提出技术洞见和细节建议,但最终决定权属于客户。客户满意度是判断软件开发是否成功的重要标准。
降低风险的基本流程:
- 可行性研究:项目开始前判断项目是否值得做、能不能做。
- 需求明确:清楚客户到底想要什么。
- 持续汇报进度:让客户了解项目状态,出现问题及时调整。
- 验收和测试:开发完成后验证功能是否符合预期,客户参与验收。
- 交付移交:确认产品符合要求后交给客户。
这个流程的核心是沟通——不仅是开发团队与客户的沟通,也包括团队内部的沟通。
Visibility:项目的可见性
Visibility 指项目状态的透明性、可观察性。如果客户问“项目进展如何”,开发团队只能回答“快做完了”或“做了一半”,说明 Visibility 很差——团队无法给出明确、量化的进度。
Visibility 越好,项目越顺利,风险越小。提高 Visibility 的方法包括:定期汇报、里程碑评审、燃尽图、版本交付等。
缩短开发周期:让风险尽早暴露
风险不是一成不变的,它会随着时间累积。 小项目比大项目好管理,短周期比长周期风险更小。如果三个月后才做集成,期间每个人可能都觉得自己的模块没问题,但集成时才发现接口、数据库字段等完全不匹配。
问题不是最后一天才出现的,而是第一天就出现了,只是一直没被纠正。软件开发不害怕 Bug,害怕的是 Bug 到最后才暴露。越早发现问题,修复成本越低。
因此,可以通过缩短开发周期、提高交付频率,让问题尽早暴露。这也是敏捷开发的基本原则之一。
敏捷真正追求的不是“更快地开发软件”,而是“更快地获得反馈,更快地适应变化”。
软件危机
当风险积累到一定程度,就可能引发软件危机。软件危机的主要表现包括:
- 软件开发周期大大超过规定日期。
- 软件开发成本严重超标。
- 用户对“已完成”系统不满意的现象经常发生。
- 软件产品的质量往往靠不住,Bug 一大堆,Patch 一个接一个。
- 软件的可维护性非常糟糕。
- 软件通常没有适当的文档资料。
- 软件的成本不断提高。
- 软件开发的生产效率的提高赶不上硬件的发展和人们需求的增长。
软件危机的出现,正是软件工程这门学科诞生的历史背景。它的核心诉求是:让软件开发从“手工作坊”走向“工程化”。
关于软件工程师的责任
软件工程师不仅要对代码负责,更要对软件产生的影响负责。 软件已广泛应用于金融、医疗、交通、能源、人工智能等领域,一个错误的软件决策可能造成巨大的经济损失,甚至危及生命安全。因此,软件工程师是一种 Professional(专业人士),不仅需要技术能力,更需要职业责任。
软件开发本质上是一项 高影响力的工程活动。软件工程师的责任包括:
- 写出正确的软件、构建高质量的软件;
- 保护客户利益、保护用户利益、保护团队利益;
- 承担社会责任。
软件工程师的四项基本责任
| 责任 | 核心要求 | 本质 |
|---|---|---|
| 保密(Confidentiality) | 尊重客户、公司和用户的信息,不泄露商业秘密、源代码和隐私数据 | 维护信任 |
| 能力(Competence) | 只承担自己有能力完成的工作,不夸大技术能力,遇到超出能力范围的问题主动寻求帮助 | 对专业负责 |
| 知识产权(Intellectual Property) | 遵守版权、许可证和知识产权规定,不抄袭、不盗用、不非法使用软件和代码 | 尊重他人的劳动成果 |
| 合法使用计算机(Computer Misuse) | 不滥用技术能力,不进行未授权访问、恶意攻击或其他违法违规行为 | 技术应服务社会,而不是危害社会 |
现代软件工程的伦理要求
现代软件工程不仅要求工程师“遵守规则”,还要求具备工程伦理:
- 诚实地报告风险;
- 尊重团队成员的意见;
- 不隐瞒 Bug;
- 不为了短期利益牺牲长期质量;
- 在技术、成本、进度之间做出负责任的工程决策。
常见问题
- 什么是软件? 计算机程序和相关文档。软件产品可针对特定客户开发,也可为通用市场开发。
- 什么是优良软件的特点? 好的软件应具有用户所需的功能与性能,而且应该可维护、可依赖、可用。
- 什么是软件工程? 软件工程是关于软件生产各个方面的工程学科。
- 基本的软件工程活动有哪些? 软件规格说明、软件开发、软件确认、软件演化。
- 软件工程和计算机科学有什么区别? 计算机科学侧重理论和基础,软件工程侧重软件开发和交付的实际活动。
- 软件工程和系统工程有什么区别? 系统工程侧重基于计算机系统开发的所有方面,包括硬件、软件和过程工程;软件工程只是这个更泛化过程的一部分。
- 软件工程面临的主要挑战是什么? 不断增长的多样性、减少交付时间以及开发可靠软件的要求。
- 软件工程的成本有哪些? 软件开发成本约占总成本的 60%,测试成本占 40%。对于定制软件,演化成本常常高于开发成本。
- 最好的软件工程技术和方法是什么? 不同技术适用于不同类型的系统,不能单纯评判一种方法比另一种更好。
- 互联网给软件工程带来了哪些不同? 互联网不仅带来了大规模、高度分布式、基于服务的系统的开发,还催生了新的经济模式,如移动 App 产业。