HIT Software Construction Review Notes(2-2 Process, Systems, and Tools of Software Construction)
第二章 软件构造的过程和工具
2.2软件构造的过程,系统和工具
1.软件构造的一般过程
软件构造的一般过程
(1)编程
Constructionlanguages
· 编程语言(例如C,C++,Java,Python)
· 建模语言(例如UML)
· 配置语言(例如XML)
基于语言?基于数学?基于图形?
①编程语言
编程工具
· 集成开发环境(IDE):为程序员提供软件开发的综合设施
· IDE通常由以下几个部分组成:
- 代码自动完成的源代码编辑器,代码重构工具
- 文件管理工具
- 库管理工具
- 类浏览工具,对象浏览工具,面向对象的类层次结构图
- 图形用户界面(GUI)生成器
- 编译器,解释器
- 自动化构建工具
- 版本控制系统
· IDE可以通过更多外部第三方工具进行拓展
②建模语言和工具
· 建模语言是可用于表达信息或知识或系统的任何人造语言,该结构由一组一致的规则定义,目标是可视化,推理,验证和传达系统设计
③配置语言
· 配置程序的参数和初始设计
- 应用程序应提供工具来创建,修改和验证其配置文件的语法
- 某些计算机程序只能在启动时读取其配置文件,其他人定期检查配置文件的变化
· 目的示例
- 部署环境设置
- 应用程序功能的变体
- 组件之间连接的变量
· 配置语言示例
- 键值文本(.int , .properties , .rc等)
- XML , YAML , JSON
分离稳定和不稳定的部分
(2)评审和静态代码分析
审查和静态分析/检查
· 代码审查是对源代码的系统审查(同行评议)
- 它旨在发现初始开发阶段忽视的错误,提高软件的整体质量
- 评审以各种形式完成,如结对编程,非正式演练和正式检查
正式的代码审查
- 正式的代码审查,例如aFagen检查(一种结构化的检查代码和文档缺陷的过程),涉及多个参与者和多个阶段的仔细与详细的检查。
- 正式的代码审查是传统的审查办法,其中软件开发者参加一系列会议并逐行审查代码,通常使用材料的印刷副本
- 正式的检查非常彻底,已经证明可以很有效的在被审查的代码中发现缺陷。
轻量级代码审查
- 轻量级代码审查通常比正式的代码审查要求更小的开销,但如果正确完成,它可以同样有效。
- 轻量级审查通常作为正常开发过程中的一部分进行:
- Over-the-shoulder——one developerlooks over the author's shoulder as the latter walks through the code
- Email pass-around——source codemanagement system emails code to reviewers automatically after check-in is made
- Pair programming——two authorsdevelop code together at the same workstation, as it is common in ExtremeProgramming
- Tool-assisted code review——authors and reviewers use software tools, informal ones such as pastebinsand IRC, or specialized tools designed for peer code review
静态代码分析
- 静态代码分析是在没有实际执行程序的情况下执行的计算机软件分析(对执行程序执行的分析成为动态分析)
- 该过程提供了对代码结构的理解,并有助于确保代码符合行业标准。
- 自动化工具可以帮助程序员和开发人员进行静态分析。
- 例如Java中的CheckStyle,FindBugs,PMD
(3)动态代码分析/profiling
- 动态代码分析是通过执行程序执行的软件分析。
- 目标程序必须执行足够的测试输入以产生有趣的行为。
- 使用诸如代码覆盖率之类的软件测试措施有助于确保已经观察到该程序的一组可能行为的足够部分。
- 性能分析(“程序性能分析”,“软件性能分析”)是一种动态程序分析的形式,用于度量程序的空间(内存)或时间复杂度,特定指令的使用情况,函数调用的频率和持续时间。
(4)调试和测试
什么是测试?
- 软件测试是一项调查,旨在为利益相关者提供有关被测产品或服务质量的信息。
- 测试技术包括执行程序或应用程序的过程,目的是查找软件错误(错误或其他缺陷),并验证软件产品是否适合使用。
- 软件测试涉及执行软件组件或系统组件来评估一个或多个感兴趣的属性。
什么是调试?
- 调试是识别错误的根本原因并对其进行纠正的过程。
- 它与测试形成对比,测试是最初检测错误的过程,调试是作为成功测试的结果而发生的。
- 在某些项目中,调试占用了总开发时间的50%。
- 对于很多程序员来说,调试是编程中最难的部分。
- 像测试一样,调试不是提高软件质量的方法,但它是诊断缺陷的一种方法。
- 软件质量必须从一开始就构建。 构建优质产品的最佳方式是仔细开发需求,设计良好并使用高质量的编码实践。
- 调试是最后的手段。
(5)重构
- 重构是改变软件系统的过程,它不会改变代码的外部行为,但会改进其内部结构
- 投入短期时间/工作成本以获得长期收益,并对系统的整体质量进行长期投资。
- 重构是:
- 重组(重新安排)代码...
- ...在一系列小的,保留语义的转换中(即代码继续工作)......
-...为了使代码更易于维护和修改
- 重构不仅仅是旧的重组
- 你需要保持代码正常工作
- 你需要一些保留语义的小步骤
- 你需要进行单元测试以证明代码正常工作
2.软件构造的狭义过程(build)
(1)构建系统
典型的BUILD场景
- 用传统编译语言编写的软件,如C,C++,Java和C#
- 用诸如Perl和Python之类的解释性语言编写的软件的打包和测试。
- 编译和打包基于Web的应用程序。
- 其中包括静态HTML页面,使用Java或C#编写的源代码,使用JSP(JavaServer Pages),ASP(Active Server Pages)或PHP(超文本预处理器)语法编写的混合文件以及多种类型的配置文件。
- 执行单元测试以验证软件的一小部分与代码的其余部分隔离
- 执行静态分析工具来识别程序源代码中的错误。这个构建系统的输出是一个错误报告文档,而不是一个可执行程序。
- 生成PDF或HTML文档。 这种类型的构建系统使用一系列不同格式的输入文件,但生成可读的文档作为输出。
编译语言
- 编译语言,如C,C ++,Java和C#。在这个模型中,源文件被编译成目标文件,然后链接到代码库或可执行程序中。
- 生成的文件被收集到可安装在目标机器上的发行包中。
- 版本控制工具
- 源树和对象树:一组特定开发人员使用的源文件和编译对象文件。
- 编译工具:输入文件并生成输出文件的工具(例如,将源代码文件转换为目标代码和可执行程序)。编译工具的常见示例包括C或Java编译器,但它们还包括文档和单元测试生成器。
- 构建机器:执行编译工具的计算设备。
- 发布打包和目标机器:打包软件,分发给最终用户,然后安装到目标机器的方法。
解释语言
- 解释的源代码不会被编译到目标代码中,所以不需要对象树。源文件本身被收集到一个发行包中,可以安装在目标机器上。
- 编译工具专注于转换源文件并将它们存储在发行包中。
- 编译成机器码不会在构建时执行,即使它可能在运行时发生。
基于Web的应用程序
- 基于Web应用程序的构建系统是编译代码,解释代码和配置或数据文件的混合。 如图所示,某些文件(如HTML文件)直接从源代码树复制到发行包,而其他(如Java源文件)则首先编译为目标代码。
- 包含代码的JavaScript文件将由用户的Web浏览器最终解释。 这些文件也直接复制到发行包。
- JSP,ASP或PHP页面,包含HTML和程序代码的混合。 这些文件由Web应用程序服务器而不是构建系统编译和执行。 这些文件也被复制到发布包中,准备安装到Web服务器上。
- 将Java源文件编译为目标代码并打包为Web应用程序的一部分。 构建系统在打包Java类文件之前执行此转换。 Java类在Web应用程序服务器上执行,甚至在Web浏览器内执行(使用Java小程序)。
单元测试,静态分析等
(2)构建系统的组件
- 版本控制工具
- 源树:程序的源代码被存储为多个磁盘文件。将这些文件安排到不同的地方称为源树。源代码树的结构通常反映了软件的体系结构。
- 对象树:一个单独的树层次结构,用于存储由构建过程构建的任何对象文件或可执行程序。
- 编译工具:将可读的源文件转换为机器可读的可执行程序文件的程序。
- 编译器:源文件——目标文件
- 链接器:多个相关的目标文件——可执行程序映像
- 基于UML的代码生成器:模型——源代码文件
- 文档生成器:脚本——文档
- 构建工具:一种在编译工具之上的级别上运行的程序。 它必须对源文件和目标文件之间的关系有足够的了解,以便它可以编排整个构建过程。 构建工具调用必要的编译工具来产生最终的构建输出。
- 构建机器:编译和构建工具执行的机器。
- 本地编译环境:该软件在与构建机器相同的目标机器上执行;
- 交叉编译环境:需要两台不同的机器,目标机器上具有不同的操作系统或CPU。
本地编译 vs 交叉编译
- 发布打包和目标机器:生成可以实际安装在用户机器上的东西。
- 从源和目标树中提取相关文件并将它们存储在发行包中。
- 发行包应该是单个磁盘文件,并且应该进行压缩以减少下载所需的时间。
- 任何不必要的调试信息都应该被删除,以免干扰软件安装。
- 包装的类型
- 存档文件:zip和解压缩
- 包管理工具:UNIX风格,如.rpm和.deb
- 定制的GUI安装工具:Windows风格
(3)The Build Process and Build Description
构建过程
- 构建过程:构建工具调用每个编译工具来完成工作,这是一个端到端的事件序列。
构建说明
- 构建工具需要以基于文本的格式编写的构建描述。
- 例如,使用Make时,将以规则的形式指定文件间依赖关系信息,这些规则存储在名为Makefile的文件中。
如何使用构建系统
- 开发人员(或私人)构建:开发人员检出了VCS的源代码并正在专用工作区中构建软件。 结果发布包将用于开发人员的私人开发
- 发布版本构建:为测试组提供一个完整的软件包供验证。当测试人员确信软件的质量足够高时,就可以为客户提供相同的软件包。用于发布版本的源代码树只编译一次,源代码树永远不会被修改。
- 理智构建:这与发布版本构建类似,只是该软件包不是针对客户的。 相反,构建过程确定当前的源代码是否没有错误并通过了一组基本的理智测试。 这种构建可以每天发生多次,并且趋向于完全自动化。
(4)Java中的编译工具
(5)Subtargets and Build Variants
构建方式
- 是否只有一种方法可以将每个源文件编译并链接到可执行程序中,并且只能生成一种类型的发布包?
- 但实际上,可以存在任意数量的变体,每个变体都使用稍微修改的构建过程并创建一个稍微不同的发布包。
三种不同的构建方式
- 构建子目标:只对构建树的一部分进行增量更改的开发人员更愿意仅重建他们正在处理的树的部分。
- 构建软件的不同版本:输出是自定义的,以改变软件的行为。这些变化可能包括支持自然语言或支持不同的产品功能组合,例如家庭版或专业版。
- 构建不同的目标架构:要在不同的目标机器上支持软件产品,必须为各种不同的CPU类型和操作系统编译相同的源文件集。 这包括x86,MIPS和PowerPC等CPU以及Linux,Windows和Mac OSX等操作系统。
构建子目标
- 任何大型软件都可以分成许多子组件,通常采用静态或动态库的形式。每个组件仅提供程序的全部功能的一部分,并且在某种程度上独立于其他组件开发。
- 为了避免耗费时间构建整个源代码树来创建最终的可执行程序,最好选择限制它们构建的子组件的数量,而不是始终重建整个源代码树。
构建软件的不同版本
- 构建不同的版本
- 语言和文化,本地化
- 硬件变化
- 价格选项
- 指定构建变体
- 修改代码
- 逐行变化
- Per-variant files
- Per-variant directories
- Per-variant build description files
构建不同的目标架构
- 只有在编译为本地代码的C/C++等语言编程时,这种类型的变体才有意义
- 它与使用与机器无关的虚拟机的Java和C#不相关
(6)构建工具
总结:
本课总结:
- 软件构建的一般过程:Design → Programming/refactoring→ Debugging → Testing → Build → Release
- 软件构建的狭义过程(Build):Validate →Compile → Link → Test → Package → Install→ Deploy
参考资料:HIT软件构造课程,MIT软件构造课程