第5章:软件工程
在20世纪60年代以前,软件规模小,开发就像个人手工作坊,一个人写代码、自己用,没什么文档。但到了60年代中期,计算机性能大幅提升,软件规模急剧膨胀,复杂度越来越高,问题也随之而来:开发进度难以预测、成本失控、功能不能满足用户需求、质量低劣、难以维护、缺少文档……这就是著名的“软件危机”。为了解决软件危机,人们提出了“软件工程”的概念,希望用工程化的方法来开发软件。
5.1 软件工程定义
软件工程就是用工程化的原则和方法来开发软件,目的是提高软件的生产率、质量和降低成本。IEEE对软件工程的定义是:将系统的、规范的、可度量的工程化方法应用于软件开发、运行和维护的全过程及方法的研究。
软件工程由三部分组成:
- 方法:完成软件项目的技术手段,支持整个软件生命周期。
- 工具:自动或半自动支持软件开发和管理,比如各种IDE、项目管理工具。
- 过程:贯穿软件开发各个环节的一系列活动,管理人员通过过程来控制质量、进度和成本。
形象地说:软件工程就像建造一座大楼,方法就是建筑技术,工具就是起重机、搅拌机,过程就是施工流程和管理。
5.2 软件需求
软件需求就是用户对系统在功能、行为、性能等方面的期望。IEEE定义:需求是用户解决问题或达到目标所需的条件或能力,也是系统必须满足的合同、标准、规范的要求。
5.2.1 需求的层次
需求分为三个层次,从宏观到微观:
- 业务需求:组织或客户的高层次目标,比如“我们要提高客户满意度”、“我们要实现无纸化办公”。通常来自投资人、高层管理人员,决定了项目的愿景和范围。
- 用户需求:用户的具体目标,用户能用系统做什么,比如“用户可以在线提交请假申请”。通过访谈、问卷等方式获取。
- 系统需求:从系统角度说明的需求,包括:
- 功能需求:系统必须实现的功能,比如“系统能计算员工工资”。
- 非功能需求:系统的属性或品质,如性能、安全性、易用性等。
- 约束:设计和实现上的限制,比如必须用Java开发、运行在Linux上。
形象地说:业务需求就像“我要建一栋别墅”,用户需求是“要有卧室、厨房、卫生间”,系统需求是“卧室要20平米,用环保材料,电路要暗埋”。
5.2.2 质量功能部署(QFD)
QFD是一种将用户要求转化为软件需求的技术,把需求分为三类:
- 常规需求:用户认为系统应该有的功能,做得越多用户越满意。比如手机要有打电话功能。
- 期望需求:用户想当然认为系统应该有的,如果没有就会不满意。比如手机应该能上网,用户可能不会明说,但如果没有就会觉得差劲。
- 意外需求(兴奋需求):用户没提但开发者加上的功能,有了会让用户惊喜,没有也不影响购买。比如手机的人脸识别解锁。
QFD帮助开发者在成本和满意度之间做权衡。
5.2.3 需求获取
需求获取就是与用户沟通,确定系统必须满足的需求。常用的方法有:用户访谈、问卷调查、采样、情节串联板、联合需求计划等。
难点在于用户往往说不清楚自己到底要什么,或者需求会变化。所以需求获取不是一次性的,需要反复沟通、确认。
5.2.4 需求分析
需求分析是把获取到的杂乱需求整理成清晰、一致、可验证的用户需求。一个好的需求应该具备:无二义性、完整性、一致性、可测试性、确定性、可跟踪性、正确性、必要性。
1. 结构化分析(SA)
结构化分析是一种面向数据流的需求分析方法,核心是数据字典,围绕它有三个模型:
- 数据模型:用**实体关系图(E-R图)**描述实体、属性和关系。
- 功能模型:用**数据流图(DFD)**描述数据流动和处理过程。
- 行为模型:用**状态转换图(STD)**描述系统状态和事件。
**数据流图(DFD)**由四种元素组成:
- 数据流(箭头):数据的流向。
- 处理(矩形):对数据的加工。
- 数据存储(开口矩形):数据存放的地方。
- 外部项(圆角框):数据源或终点。
DFD的建模步骤:确定系统范围 → 画顶层图 → 逐层分解 → 检查确认。
数据字典是对DFD中所有元素的详细说明,包括数据项、数据结构、数据流、数据存储、处理过程。它就像一本“数据百科全书”,供分析员和用户查询。
2. 面向对象分析(OOA)
OOA是从对象的角度分析问题域,识别类和对象,定义它们的属性和方法,以及之间的关系。OOA模型由五个层次(主题层、对象类层、结构层、属性层、服务层)和五个活动(标识对象类、标识结构、定义主题、定义属性、定义服务)组成。
OOA的基本原则:
- 抽象:抽取共同本质特征,忽略非本质细节。
- 封装:将属性和方法打包,隐藏内部细节。
- 继承:子类自动拥有父类的属性和方法。
- 分类:把相同属性和方法的对象归为一类。
- 聚合:整体与部分的关系。
- 关联:对象之间的联系。
- 消息通信:对象之间只能通过消息交互。
- 粒度控制:在宏观和微观之间切换视野。
- 行为分析:分析对象的动态行为。
OOA基本步骤:
- 确定对象和类。
- 确定结构(泛化-特化、整体-部分)。
- 确定主题。
- 确定属性。
- 确定方法。
5.2.5 需求规格说明书(SRS)
SRS是需求分析的最终成果,是项目干系人和开发团队对系统初始规定的共同理解,也是后续开发的基础。国家标准GB/T 8567提供了SRS模板,主要包括:
- 范围:系统标识、用途、背景、文档概述等。
- 引用文件:相关文档列表。
- 需求:详细描述功能、性能、接口、环境、质量等。
- 合格性规定:如何验证每个需求(演示、测试、分析等)。
- 需求可追踪性:双向追踪。
- 尚未解决的问题:遗留问题说明。
- 注解:术语、词汇。
- 附录:补充信息。
SRS需要经过验证(评审和测试),确保正确、完整、一致。
5.2.6 需求变更
需求变更是软件开发中的常态,但不能失控。变更控制过程包括:
- 问题分析和变更描述:分析变更提议的有效性。
- 变更分析和成本计算:评估影响和成本,决定是否执行。
- 变更实现:执行变更,并更新相关文档和代码。
**变更控制委员会(CCB)**由多方代表组成,负责裁决是否接受变更。CCB不是作业机构,只做决策。
变更策略:所有变更必须遵循过程;未批准的不做;CCB决定;变更内容要可跟踪。
5.2.7 需求跟踪
需求跟踪是建立需求与后续工作成果(设计、代码、测试等)之间的联系,确保所有需求都被实现,且所有成果都有需求依据。分为:
- 正向跟踪:从需求出发,找对应的设计、代码、测试。
- 逆向跟踪:从设计、代码、测试出发,找对应的需求。
常用工具是需求跟踪矩阵,记录需求与各阶段产出的对应关系。
5.3 软件设计
软件设计是把需求转化为软件蓝图的过程,解决“怎么做”的问题。分为结构化设计和面向对象设计。
5.3.1 结构化设计(SD)
SD是一种面向数据流的设计方法,以DFD和数据字典为基础,自顶向下、逐步求精。分为两个阶段:
- 概要设计:确定软件结构,划分模块,定义模块功能和接口,画出模块结构图(SC)。
- 详细设计:为每个模块设计具体算法、数据结构、界面等,用流程图、PAD图、伪码等工具。
模块化设计的关键概念:
- 信息隐藏:模块内部细节对外隐藏,只暴露接口。
- 模块化:模块具有功能、逻辑、状态三个属性。
- 耦合:模块之间联系的紧密程度。耦合度从低到高:非直接耦合、数据耦合、标记耦合、控制耦合、通信耦合、公共耦合、内容耦合。设计要追求低耦合。
- 内聚:模块内部各成分联系的紧密程度。内聚度从高到低:功能内聚、顺序内聚、通信内聚、过程内聚、时间内聚、逻辑内聚、偶然内聚。设计要追求高内聚。
系统结构图(SC):反映模块之间的层次结构和调用关系。
详细设计的工具:
- 图形工具:业务流程图、程序流程图、PAD图、NS图。
- 表格工具:决策表。
- 语言工具:伪码、PDL。
5.3.2 面向对象设计(OOD)
OOD是OOA的延续,主要任务是对类和对象进行设计,包括属性、方法以及类之间的关系。OOD的原则:
- 单一职责原则:一个类只有一个引起它变化的原因。
- 开闭原则:对扩展开放,对修改封闭。
- 里氏替换原则:子类可以替换父类。
- 依赖倒置原则:依赖抽象,不依赖具体实现。
- 接口隔离原则:使用多个专门接口,而不是一个总接口。
- 组合重用原则:尽量用组合代替继承。
- 迪米特原则:一个对象应尽可能少地了解其他对象。
在OOD中,类分为三种类型:
- 实体类:对应业务实体,需要持久化存储,如“学生”、“课程”。通常有属性,不一定有操作。
- 控制类:负责用例的控制行为,如“身份验证器”。通常有方法,不一定有属性。
- 边界类:位于系统与外界交互的边界,如窗口、接口、报表。可以有属性和方法。
5.3.3 统一建模语言(UML)
UML是一种用于软件系统建模的通用语言,支持从需求分析到设计实现的全过程。UML的结构包括:
- 构造块:事物(结构事物、行为事物、分组事物、注释事物)、关系(依赖、关联、泛化、实现)、图。
- 规则:命名、范围、可见性、完整性、执行等。
- 公共机制:规格说明、修饰、公共分类、扩展机制。
UML 2.0中的14种图:
- 类图、对象图、构件图、组合结构图、用例图、顺序图、通信图、定时图、状态图、活动图、部署图、制品图、包图、交互概览图。
UML的五种视图:
- 逻辑视图:系统的静态结构和动态行为。
- 进程视图:并发与同步。
- 实现视图:代码文件和构件。
- 部署视图:物理节点上的部署。
- 用例视图:从用户角度展示功能。
5.3.4 设计模式
设计模式是前人经验的总结,是可复用的解决方案。根据目的分为三类:
- 创建型模式:如何创建对象,如单例、工厂、建造者。
- 结构型模式:如何组合类或对象,如适配器、代理、装饰。
- 行为型模式:如何交互和分配职责,如观察者、策略、模板方法。
5.4 软件实现
5.4.1 软件配置管理(SCM)
SCM是标识、组织和控制修改的技术,目标是标识变更、控制变更、确保变更正确实现,并向相关人员报告。核心内容:
- 版本控制:记录文件变更历史,支持并行开发,分支与合并。
- 变更控制:管理变更过程,确保有序。
SCM活动包括:计划、标识、控制、状态记录、审计、发布管理。
5.4.2 软件编码
编码是把设计翻译成计算机能理解的程序。需要注意:
- 程序设计语言选择:根据项目需求选择合适语言。
- 程序设计风格:源程序文档化、数据说明规范、语句结构清晰、输入/输出友好。
- 程序复杂性度量:定量评估复杂度,用于估算工作量和缺陷。
- 编码效率:包括程序效率、算法效率、存储效率、I/O效率。
5.4.3 软件测试
测试是为了发现错误而执行程序的过程,目的是确保软件质量。
测试方法:
- 静态测试:不运行程序,通过检查文档和代码发现错误,如桌前检查、代码走查、代码审查。能发现30%~70%的逻辑错误。
- 动态测试:运行程序,比较实际结果与预期结果。包括:
- 白盒测试(结构测试):透明测试,关注内部逻辑,设计测试用例覆盖语句、分支、路径等。
- 黑盒测试(功能测试):不透明测试,关注功能是否满足需求,常用等价类划分、边界值分析、因果图等。
测试类型(GB/T 15532):
- 单元测试:测试单个模块。
- 集成测试:测试模块组合后的接口和交互。
- 确认测试:验证软件是否满足用户需求。
- 系统测试:在真实环境下测试整个系统,包括功能、性能、安全等。
- 配置项测试:测试软件配置项是否符合SRS。
- 回归测试:修改后测试,确保原有功能不受影响。
面向对象的测试:由于封装、继承、多态,测试策略不同,测试焦点从模块移到类,测试范围扩大到分析和设计模型。
软件调试:发现错误后定位并改正错误,常用蛮力法、回溯法、原因排除法。
5.5 部署交付
5.5.1 软件部署
软件部署是将软件安装到用户环境并使其运行的过程,包括打包、安装、配置、测试、集成、更新等。部署有风险,因为软件越来越复杂、环境不确定、构件来源多样。部署模式有:
- 面向单机软件的部署:简单安装卸载。
- 集中式服务器应用部署:适用于小规模用户。
- 基于微服务的分布式部署:适用于高并发、云原生应用,常结合容器和DevOps。
5.5.2 软件交付
传统软件交付流程:业务产生想法 → 开发实现 → 测试 → 运维。存在问题:沟通效率低、自动化测试不足、手工运维质量难保证。导致进度不可控、环境不稳定、协作不畅。
5.5.3 持续交付
持续交付是一系列开发实践,确保代码能快速、安全地部署到生产环境。它通过自动化流程,实现一键部署。优势:
- 缩短部署时间,降低风险。
- 快速反馈,及时发现缺陷。
- 软件始终处于可靠状态。
- 简化部署,版本清晰。
- 交付过程可靠、可预期、可视化。
5.5.4 持续部署
持续部署是持续交付的重要环节,常用容器技术(如Kubernetes+Docker)实现。部署原则:
- 部署包来自统一存储库。
- 所有环境使用相同部署方式和脚本。
- 部署流程阶梯式晋级,可回滚。
- 由运维人员执行,仅通过流水线改变生产环境。
- 不可变服务器:服务器一旦部署就不修改,需要更新就替换新版本。
- 部署方式:蓝绿部署(新旧版本并行,通过域名切换)和金丝雀部署(先让少量用户试用新版本)。
部署层次:Build(编译打包)→ Ship(安装依赖)→ Run(启动环境)。
5.5.5 部署和交付的新趋势
- 职责转变:开发人员参与交付和部署,运维人员自动化脚本。
- 云计算普及:环境可自动化创建和回收,部署更灵活。
- 研发运维融合:DevOps文化,打破壁垒。
5.6 软件质量管理
软件质量是软件与明确和隐含需求的一致程度。从用户角度,质量因素分为三组:
- 产品运行:正确性、健壮性、效率、完整性、可用性、风险。
- 产品修改:可理解性、可维修性、灵活性、可测试性。
- 产品转移:可移植性、可再用性、互运行性。
软件质量保证(SQA):通过有计划、系统的方法,向管理层保证标准和过程被遵循。目标是预防缺陷,尽早捕获错误,作用于过程,贯穿所有活动。
SQA的主要任务:
- 审计与评审:审查工作产品、工具、设备是否符合标准,确保过程被遵循。
- 报告:记录结果,发布给相关人员。
- 处理不合格问题:发现问题及时处理和反馈。
5.7 软件过程能力成熟度
软件过程能力是组织基于过程、技术、资源和人员达成业务目标的综合能力。中国电子工业标准化技术协会发布了CSMM(软件过程能力成熟度模型)。
5.7.1 成熟度模型
CSMM模型由4个能力域、20个能力子域、161个能力要求组成:
- 治理:战略与治理、目标管理。
- 开发与交付:需求、设计、开发、测试、部署、服务、开源应用。
- 管理与支持:项目策划、监控、结项、质量保证、风险管理、配置管理、供应商管理。
- 组织管理:过程管理、人员能力管理、组织资源管理、过程能力管理。
5.7.2 成熟度等级
CSMM定义了5个等级,从低到高:
- 1级:初始级
- 结果特征:软件过程和结果具有不确定性。
- 行为特征:能初步交付,但依赖个人能力,无完整管理规范。
- 2级:项目规范级
- 结果特征:项目基本可按计划实现预期结果。
- 行为特征:项目有选择地遵循管理规范,组织提供基础支持。
- 3级:组织改进级
- 结果特征:在组织范围内稳定实现预期项目目标。
- 行为特征:建立并持续改进组织标准过程和资产,项目根据自身特征应用并贡献资产。
- 4级:量化提升级
- 结果特征:量化管理和实现组织和项目目标。
- 行为特征:使用统计分析技术,建立量化的质量与过程绩效目标,分析数据、预测结果。
- 5级:创新引领级
- 结果特征:通过创新实现业务目标持续提升,引领行业发展。
- 行为特征:优化革新,创新提升竞争力,推广自身经验为行业最佳实践。
各能力域在不同等级有对应的要求,等级越高要求越全面。