第三章 软件构造过程与配置管理
3.1软件开发生命周期(SDLC)
从无到有、从有到好
3.2传统软件流程模型
两种基本类型
- 线性过程
- 迭代过程
现有模型
瀑布过程、增量过程、V字模型、原型过程、螺旋模型
选择合适的过程模型的依据
- 适应变化的能力
- 开发效率/管理复杂程度
- 开发出软件的质量
瀑布式:线性推动、阶段划分清楚、整体推进、无迭代、管理简单、无法适应需求(增量/变化)
增量过程:线性推进、增量式(多个瀑布的串行)、无迭代、比较容易适应需求的增加
V字模型:用于验证和确认、可以认为是瀑布模型的扩展(不是线性向下移动,过程步骤在编码阶段后向上弯曲,形成典型的V形)
原型过程:在原型上持续不断的迭代发现用户变化的需求
迭代:开发之后有用户试用/评审,发现问题反馈给开发者,开发者修改愿有的实现,继续交给用户评审
不断循环这个过程知道客户满意为止。时间代价很高,但开发质量也是很高
优势
- 软件设计者和实现者可以在项目的早期阶段从用户那里获得有价值的反馈。
- 客户端可以比较所制作的软件是否与构建软件程序的软件规范相匹配。
- 它还允许软件工程师对初步项目估计的准确性以及是否能够成功地满足最后期限和里程碑进行一些洞察。
螺旋模型(非常复杂的过程):多轮迭代基本遵循瀑布模式、每轮迭代有明确的目标,遵循“原型”过程,进行严格的风险分析,方可进入下一轮迭代
3.3敏捷开发和极限编程(XP)
敏捷开发:通过快速迭代和小规模的持续改进,以快速适应变化
敏捷=增量+迭代 每次迭代处理一个小规模增量
- 极限的用户参与
- 极限的小步骤迭代
- 极限的确认/验证
极限编程
12条规则必须同时遵守,不可放弃其一
- 计划的制定:确定本次迭代的范围
- 小版本:用最少代码的工作量带来最大的业务价值
- 简单设计:保证代码的简单
- 测试:极限编程的核心
- 持续集成
- 重构
- 结对编程
- 代码共享
- 每周只工作40小时
- 现场客户
- 隐喻
- 编码标准
3.4软件配置管理(SCM)和版本控制系统(VCS)
软件配置管理(SCM):追踪和控制软件的变化
配置项的生命周期(CI)
软件的任何组成成分(源代码、数据、文档、硬件、各种环境)都可能随着软件生命周期的时间而更新
软件配置项:软件中发生变化的基本单元(如:文件)
基线:软件持续变化过程中的“稳定时刻”(例如:对外发布的版本)
- 代表多个源代码文件的一组版本
- 代表文档的一个稳定状态
CMDB:配置管理数据库
存储软件的各配置项随时间发生变化的信息+基线
版本控制
版本:为软件人以特定时刻的形态指派一个唯一的编号,作为“身份标识”
古老的版本控制方法:通过复制文件并修改文件名
为什么需要对个人进行版本控制?
回滚到上一个版本
比较两个版本的差异
备份软件版本历史
获取备份
合并
在多个开发者之间共享和协作
记录每一个开发者的动作,便于“审计”
多个版本之间,形成线性或分支结构
仓库:即于SCM中的CMDB
工作拷贝:在开发者本地机器上的一份项目拷贝
文件:一个独立的配置项
版本:在某个特定时间点的所有文件的共同状态
变化:即code churn,两个版本之间的差异
HEAD:程序员正在其上工作的版本
版本控制系统(VCS)
本地版本控制系统:仓库存储于开发者本地机器无法协作共享和
集中式版本控制系统:仓库存储于独立的服务器,支持多开发者之间的协作 分布式版本控制系统:仓库存储于独立的服务器+每个开发者的本地机器
3.5 Git作为一个SCM工具
管理软件演化过程中的变化
一个Git存储库有三个部分
- 本地的CMDB
- 工作目的:本地文件系统
- 暂存区:隔离工作目录和Git仓库
只有暂存区是虚拟的,其余三个结构都是真实存在文件夹的,暂存区通过文件的标识来区分文件是否进入了暂存区。
每个文件都属于以下三种状态之一 - 已修改
- 已暂存
- 已提交
Commit 对象有两种产生方式 - 通过commit命令产生
- 通过合并分支产生
Commit对象的内容 - 文件数的根节点tree
- Author
- Committer
- 父节点的指针
与之前commit中未发生变化的文件,无需重复存储,只需一个链接即可
从另一台机器/服务器复制一个git项目意味着复制整个对象图
对象图是Git项目的历史,是一个有向无环图
Object Graph:版本之间的演化关系图,一条边A->B表征了“在版本B的基础上作出变化,形成了版本A”
历史图中的每个节点都是一个提交节点,版本啊a.k.a.项目修订版:在该时间点的所有文件的完整快照。
每个commit指向一个父亲
多个commit指向同一个父亲:分支
一个commit指向两个父亲:合并。有些人有双亲:他们是将不同历史联系在一起的版本
一个分支只是一个指向一个提交的名称。
头部指向当前的提交。
我们需要记住我们在做哪个分支。因此,头部指向当前的分支,它指向当前的提交。
对于任何合理大小的项目,大多数文件在任何给定版本中都不会更改。存储文件的冗余副本会造成浪费,所以Git不会这么做。
相反,Git对象图存储单个文件的每个版本一次,并允许多个提交共享该一个副本。
对象图中的节点
Git支持分支机构和合并机构
分支是处于修订控制下的对象的复制,以便可以沿两个分支并行进行修改
3.6软件建设的一般流程
从用途上划分
编程语言、建模语言、配置语言、构建语言
从形态上划分
基于语言学的构造语言
基于数学的形式化构造语言
基于图形的可视化构造语言
1. 编程语言
编程工具
集成开发环境(IDE):为程序员提供的进行软件开发的全面设施。
IDE通常包括:源代码编译器、智能代码补全工具、代码重构工具
文件管理
库管理
软件逻辑实体可视化
图形化用户界面构造器
编译器、解释器
自动化build工具
版本控制系统
外部的第三方工具
2. 建模语言
建模语言是任何人工语言,可以用来表达由一组一致的规则定义的结构中的信息、知识或系统,其目的是可视化、推理、验证和交流系统的设计。
UML统一建模语言
3. 配置语言
配置文件为程序配置参数和初始设置。
审核和静态代码分析
代码评审
代码评审是对源代码的系统检查(同行评审)。
结对编程、走查、正式会议评审、自动化评审
正式的代码评审会议
正式的代码审查,如Fagan检查,涉及到一个有多个参与者和多个阶段的仔细和详细的过程。
轻量级的代码评审
轻量级的代码检查通常比正式的代码检查需要更少的开销,尽管如果正确执行,它也可以同样有效。
轻量级审查通常作为正常开发过程的一部分进行:
- Over-the-shoulder
- 电子邮件传递
- 结对编程
- 工具辅助代码评审
利用工具进行的静态代码分析
静态代码分析是对在没有实际执行程序的情况下执行的计算机软件的分析(在执行程序时执行的分析称为动态分析)。
该过程提供了对代码结构的理解,并可以帮助确保代码符合行业标准。
自动化工具可以帮助程序员和开发人员执行静态分析。
代码审查的目的 - 改进代码
- 改进程序员
代码审查在Apache和Mozilla等开源项目中被广泛应用。
代码审查在工业中也被广泛应用。
代码审查一些具体的例子:错误和潜在的错误、不清楚,混乱的代码、对java的误解、滥用(或未使用)基本的设计概念。
动态代码分析/分析
动态分析:要执行程序 并观察现象、收集数据分析不足
对代码的运行时状态和性能进行度量,发现代码中的潜在问题
调试和测试
测试:发现程序是否有错误
调试:定位错误、发现错误根源。它与最初检测错误的过程不同,调试是测试成功的结果。
与测试一样,调试不是提高软件质量的方法,但它是诊断缺陷的方法。
调试是最后的手段。
重构
重构:在不改变功能的前提下优化代码
重构是改变软件系统的过程,即它不改变代码的外部行为,但又改进其内部结构
总结
通用软件开发生命周期(SDLC)
传统的软件过程模型:瀑布、增量、原型,迭代
敏捷开发
协作式软件开发
软件配置管理(SCM)
Git作为一个SCM工具
软件设计的一般流程:设计编程/重构调试测试构建版本
软件构建的狭隘过程(build):验证编译链接测试软件包安装部署