Chapter 2: Process and Tools of Software Construction
软件构造的过程和工具
Objectives of this lecture课程目标
-软件开发的基本过程
-传统的软件开发过程模型
-敏捷开发
-To understand (SCM) 软件配置管理
-Git作为配置管理工具
Outline大纲
-软件开发生命周期(SDLC)
-传统的软件过程模型(瀑布、增量、Vmodel、原型、螺旋)
-敏捷开发和极限编程(XP)
-协作软件开发
-软件配置管理(SCM)
-Git作为一个配置管理工具
第1章搞清楚了:软件构造的结果形态、如何是“好”
第2章开始关心:软件开发(01…n)遵循什么过程
2.1 Software Lifecycle and Configuration Management
软件生命周期与配置管理
initial 最初的 discarded 被丢弃的
Example 1: Microsoft Windows (1985-2016)
“Is Software Alive?” 软件有生命吗
当然!任何软件都有它自己的生命。
-软件的“年龄”:软件生产和使用多久了?
-软件的“生命力”:在特定的时间,它在多大程度上受到市场和用户的欢迎?
期待:持久,随时充满活力Long-lasting and full of vitality at any time
然而,
-软件开发失败(从0到不了1)
-执行过程中充满错误
-软件老化/衰退(有效性降低)
-软件的死亡
2. Traditional Software process models
传统的软件过程模型
Two basic types:两种基本类型
– Linear 线性过程
– Iterative 迭代过程
Existing models已存模型:
– Waterfall (Linear, non-iterative) 瀑布过程(线性过程,非迭代)
– Incremental (non-iterative) 增量过程(非迭代)
– V-Model (for verification and validation) V字模型(用于检验和验证)
– Prototyping (iterative) 原型过程(迭代过程)
– Spiral (iterative) 螺旋模型(迭代过程)
Key quality considerations(关键质量因素) 选择合适的过程模型的依据:
– User involvement (adapt to changes) 用户参与程度有多大?适应变化的能力
– Development efficiency, management complexity 开发效率/管理复杂度
– Quality of software 开发出的软件的质量
Waterfall (Linear , sequential , non-iterative)
瀑布过程(线性过程,顺序,非迭代)
瀑布过程:
• 线性推进
• 阶段划分清楚
• 整体推进
• 无迭代
• 管理简单
• 无法适应需求增加/变化
通过概念、启动、分析、设计、构建、测试、实现和维护的阶段,进展被视为稳步向下流动(就像瀑布一样)。
易于使用,但事后更改的成本高得令人望而却步。
由温斯顿·w·罗伊斯于1970年定义。
Incremental (non-iterative) 增量过程(非迭代)
产品的设计、实现和测试是递增的(每次增加一点),直到产品完成为止。
它增量地应用瀑布模型。
-系统被分解成许多小型开发项目。
-建立部分系统以生成最终系统。
-首先处理最高优先次序的要求。
-一旦开发出增量部分,则冻结该部分的需求。
增量过程:
• 线性推进
• 增量式(多个瀑布的串行)
• 无迭代
• 比较容易适应需求的增加
delivery 交付 increment 增量
V-Model (for verification and validation) V字模型(用于检验和验证)
V-model表示一个开发过程,可以认为是瀑布模型的扩展。
-过程步骤在编码阶段后向上弯曲,而不是线性向下移动,形成典型的V型。
演示开发生命周期的每个阶段与其相关测试阶段之间的关系。
-水平轴和垂直轴分别表示时间或项目完整性(从左到右)和抽象级别(最上面的粗粒度抽象)
implementation 实现 integration 集成
Prototyping (iterative) 原型过程(迭代过程)
软件原型是创建软件应用程序原型的活动,即,正在开发的软件程序的不完整版本。
原型通常模拟最终产品的几个方面,而且可能与最终产品完全不同。
过程:
-确定基本要求:确定基本要求,包括所需的输入和输出信息。细节通常可以忽略。
-开发初始原型:开发的初始原型只包含用户界面。
-审查:客户,包括最终用户,审查原型,并就添加或更改提供反馈。
-对原型进行修改和增强:利用反馈对规格和原型进行改进。如果引入了更改,则可能需要重复3和4步。
迭代:开发出来之后由用户试用/评审,发现问题反馈给开发者,开发者修改原有的实现,继续交给用户评审。
循环往复这个过程,直到用户满意为止。时间代价高,但开发质量也高。
Spiral (iterative) 螺旋模型(迭代过程)
螺旋模型是软件项目的风险驱动过程模型生成器。
-基于给定项目的独特风险模式,螺旋模型指导团队采用一个或多个流程模型的元素,例如增量式、瀑布式或渐进原型。
非常复杂的过程:
• 多轮迭代基本遵循瀑布模式
• 每轮迭代有明确的目标,遵循“原型”过程,进行严格的风险分析,方可进入下一轮迭代。
Agile development
敏捷开发
Agile development敏捷开发:
通过快速迭代和小规模的持续改进,以快速适应变化。
Agile Manifesto 敏捷宣言 rapid delivery 快速交付
Agile = 增量+ 迭代 每次迭代处理一个增量
极限的用户参与
极限的小步骤迭代
极限的确认/验证
捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。
Waterfall vs. Agile
eXtreme Programming (XP,极限编程)
XP是一种近螺旋式的开发方法,它将复杂的开发过程分解为一个个相对比较简单的小周期;通过积极的交流、反馈以及其它一系列的方法,开发人员和客户可以非常清楚开发进度、变化、待解决的问题和潜在的困难等,并根据实际情况及时地调整开发过程。适用于小团队开发。
Pair Programming 结对编程
Task board and progress monitoring 任务板和进度监控
4*. Collaborative software development
协作软件开发
开放源码开发模型
Software Configuration Management (SCM)
软件配置管理:追踪和控制软件的变化
SCM practices include revision control and the establishment of baselines.
Life Cycle of a Configuration Item (SCI/CI) 软件配置项:软件中发生变化的基本
单元(例如:文件)
Configuration Items (SCI/CI) and Baselines 基线:软件持续变化过程中的“稳定时刻”(例如:对外发布的版本)
CMDB and Check-in/Check-out for Auditing CMDB和审核的签入/签出
CMDB:配置管理数据库:存储软件的各配置项随时间发生变化的信息+基线
Versioning 版本控制
版本:为软件的任一特定时刻(Moment)的形态指派一个唯一的编号,作为“身份标识”。
古老的版本控制方法:通过复制文件并修改文件名
为什么需要版本控制?
-回滚到上一个版本
-比较两个版本的差异
-备份软件版本历史
-获取备份
-合并
为什么需要版本控制在团队工作中
-在多个开发者之间共享和协作
-记录每个开发者的动作,便于“审计”
History of an SCI 多个版本之间,形成线性或分支结构
Version control terminology版本控制术语:
Repository仓库:即于SCM中的CMDB
Working copy工作拷贝:在开发者本地机器上的一份项目拷贝
File文件:一个独立的配置项
Version or revision版本:在某个特定时间点的所有文件的共同状态
Change or diff变化:即code churn,两个版本之间的差异
Head:程序员正在其上工作的版本
Features of a version control system版本控制系统的特性:
-Reliable:可靠:保留版本,只要我们需要;允许备份
-Multiple files:多个文件:跟踪项目的版本,而不是单个文件
-Meaningful versions有意义的版本:有哪些更改,为什么要进行更改?
-Revert:还原:还原旧版本,全部或部分
-Compare versions比较版本
-Review history回顾历史:对于整个项目或单个文件
-Not just for code不仅仅是代码:散文,图片,…
它应该允许多人一起工作:
Version Control System (VCS) 版本控制系统
本地VCS Local VCS
集中式VCS Centralized VCS
分布式VCS Distributed VCS6.2
本地版本控制系统:仓库存储于开发者本地机器无法共享和协作
集中式版本控制系统:仓库存储于独立的服务器,支持多开发者之间的协作
分布式版本控制系统:仓库存储于独立的服务器+每个开发者的本地机器
Object graph in Git Git中的对象图
我们使用Git所做的所有操作——克隆、添加、提交、推送、日志、合并……——都是在一个图数据结构上进行的操作,该结构存储了项目中所有版本的文件,以及描述这些更改的所有日志条目。
Git对象图存储在存储库的. Git目录中。
从另一台机器/服务器复制git项目意味着复制整个对象图。
git clone URL local_repository
对象图是什么样子的?对象图是一个有向无环图(DAG),它是Git项目的历史记录。
Object Graph:版本之间的演化关系图,一条边A->B表征了“在版本B的基础上作出变化,形成了版本A”
Commits: nodes in Object Graph 提交:对象图中的节点
每个commit指向一个父亲
多个commit指向同一个父亲:分支
一个commit指向两个父亲:合并
分支只是一个指向提交的名称。
HEAD指向当前提交。
-我们要记住我们在哪个部门工作。HEAD指向当前分支,该分支指向当前提交。
Git表示带有树节点的提交。
-对于任何合理大小的项目,大多数文件在任何给定的修订中都不会更改。存储文件的冗余副本会造成浪费,所以Git不会这样做。
相反,Git对象图只存储单个文件的每个版本,并允许多个提交共享该副本。
-每个提交也有日志数据-谁,何时,短日志消息,等等。
Managing changes in Git 管理Git中的更改
传统VCS存储版本之间的变化(行) Git存储发生变化的文件(而非代码行),
不变化的文件不重复存储
文件未发生变化,则后续多个版本始终指向同一个文件
文件发生变化了,存储两份不同的文件,两个版本指向不同的文件
Add to the object graph with git commit
Send & receive object graphs with git push & git pull
Git supports Branch and Merge 分支/合并
Git supports collaboration Git支持协作
本地存储库和远程存储库
GitHub工作过程
基本流程:提交、分支和合并 commit, branch and merge
协作过程:fork和pull请求
Issue Tracking and Pull Request
2.2 Process, Systems, and Tools of Software Construction
软件构造的过程、系统和工具
2.1节:软件开发(01…n)遵循什么过程
本节:软件构造遵循什么“子过程”
(1) Programming 编码
Construction languages 语言
从用途上划分
– Programming languages (e.g., C, C++, Java, Python) 编程语言
– Modeling languages (e.g., UML) 建模语言
– Configuration languages (e.g., XML) 配置语言
– Build languages (e.g., XML) 构建语言
从形态上划分
– Linguistic-based 基于语言学的构造语言
– Mathematics-based (formal) 基于数学的形式化构造语言
– Graphics-based (visual) 基于图形的可视化构造语言
<1> Programming Languages 编程语言
Programming tools
Integrated development environment (IDE)集成开发环境:
为程序员提供全面的软件开发工具。
An IDE normally consists of:
– Source code editor with intelligent code completion, code refactoring tool源代码编辑器、智能代码补全工具、代码重构工具
– File management tool 文件管理
– Library management tool 库管理
– Class browser, object browser, class hierarchy diagram 软件逻辑实体可视化
– Graphical User Interface (GUI) builder 图形化用户界面构造器
– Compiler, interpreter 编译器、解释器
– Build automation tools 自动化build工具
– Version control system 版本控制系统
– Extensible by more external third-party tools 外部的第三方工具
Eclipse as an IDE example
pane 窗口
Core components of Eclipse IDE Eclipse IDE的核心组件
Eclipse architecture Eclipse体系结构
<2> Modeling languages 建模语言
建模语言是任何一种人工语言,它可以用来表达信息、知识或系统,其结构由一组一致的规则定义,目标是可视化、推理、验证和交流系统的设计。
UML as a modeling language and tool example
Unified Modeling Language UML 统一建模语言
UML是一种开放的方法,用于说明、可视化、构建和编写一个正在开发的、面向对象的、软件密集系统的制品的开放方法。UML展现了一系列最佳工程实践,这些最佳实践在对大规模,复杂系统进行建模方面,特别是在软件架构层次已经被验证有效。
UML用例图Use Case Diagram
UML类图
UML序列图
UML组件图 Component Diagram
<3>Configuration languages 配置语言
配置文件为程序配置参数和初始设置。
-应用程序应提供工具,以创建、修改和验证其配置文件的语法;
-一些计算机程序只在启动时读取配置文件。其他定期检查配置文件的更改。
目的的例子:
-部署环境设置
-应用程序功能的变体
-组件之间连接的变体
配置语言例子:
-键值文本(ini, .properties, .rc等)
改变软件在运行时的行为
分离稳定和不稳定的部分
(2) Review and static code analysis 代码评审和静态代码分析
Review代码评审
是对源代码的系统检查(peer review)。
-旨在发现开发初期被忽视的错误,提高整体质量。
-评审以各种形式进行,如结对编程;走查;正式评审会议;自动化评审
pair programming, informal walkthroughs, and formal inspections.
Formal code review正式的代码评审,例如Fagan检查,涉及到一个包含多个参与者和多个阶段的仔细而详细的过程。
正式的代码评审是传统的评审方法,软件开发人员参加评审
Lightweight code review 轻量级的代码评审
轻量级代码检查通常比正式的代码检查需要更少的开销,但是如果处理得当,它也可以同样有效。
轻量级评审通常作为正常开发过程的一部分进行:
Purpose of Code Review
代码评审实际上有两个目的:
-改进代码。发现bug,预测可能的bug,检查代码的清晰性,并检查与项目风格标准的一致性。
-改进程序员。代码评审是程序员相互学习和传授新语言特性、项目设计或编码标准的更改以及新技术的重要方式。特别是在开源项目中,很多对话都是在代码评审上下文中进行的。
代码评审在Apache和Mozilla等开源项目中得到了广泛的实践。
代码评审在工业中也得到了广泛的应用。
-在谷歌,你不能把任何代码推入主存储库,直到另一个工程师在代码审查中签署了它。
(3) Dynamic code analysis / profiling 动态代码分析/性能分析
动态分析:要执行程序并观察现象、收集数据、分析不足
目标程序必须使用足够的测试输入来执行,以产生有趣的行为。
使用软件测试度量,例如代码覆盖率,可以帮助确保已经观察到程序的一组可能行为的适当部分。
性能分析(“程序分析”,“软件分析”)是动态程序分析的一种形式,它度量程序的空间(内存)或时间复杂度、特定指令的使用情况,或函数调用的频率和持续时间。
对代码的运行时状态和性能进行度量,发现代码中的潜在问题
(4) Debugging and Testing
What is testing? 测试:发现程序是否有错误
What is Debugging? 调试:定位错误、发现错误根源
软件测试是向涉众提供有关被测试产品或服务质量的信息的调查。
测试技术包括执行程序或应用程序的过程,目的是发现软件bug(错误或其他缺陷),并验证软件产品适合使用。
软件测试涉及软件组件或系统组件的执行,以评估一个或多个感兴趣的属性
调试是确定错误的根本原因并加以纠正的过程。
它与测试相反,测试是最初检测错误的过程,调试是测试成功的结果。
-在一些项目中,调试占用了全部开发时间的50%。
-对许多程序员来说,调试是编程中最困难的部分。
与测试一样,调试不是提高软件质量的方法,而是诊断缺陷的方法。
-软件质量必须从一开始就内置。构建高质量产品的最佳方法是仔细地开发需求,进行良好的设计,并使用高质量的编码实践。
调试是最后的手段。
(5) Refactoring 重构
Refactoring 重构:在不改变功能的前提下优化代码
版本控制工具Version-control tool
源树和对象树Source trees and object trees:特定开发人员使用的一组源文件和已编译的目标文件
编译工具Compilation tools:接受输入文件并生成输出文件的工具(例如,将源代码文件转换为目标代码和可执行程序)。编译工具的常见示例包括C或Java编译器,但也包括文档和单元测试生成器。
编译机Build machines:执行编译工具的计算设备。
发布打包和目标机器Release packaging and target machines:将软件打包,分发给最终用户,然后安装到目标机器上的方法。
Interpreted Languages 解释语言
解释的源代码不会编译成目标代码,因此不需要对象树。源文件本身被收集到一个发布包中,准备安装到目标机器上。
编译工具专注于转换源文件并将它们存储在发布包中。
编译成机器码不会在构建时执行,即使它可能在运行时执行。
Web-Based Applications 基于web的应用程序
基于web的应用程序的构建系统是编译代码、解释代码和配置或数据文件的组合。
有些文件(如HTML文件)直接从源树复制到发布包,而其他文件(如Java源文件)则首先编译成目标代码。
静态HTML文件,只包含要在web浏览器中显示的标记数据。这些文件被直接复制到发布包中。
包含由最终用户的web浏览器解释的代码的JavaScript文件。这些文件也被直接复制到发布包中。
JSP、ASP或PHP页面,包含HTML和程序代码的混合。这些文件由web应用程序服务器编译和执行,而不是由构建系统编译和执行。这些文件也被复制到发布包中,准备安装在web服务器上。
要编译成目标代码并打包为web应用程序的一部分的Java源文件。构建系统在打包Java类文件之前执行此转换。Java类在web应用程序服务器上执行,甚至在web浏览器中执行(使用Java applet)。
Unit Testing, Static Analysis, etc 单元测试、静态分析等
(2) Components of a Build System
版本控制工具Version-Control Tools
源代码树Source Tree::程序的源代码存储为许多磁盘文件。这种将文件排列成不同文件的方法称为源树。源代码树的结构通常反映软件的体系结构。
对象树Object Trees:一个单独的树层次结构,它存储由构建过程构造的任何对象文件或可执行程序。
编译工具Compilation Tools:将人类可读的源文件翻译成机器可读的可执行程序文件的程序。
-编译器Compiler:源文件,目标文件
-链接器Linker::多个相关目标文件的可执行程序图像
-基于uml的代码生成器UML-based code generator:模型源代码文件
-文档生成器Documentation generator:脚本文档
构建工具Build Tools:在编译工具之上运行的程序。它必须对源文件和目标文件之间的关系有足够的了解,以便能够编排整个构建过程。构建工具调用必要的编译工具来生成最终的构建输出。
编译机Build Machines:编译和编译工具在其上执行的机器。
-本机编译环境:软件在与构建机相同的目标机上执行;
-交叉编译环境:需要两台不同的机器,目标机器上有不同的操作系统或CPU。
本地编译与交叉编译
平常做的编译叫本地编译,也就是在当前平台编译,编译得到的程序也是在本地执行。
交叉编译简单地说,就是在一个平台上生成另一个平台上的可执行代码。同一个体系结构可以运行不同的操作系统;同样,同一个操作系统也可以在不同的体系结构上运行。举例来说,我们常说的x86 Linux平台实际上是Intel x86体系结构和Linux for x86操作系统的统称;而x86 WinNT平台实际上是Intel x86体系结构和Windows NT for x86操作系统的简称。
发布打包和目标机器:生成可以实际安装到用户机器上的东西。
-从源树和对象树中提取相关文件,并将其存储在发布包中。
-发行包应该是一个单一的磁盘文件,并应进行压缩,以减少下载所需的时间。
-应该删除任何非必要的调试信息,这样就不会打乱软件的安装。
包装类型:
-存档文件:压缩和解压缩
-包管理工具:unix风格的,如.rpm和.deb
-定制GUI安装工具:windows风格
(3) The Build Process and Build Description
构建过程和构建描述
Build Process构建过程:
构建工具调用每个编译工具来完成任务,这是一个端到端事件序列。
Build language (build description) 构建语言(构建描述)
构建工具需要以基于文本的格式编写构建描述。
-它遵循特定构建语言的语法规则。
例如,在使用Make时,以规则的形式指定文件间依赖信息,这些规则存储在名为Makefile的文件中。
您可以手动编写描述,也可以通过IDE生成描述
如何使用构建系统
开发人员(或私有)构建Developer (or private) build:开发人员已从VCS检出源代码,并正在私有工作区中构建软件。
发布构建Release build:提供一个完整的软件包供测试组验证。当测试人员确信软件具有足够高的质量时,同样的包就会提供给客户。
健全构建Sanity build:构建过程确定当前源代码是否没有错误,并通过一组基本的健全测试。这种类型的构建可能每天发生很多次,并且趋向于完全自动化。
-每日构建/每夜构建每日构建
-持续集成(CI)持续集成
Continuous Integration (CI) 持续集成
持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。
Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。
(4) Compilation Tools in Java Java编译工具
Java语言的一大卖点是它的“一次编写,随处运行”哲学。
也就是说,应该可以在Linux机器上编译Java程序,而无需任何修改就可以在Windows或Solaris机器
上运行它。
这是通过使用由Java虚拟机(JVM)解释的一组标准字节码来实现的。
由于Java的安全特性,可以限制Java程序执行的环境,因此允许执行不受信任的程序,而不用担心会
损害主机。
Java编译工具 Compilation Tools in Java
Java开发工具包(JDK) The Java Development Kit
GNU Java编译器
Eclipse Java编译器(ECJ)
Java中的目标文件 Object files in Java
Java类的目标文件格式称为类文件,其后缀为.class。
与机器无关的字节码,用来描述程序的流程,而不是直接编译成本机机器码。
需要一个Java虚拟机(JVM)来加载和解释这些字节码,尽管JVM可能在实际执行程序之前首先将它们转换为本机代码。
使用javac命令将Java源文件转换为类文件。
Java可执行程序
Java编程是动态类加载。生成可执行程序不需要构建时链接步骤。相反,当运行中的程序需要Java类时,它们会被单独加载到内存中。没有单一的可执行程序映像要加载。
Java程序只是一个动态库的集合,尽管单个类一次加载一个,而不是作为更大的共享库的一部分加载。
Java程序需要执行两件事:
-必须为JVM提供包含主方法的类的名称。这将用作执行的起点。
JVM还必须提供一个类路径,用于标识附加类的位置。
Libraries in Java
(5) Subtargets and Build Variants 子目标和构建变体
2.1
A D D git remote add;git commit AB AC C
2.2
B A A D ABCD A