3 软件构造的过程及配置管理
3.1软件开发的生命周期
3.2传统的软件开发过程模型
两类基本类型:线性过程、迭代过程
开发过程模型:瀑布、增量、V字、原型、螺旋模型
选择合适的过程模型的依据:用户参与程度(适应变化的程度)、开发效率(复杂度)、软件质量
瀑布模型
特点:线性推进、阶段划分清楚、整体推进、无迭代、管理简单、无法适应需求、难以增加/变化
使用场景:需求稳定的项目
增量模型
特点:线性推进、增量式(多个瀑布的串行)、无迭代、比较容易适应需求的增加
V字模型
特点:在瀑布模型的基础上增加了测试和评价,展示了开发生命周期的每个阶段之间的关系及其相关的测试阶段
原型模型
在原型上持续不断地迭代发现用户变化的需求,时间代价高,但开发质量也高。
迭代:开发之后用用户使用/评审,发现问题反馈给开发者,开发者修改原有的实现,继续交给用户评审。循环直到用户满意。
螺旋模型
一种风险驱动的过程模型
将开发分为4个步骤,并一轮一轮进行迭代。
3.3敏捷开发
核心思想:通过快速迭代和小规模的持续改进,以快速适应变化。
强调:极限的用户参与、极限的小步骤迭代、极限的确认/验证
敏捷开发的方法:XP(极限编程)、Scrum
3.4软件配置项管理(SCM)和版本控制系统(VCS)
3.4.1软件配置管理(Software Configuration Management)
含义:追踪和控制软件的变化
核心:版本控制和基线的控制
软件配置项:软件中发生变化的基本单元
基线:软件持续变化过程中的“稳定版本”(如对外发布的版本)
CMDB:配置管理数据库,存储软件的各配置项随时间发生变化的信息和基线
3.4.2版本控制(Version Control System )
常见功能:
- 个人:回滚到上一个版本、比较版本之间的差异、备份软件版本历史、换取备份、合并
- 团队:多人协作、记录每个人的动作
版本控制术语:
- 仓库:SCM中的CMDB
- 工作拷贝:在开发者本地机器上的一份项目拷贝
- 文件:一个独立的配置项
- 版本:在蘑菇特定时间点的所有文件的共同状态
- 变化:两个版本之间的差异
- HEAD:当前工作版本
VCS的特征:
- 有意义的修改信息(变化以及原因)
- 可靠(保留旧版本)
- 可以回退到旧版本
- 可比较不同版本的差异
- 可查看修改历史
- 多人协作可合并
- 允许独立和共同工作
3.5以git为例讲解SCM工具
git 仓库
一个git仓库有3个部分:
- 本地的CMDB
- 工作目录:本地文件系统
- 暂存区:用来隔离工作目录和git仓库
文件在git仓库的3个状态:
- 已修改、以暂存、以提交
git中的对象图
git的所有操作都是在一个图数据结构上进行的,git对象图存储在存储库的.git目录中。从另一台机器/服务器复制git项目意味着复制整个对象图。
对象图是一个有向的无环图,一条边 A → B A\rightarrow B A→B表示“在版本B 的基础上做出变化,形成了版本A”;每个 → \rightarrow →指向一个父亲,如果有多个commit指向同一个父亲,则为产生分支,如果是一个commit指向多个父亲,则为merge
每次commit都会形成一个新的节点,这个节点包含所有文件的完整快照。
commit的信息:根节点、作者、提交者、备注信息等
git版本控制与传统VCS的不同:
- 传统VCS记录版本之间的变化信息,根据原信息来进行修改,速度较慢
- git直接保存每个版本独自的信息,每个版本都是完整信息,不变化的文件不进行再次存储。每次更新时,没有修改的文件直接将指针指向旧版本,而修改过的文件使用新的指针来指向即可,速度快。
常见git命令
git init//初始化git仓库
git add*.c
git add readme.md//将文件添加到暂存区,开始对这些文件进行跟踪
git commit//将暂存区文件提交到本地仓库
git push//将本地仓库的文件提交到远程仓库(服务器)
git status//查看当前文件状态
git diff//查看当前文件和暂存区快照之间的差异,即修改后未add的内容
git commit -a//跳过git add步骤,直接将所有修改过的文件暂存起来并提交
git rm//从git中移除某个文件,不再跟踪,也将原文件删除
git fetch//从远程仓库抓取文件到本地,但不与本地的合并
git pull//与fetch类似,但是还会与本地合并
git checkout//切换分支
git checkout -b phase1//创建分支phase1并切换到phase1分支
git merge//合并,需要在主分支(main)上进行操作
github
全球最大的开源平台,可以参与开源项目,参与前首先需要fork到自己仓库,然后再修改并pull request
3.6软件构建的一般过程
3.6.1 编程
软件构造语言可以依据分类标准不同而有不同的划分。
从用途上分:
- 编程语言(C/C++,java,python)
- 建模语言(UML)
- 配置语言(XML)
- 构建语言(XML)
从形态上分:
- 基于语言学的构造语言
- 基于数学的形式化构造语言
- 基于图形的可视化构造语言
3.6.2审查和代码评审
代码审查是源代码的系统检查。其常见方法有:结对编程、走查、正式评审会议、自动化评审等。
正式的代码评审会议:结构化的检査
轻量级的代码评审:相比正式评审开销小,效果可能与其相同
利用工具进行的静态代码分析:对未实际执行程序进行的分析(在执行程序时进行的分析称为动态分析)
代码评审的一些具体例子:bug,结构混乱,方法使用不当,错误使用基本设计概念
3.6.3动态代码分析/profile(评测)
动态程序分析是通过执行程序对软件进行的分析。
动态分析:要执行程序并贯彻现象、收集数据、分析不足
- 分析要求:程序要经过充分的测试、使用软件测试工具(确保代码的可能功能均被充分测试到)、使用评测发现代码中潜在的问题
评测(profile)是一种动态程序分析形式,用于测量程序的空间(内存)或时间复杂性、特定指令的使用情况,或函数调用的频率和持续时间。
3.6.4调试和测试
测试:发现程序是否有错误
调试:在测试发现问题之后,找到bug并修正,之后还要进行回归测试
调试和测试不会提升软件质量,而是发现和解决缺陷的主要手段;软件质量应该通过认真地分析需求、良好的设计、高质量的编码来实现
3.6.5重构
重构:在不改变功能的前提下优化代码,要可以兼容以前版本,既不改变软件的内部结构,也不改变软件的外部行为。
重构后还要进行单元测试保证代码正常工作
3.7狭义的软件构建过程(Build)
简单理解build:从build time到run time的过程。其实质是借助于公寓,将软件构造的各阶段活动(编译、打包、静态分析、测试、生成文档、部署等)”自动化“,从而提高构造效率
3.7.1典型的应用场景
- 用传统编译语言编写的软件的编译,如C、C++、Java和C#
- 用Perl和Python等解释语言编写的软件的打包和测试
- 基于web的应用程序的编译和打包
- 执行单元测试以验证软件的一小部分,与代码的其余部分隔离
- 执行静态分析工具来识别程序源代码中的错误。
- 生成PDF或HTML文档。这种类型的构建系统使用一系列不同格式的输入文件,但会生成人类可读的文档作为输出。
3.7.2编译系统的构成
- 版本控制工具
- 源代码树:程序的源代码存储为多个磁盘文件。将文件排列成不同的路径称为源树。源代码树的结构通常反映软件的体系结构。
- 对象树:一个单独的树层次结构,存储由构建过程构造的任何对象文件或可执行程序。
- 编译工具:将人类可读的源文件转换为机器可读的可执行程序文件的程序。
- 发布打包好的程序和目标机器:生成可以实际安装到用户机器上的软件。
- 包装类型:压缩和解压缩、包管理工具(rpm、.deb)GUI安装工具
3.7.3 build过程
构建过程:构建工具调用每个编译工具来完成任务,如编译、链接等。
3.7.4 构建语言(构建描述)
以基于文本的格式编写构建描述。如:
3.7.5如何使用构建系统
- 开发者:从VCS中获得源代码并进行开发
- 发行版:为测试组提供一个完整的软件包进行验证
- 健全构建:构建过程确定当前源代码是否没有错误,并通过一组基本的健全性测试。
3.7.6构建工具
对Java而言:Make,Ant,Maven,Gradle等
以maven为例:
- Apache Maven是一个软件项目管理和理解工具,主要目标是让开发人员在最短的时间内理解开发工作的完整状态。
- 只需在项目的pom.xml简单声明,Maven可自动将所需依赖项从远程服务器下载到本地并加入项目,省去了繁琐的手工配置过程。这些下载的JAR在本地由Maven统一管理,在各个本地项目之间共享。