# 软件开发
- 20 世纪,计算机软件变得越来越复杂,因此人们总结了关于软件的各种技术、方法论,形成一门新的学科,软件工程(Software Engineering,SE)。
- 研究软件工程的主要目的是:优化软件的开发过程,使得开发速度快、成本低、软件质量好。
- 个人开发软件时,可能比较随意,不考虑软件工程。
- 企业开发软件时,需要考虑多人协作、工程排期等问题,有必要考虑软件工程。
- 在企业中,参与软件工程的工作人员,通常称为软件工程师(Software Engineer),俗称为程序员(Programmer)。
- 软件工程涉及到多种学科:
- 管理学:人们将土木工程、车辆工程等传统的管理学经验,沿用到了软件工程。
- 计算机科学(Computer Science,CS):泛指对计算机的科学研究,比如计算机组成、计算机网络、操作系统、编程语言、数据结构、算法、人工智能。
- 互联网技术(Internet Technology,IT):泛指基于计算机互联网的技术,比如 Web 网站。
# 软件开发流程
假设一个企业,想售卖软件来营利,则总体流程如下:
- 分析需求
- 设计软件
- 开发软件
- 售卖软件
- 售后(包括运维、技术支持)
企业开发软件时,标准流程如下:
- 开发(develop)
- 该环节,主要是修改软件的源代码。
- 构建(build)
- 很多软件是用 C、Java 等编译型语言开发的,源代码不能直接被人类使用,需要编译成二进制文件,才能被人类使用。
- 很多软件比较复杂,除了编译,还需要进行一些加工操作,这些操作统称为构建。
- 测试(test)
- 每次修改软件之后,可能引入 bug 等问题,因此需要经过测试,检查没有问题之后,才能交给用户使用。
- 发版(release)
- 如果测试环节发现了软件的问题,就需要修改软件,重新开始流程:
开发 -> 构建 -> 测试
- 软件测试环节没发现问题,则需要将软件的当前状态记录下来,作为一个版本。
- 例如记录:v1 版本的软件,源代码是什么内容,配置文件是什么内容。
- 早期的软件工程师,需要手动记录每个版本的内容,很麻烦。后来发明了 Git 等版本管理工具,可以自动记录版本。
- 开发一个软件时,可能先后发布多个版本,每个版本都应该记录下来。
- 这样能看出软件的修改历史,每个版本改了哪些内容。
- 客户默认会使用软件的最新版本,但有的客户希望使用旧版本,比如客户没时间升级新版本、不习惯新版本。
- 如果测试环节发现了软件的问题,就需要修改软件,重新开始流程:
- 部署(deploy)
- 该环节,是将软件拷贝到一个计算机中,正式运行。
- 在测试环节,为了节省成本,通常将软件放在一个性能较差的计算机中运行。等到正式部署时,才将软件放到正式的计算机中。
- 交付(delivery)
- 该环节,是通知客户,将软件交给客户使用。
- 开发(develop)
# 加快流程
开发一个软件时,可能先后发布多个版本,因此需要多次执行
分析需求 -> 设计软件 -> 开发软件
的流程。- 但每次修改软件,都重新走一遍整个流程,耗时较久。
- 为了加快流程,人们提出了以下几种方法。
瀑布开发(waterfall development)
- :遵守标准的软件开发流程,一步一步执行。完成一个环节之后,再专心执行下一环节。
- 优点:
- 对于管理者比较简单,同时只需要专心考虑一个环节。
- 缺点:
- 开发软件的速度慢。比如开发环节结束之后,工程师们才开会讨论测试方案。
- 交付周期长。每次客户的需求变化时,需要重新走一遍整个流程,增加时间成本、人力成本。
- 瀑布开发是一种传统的软件开发模式,被 20 世纪的企业广泛采用,但缺点明显。
迭代开发(iterative development)
- :每几周发布一个新版本(称为一次迭代),每次只开发软件 n% 的功能,并且让客户试用这部分功能,接收客户的反馈。等软件 100% 的功能开发完毕之后,才正式交付。
- 优点:
- 一边开发软件,一边根据客户的反馈来修正软件,这样能保证软件一直让客户差不多满意。
- 否则,如果软件让客户很不满意,客户会要求对软件作出大幅修改,增加很多时间成本、人力成本。甚至,客户可能放弃购买该软件。
- 一边开发软件,一边根据客户的反馈来修正软件,这样能保证软件一直让客户差不多满意。
敏捷开发(agile development)
- 2001 年,一些程序员开始宣扬敏捷开发的思想,提倡以下职业行为:
- 同事之间及时沟通、快速协作。
- 传统的工作模式是,同事之间通过企业行政流程进行协作,速度慢、效率低。
- 在开发软件的初期,就与客户沟通、让客户试用,从而及时了解客户的需求,避免开发软件的方向走偏。
- 与其给客户编写文档说明,不如直接展示可用的软件,即使只有部分功能可用。
- 每次收到客户的新需求时,能快速迭代出一个新版本。
- 同事之间及时沟通、快速协作。
- 缺点:
- 敏捷开发需要企业有高效的管理能力,但很多传统企业只有能力实施瀑布开发。
- 后来,敏捷开发衍生出几种方案:
- Scrum
- 要求同事们每天早上开一个几分钟的站会,交流昨天的工作进度、今天的工作安排。
- 要求每两周完成一次迭代。
- 极限编程
- 它认为,如果一项措施的效果是好的,则将它做到极致。
- 它提倡自动化测试、代码评审、快速迭代等措施。
- Scrum
- 2001 年,一些程序员开始宣扬敏捷开发的思想,提倡以下职业行为:
测试驱动的开发
- :先按照需求,编写测试用例,然后开发能通过这些测试用例的代码。
- 例如客户希望软件提供某一功能,则编写测试用例,检查软件能否实现该功能。然后开发代码,直到通过测试用例。
- 优点:
- 开发代码时,目标更明确,只要通过测试用例即可。
- 缺点:
- 客户的一个需求,可能需要用大量测试用例来描述,而且不一定能准确描述。
# 相关经验
分析需求时
- 需要确定这个软件,希望实现什么功能、达到什么效果。
- 评价一个软件好不好,需要衡量多个因素,做出取舍:
- 成本
- 功能(是否满足用户的需求)
- 性能
- 安全性(例如银行的软件系统最看重安全性)
- 难点:程序员按照自己的想法开发软件,但不满足客户的需求,就赚不到钱
- 难点:客户的需求不清晰
- 客户通常不确定自己想要什么效果,只有个粗略想法。
- 客户通常不了解计算机软件的原理,可能提出一些很难实现的需求,或者需要很大成本才能实现。
- 难点:客户的需求会变化,导致软件开发成本增加
- 例如客户突发奇想提了一个需求,过了一段时间却不想要这个需求了。
- 例如客户方存在多人,提出不同的需求。
设计软件时
- 实现常见的功能时,应该先到网上找找,有没有现成的方案。也许别人已经提出了良好的方案,可以供你借鉴,或者被你复用,避免重复造轮子。
编写代码时
- 应该先规划,再行动。继续规划,继续行动。
- 先想象出代码是什么样子,再把它编写出来,这样效率高。而不是先写一行代码,再构思下一行代码怎么写。
- 为了避免努力的方向错误,埋头苦干几个小时之后,就暂停一下,检查工作效果。
- 为了方便以后新增需求,编写的代码,应该具有良好的可扩展性。
- 为了多年之后,这段代码还能被人看懂,应该将代码写得尽量容易理解,并加上注释。
- 不要随便重构代码,这要花费很大代价,甚至代价可能超过重新开发整个软件。
- 编写软件时,首先实现功能,然后才考虑性能。
- 甚至,可以不考虑性能,只留下可扩展的代码,以后有需要时再花时间优化性能。
- 在一个软件的开发初期,需求可能变化,代码架构可能大改,此时优化性能,可能做无用功。
- 为了编写健壮的软件,
- 将一个复合功能,分解成多个基础功能,便于单独修改、单元测试。
- 一个软件被第三方调用时,应该不信任外部的输入值,总是加一段代码来检查输入值是否合理。毕竟第三方可能恶意攻击。
- 一个软件调用第三方时,应该不信任第三方的输出值,总是加一段代码来检查输出值是否合理。
- 严谨的情况下,假设每个环节都可能出现异常,然后编写一些代码来处理这些异常。例如调用一个函数的耗时太久怎么办?
- 应该先规划,再行动。继续规划,继续行动。
测试时
- 建议给软件编写很多自动化测试脚本。这样每次修改软件,都可以立即测试,检查软件能否正常工作,更放心。
# 软件版本
每次给软件发布一个版本时,版本名称应该采用什么格式?
- 简单的软件,可以采用当前日期,作为版本名称。例如
20220101
- 优点:容易看出这个版本是什么时候发布的。
- 复杂的软件,建议采用语义化版本,让人大致看出这个版本的改动幅度有多大。格式如下:
主版本号.子版本号[.修订版本号[.编译版本号]]
- 如果新版本,不再兼容某些旧 API ,则将主版本号递增。(递增的同时,将右侧的各个版本号复位为 0 )
- 如果新版本,新增了功能、特性,但依然兼容所有旧 API ,则主版本号不变,子版本号递增。
- 如果新版本,没有新增功能、特性,只是修改了一些代码(通常是为了修复一些 bug ),则将修订版本号递增。
- 如果同一版本的代码,进行了多次编译(比如针对 Linux、Window 平台分别编译一次),则使用不同的编译版本号。
- 简单的软件,可以采用当前日期,作为版本名称。例如
在软件的开发流程中,可以使用几种版本代号:
α, alpha # 表示该版本只是一个初步完成品,通常有很多 bug 。因此该版本只用于内部测试,不建议客户使用 β, beta # 消除了严重错误,可以提供给部分用户试用,即公开测试 RC, Release Candidate # 候选发布版,公开测试一段时间,如果没有发现问题,就晋升为 release 版本 release # 正式发布的版本
企业在售卖软件时,可以提供多种版本,售价不同:
standard # 标准版,提供了软件的基本功能,满足普通用户的需求 professional # 专业版,在标准版的基础上增加了一些高级功能,满足专业用户的需求 enterprise # 企业版,提供该软件的所有功能。可能按该企业的用户数量收费