软件构造一词指的是通过编码、验证、单元测试、集成测试和调试等组合详细创建工作软件的过程。
软件构建知识领域(KA)与所有其他KA都有关联,但它与软件设计和软件测试的关联最为紧密,因为软件构建过程涉及重要的软件设计和测试。
该过程使用设计输出并提供输入到测试(在这种情况下,“设计”和“测试”指的是活动,而不是KA)。设计、构建和测试之间的界限(如果有)将取决于项目中使用的软件生命周期过程。 虽然在构建之前可能会进行一些详细的设计工作,但很多设计工作是在构建活动期间完成的。因此,软件构建KA与软件设计KA密切相关。
在整个构建过程中,软件工程师既进行单元测试又进行集成测试。因此,软件构建KA与软件测试KA也密切相关。
软件构建通常会产生软件项目中需要管理的配置项数量最多(源文件、文档、测试用例等)。因此,软件构建KA也与软件配置管理KA密切相关。
尽管软件质量在所有KA中都很重要,但代码是软件项目的最终交付成果,因此软件质量KA与软件构建KA密切相关。
由于软件构建需要算法和编码实践的知识,它与计算基础KA密切相关,后者关注支持软件产品设计和构建的计算机科学基础。它还与项目管理相关,因为构建管理可能会带来相当大的挑战。
图3.1展示了软件构建知识领域(KA)的顶层分解的图形表示。
软件构建基础包括:
大多数人在长时间内都无法将复杂结构和信息保存在工作记忆中,这对于将意图传达给计算机是一个主要因素,这导致了软件构建中最强烈的驱动力之一:最小化复杂性。减少复杂性的需求适用于软件构建的方方面面,特别是对于软件构建的测试而言,这尤为关键。
在软件构建中,通过强调简单易读的代码创建而不是聪明的代码来实现减少复杂性。这是通过使用标准(见第1.5节,构建标准)、模块化设计(见第3.1节,构建设计)和许多其他具体技术(见第3.3节,编码)来实现的。它还受到构建重点质量技术的支持(见第3.7节,构建质量)。
大多数软件会随着时间的推移而发生变化,对变化的预见驱动着软件构建的许多方面;软件运行环境的变化也会以不同的方式影响软件。
预见变化有助于软件工程师构建可扩展的软件,这意味着他们可以增强软件产品而不破坏其基本结构。
预见变化得到许多具体技术的支持(见第3.3节,编码)。
构建以进行验证意味着以这样一种方式构建软件,即软件工程师在编写软件时以及测试人员和用户在独立测试和运行活动中都能轻松地发现缺陷。支持构建以进行验证的具体技术包括遵循编码标准以支持代码审查和单元测试,组织代码以支持自动化测试,并限制使用复杂或难以理解的语言结构,等等。
重用是指在解决不同问题时使用现有资产。在软件构建中,通常重用的资产包括库、模块、组件、源代码和商业现成(COTS)资产。重用最好是按照明确定义、可重复的过程系统地实践。系统化的重用可以实现显著的软件生产率、质量和成本改进。
重用有两个密切相关的方面:“构建以重用”和“构建带重用”。前者意味着创建可重用的软件资产,而后者意味着在构建新解决方案时重用软件资产。
重用经常超越项目的界限,这意味着可重用的资产可以在其他项目或组织中构建。
在构建过程中应用外部或内部开发标准有助于实现项目在效率、质量和成本方面的目标。具体来说,允许的编程语言子集和使用标准的选择是实现更高安全性的重要辅助。
直接影响构建问题的标准包括:
使用外部标准。构建依赖于对构建语言、构建工具、技术接口以及软件构建KA与其他KA之间的交互使用外部标准。标准来自多个来源,包括硬件和软件接口规范(如对象管理组(OMG))和国际组织(如IEEE或ISO)。
使用内部标准。标准也可以在组织层面或用于特定项目的基础上创建。这些标准支持协调组活动,最小化复杂性,预见变化和构建以进行验证。
创建软件的多种模型已经被开发出来;有些模型更加强调构建。
一些模型在构建方面更加线性——比如瀑布模型和分阶段交付生命周期模型。这些模型将构建视为仅在完成了重要的先决条件工作后才会发生的活动,包括详细的需求工作、广泛的设计工作和详细的规划。更线性的方法倾向于强调构建之前的活动(需求和设计),并在活动之间创建更明确的分隔。在这些模型中,构建的主要重点可能是编码。
其他模型更加迭代——比如进化原型和敏捷开发。这些方法倾向于将构建视为与其他软件开发活动(包括需求、设计和规划)同时进行或者重叠进行的活动。这些方法往往混合了设计、编码和测试活动,并经常将活动的组合视为构建(参见软件管理和软件过程KA)。
因此,所谓的“构建”在很大程度上取决于使用的生命周期模型。一般来说,软件构建主要是编码和调试,但也涉及构建规划、详细设计、单元测试、集成测试和其他活动。
构建方法的选择是构建规划活动的关键方面。构建方法的选择影响构建先决条件的执行程度、执行顺序以及在构建工作开始之前应完成的程度。
构建方法的选择影响项目团队降低复杂性、预见变化和构建以进行验证的能力。每个这些目标也可以在过程、需求和设计层面上得到解决——但它们会受到构建方法选择的影响。
构建规划还定义了组件创建和集成的顺序、集成策略(例如,分阶段或增量集成)、软件质量管理流程、特定软件工程师的任务分配以及根据选择的方法进行的其他任务。
可以测量许多构建活动和制品,包括开发的代码、修改的代码、重用的代码、销毁的代码、代码复杂性、代码检查统计、故障修复和故障查找率、工作量和进度安排。这些测量对于管理构建、在构建过程中确保质量以及改进构建过程等方面都是有用的(有关测量的更多信息,请参见软件工程过程KA)。
构建是软件工程师必须处理的一种活动,有时候涉及到混乱和变化多端的现实约束,他或她必须精确地处理这些情况。由于受到现实世界约束的影响,构建更多地受到实际考虑的驱动,而软件工程在构建活动中可能更像是手艺活。
一些项目将大量的设计活动分配给了构建阶段,而其他项目则将设计分配给专门的设计阶段。无论确切的分配如何,一些详细的设计工作将在构建级别进行,而这些设计工作往往是由正在解决的现实问题所强加的约束所决定的。
就像建造物理结构的建筑工人必须对建筑者计划中未预料到的间隙进行小规模修改一样,软件构建工作者必须在构建过程中对软件设计的细节进行较小或较大范围的修改。
在构建级别进行的设计活动的细节基本上与软件设计KA中描述的相同,但是它们应用于算法、数据结构和接口的较小规模。
构建语言包括人类用来指定问题的可执行解决方案的所有形式的通信。构建语言及其实现(例如编译器)可以影响性能、可靠性、可移植性等软件质量属性。它们可能严重影响安全漏洞。
最简单类型的构建语言是配置语言,其中软件工程师从一组有限的预定义选项中选择,以创建新的或定制的软件安装。Windows和Unix操作系统中使用的文本配置文件就是其中的例子,而某些程序生成器的菜单式选择列表则构成了配置语言的另一个例子。
工具包语言用于从工具包中的元素构建应用程序(集成的应用程序特定可重用部件集)。它们比配置语言复杂。工具包语言可能明确定义为应用程序编程语言,也可能应用程序仅由工具包的接口集合暗示。
脚本语言是常用的应用程序编程语言类型。在某些脚本语言中,脚本称为批处理文件或宏。
编程语言是最灵活的构建语言类型。它们对于特定应用领域和开发过程的信息最少,因此使用起来需要最多的培训和技能。编程语言的选择可能会对在编码过程中引入漏洞的可能性产生重大影响——例如,对于安全视角来说,C和C++的不加批判的使用是可疑的选择。
有三种通用的编程语言表示法,即
语言表示法特别以使用文本字符串来表示复杂的软件构建而著称。将文本字符串组合成模式可能具有类似句子的语法。正确使用时,每个这样的字符串应具有强烈的语义内涵,提供对软件构建执行时将发生的事情的直观理解。
形式表示法对词语和文本字符串的直观、日常意义依赖较少,而更多地依赖于通过精确、明确和形式(或数学)定义支持的定义。形式构建表示法和形式方法是大多数系统编程表示法的语义基础,其中准确性、时间行为和可测试性比映
射到自然语言中更重要。形式构建还使用了准确定义的符号组合方式,避免了许多自然语言构建的歧义。
可视表示法在很大程度上依赖于语言和形式构建的文本表示,并且更依赖于直接的视觉解释和代表底层软件的视觉实体的放置。可视构建往往受到仅通过在显示器上排列图标来制作“复杂”语句的困难所限制。然而,在程序的主要编程任务是简单地构建和“调整”程序的可视界面,而其详细行为具有底层定义的情况下,这些图标可以是强大的工具。
以下考虑因素适用于软件构建编码活动:
构建涉及两种测试形式,通常由编写代码的软件工程师执行:
构建测试的目的是缩小故障被插入代码的时间与检测到这些故障的时间之间的差距,从而减少修复它们所产生的成本。在某些情况下,测试用例是在编写代码后编写的。在其他情况下,测试用例可能是在编写代码之前创建的。
构建测试通常涉及各种类型的测试的子集,这些类型在软件测试KA中有描述。例如,构建测试通常不包括系统测试、Alpha测试、Beta测试、压力测试、配置测试、可用性测试或其他更专门的测试形式。有关构建测试的主题已经发表了两个标准:IEEE 829-1998标准,软件测试文档标准,以及IEEE 1008-1987标准,软件单元测试标准。
(有关更多专业参考资料,请参阅软件测试KA中的2.1.1,单元测试和2.1.2,集成测试的部分。)
重用构建创建具有未来在当前项目或采用广泛的、多系统视角的其他项目中重复使用潜力的软件。重用构建通常基于变异性分析和设计。为了避免代码克隆的问题,期望将可重用代码片段封装到良好结构化的库或组件中。
在编码和测试过程中与软件重用相关的任务如下:
构建与重用意味着利用现有软件资产创建新软件。最流行的重用方法是从语言、平台、工具提供的库或组织存储库中重用代码。除了这些之外,当今开发的应用程序广泛使用许多开源库。重用和现成软件通常具有与新开发的软件相同或更好的质量要求(例如,安全级别)。
在编码和测试过程中与重用构建相关的任务如下:
除了由需求和设计引入的故障外,构建过程中引入的故障也可能导致严重的质量问题——例如,安全漏洞。这不仅包括安全功能中的故障,还包括其他地方允许绕过此功能的故障以及其他安全弱点或违规行为。
存在许多技术以确保代码在构建过程中的质量。用于构建质量的主要技术包括
所选择的具体技术取决于正在构建的软件的性质,以及执行构建活动的软件工程师的技能。程序员应该了解良好的实践和常见的漏洞——例如,从广泛公认的常见漏
洞列表中了解。对于几种常见的编程语言,可以使用自动的静态代码分析来检测安全弱点,并且可以在安全关键项目中使用。
构建质量活动与其他质量活动的区别在于它们的焦点。构建质量活动侧重于与代码直接相关的代码和与代码较少直接相关的工件,如需求、高层设计和计划不同。.
构建期间的一个关键活动是将单独构建的例程、类、组件和子系统集成到一个系统中。此外,特定的软件系统可能需要与其他软件或硬件系统集成。
与构建集成相关的关注点包括规划组件集成的顺序、确定需要的硬件、创建支持软件中间版本的脚手架、确定在组件集成之前对其进行的测试和质量工作的程度,以及确定项目中的点在这些点上对软件进行了测试。可以通过阶段性或增量性方法来集成程序。阶段性集成,也称为“大爆炸”集成,涉及推迟组件软件部分的集成,直到版本中的所有部分都完成。人们认为增量集成比传统的阶段性集成具有许多优点,例如更容易的错误定位、改进的进度监控、更早的产品交付和改善的客户关系。在增量集成中,开发人员逐个编写和测试程序的片段,然后将这些片段合并。通常需要额外的测试基础设施,例如存根、驱动程序和模拟对象,以支持增量集成。通过逐个构建和集成单位(例如类或组件),构建过程可以向开发人员和客户提供早期反馈。增量集成的其他优点包括更容易的错误定位、改进的进度监控、更全面的测试单元等。
应用程序编程接口(API)是导出并可供库或框架的用户编写其应用程序使用的一组签名。除了签名外,API应始终包括关于程序效果和/或行为(即其语义)的说明。
API设计应尽量使API易于学习和记忆,导致可读的代码,难以滥用,易于扩展,完整,并保持向后兼容性。由于API通常比其实现更持久用于广泛使用的库或框架,因此希望API直接且稳定,以便促进客户应用程序的开发和维护。
API的使用涉及选择、学习、测试、集成和可能扩展由库或框架提供的API(参见第3.6节,重用构建)的过程。
面向对象的语言支持一系列运行时机制,包括多态和反射。这些运行时机制增加了面向对象程序的灵活性和适应性。多态是一种语言支持通用操作的能力,而不需要在运行时知道软件将包含哪种具体对象。因为程序事先不知道对象的确切类型,所以确切的行为是在运行时确定的(称为动态绑定)。
反射是程序观察和修改其自身结构和行为的能力。反射允许在运行时检查类、接口、字段和方法,而无需在编译时知道它们的名称。它还允许在运行时使用参数化类和方法名称实例化新对象和调用方法。
参数化类型,也称为泛型(Ada,Eiffel)和模板(C ++),使得可以定义一种类型或类,而无需指定它使用的所有其他类型。未指定的类型在使用点提供为参数。参数化类型提供了一种在面向对象软件中组合行为的第三种方式(除了类继承和对象组合)。
断言是放置在程序中的可执行断言的谓词,通常是例程或宏,允许对程序进行运行时检查。断言在高可靠性程序中特别有用。它们使程序员能够更快地发现不匹配的接口假设、在代码修改时引入的错误等。断言通常在开发时编译到代码中,然后在代码中编译出来,以免降低性能。
按契约设计是一种开发方法,其中为每个例程包括前置条件和后置条件。当使用前置条件和后置条件时,每个例程或类都被认为与程序的其余部分形成契约。此外,契约提供了对例程语义的精确规范,从而有助于理解其行为。据认为,按契约设计可以提高软件构建的质量。
防御性编程意味着保护例程免受无效输入的破坏。处理无效输入的常见方法包括检查所有输入参数的值,并决定如何处理不良输入。断言通常用于防御性编程以检查输入值。
错误处理方式影响软件满足有关正确性、健壮性和其他非功能属性的要求的能力。有时使用断言来检查错误。其他错误处理技术——如返回中性值、替换下一个有效数据片段、记录警告消息、返回错误代码或关闭软件等——也被使用。
异常用于检测和处理错误或异常事件。异常的基本结构是一个例程使用throw来抛出检测到的异常,然后异常处理块将在try-catch块中捕获异常。try-catch块可以处理例程中的错误条件,也可以将控制返回给调用例程。异常处理策略应该经过精心设计,遵循常见原则,例如在异常消息中包含导致异常的所有信息、避免空的catch块、了解库代码抛出的异常、可能构建一个集中的异常报告器以及标准化程序对异常的使用。
容错是一组技术,通过检测错误并在可能时从中恢复或在无法恢复时限制其影响来提高软件可靠性。最常见的容错策略包括备份和重试、使用辅助代码、使用投票算法以及用虚假值替换错误值,该虚假值将具有良性影响。
可执行模型抽象了特定编程语言的细节和关于软件组织的决策。与传统软件模型不同,使用可执行建模语言(如可执行UML)构建的规范可以在各种软件环境中部署而无需更改。可执行模型编译器(转换器)可以使用关于目标硬件和软件环境的一组决策将可执行模型转换为实现。因此,构建可执行模型可以被视为构建可执行软件的一种方式。
可执行模型是支持面向模型的体系结构(MDA)倡议的基础之一,该倡议由对象管理组织(OMG)发起。可执行模型是完全指
定平台独立模型(PIM)的一种方法;PIM是不依赖于任何实现技术的问题解决方案的模型。然后,可以通过将PIM和依赖于其的平台织合在一起来生成特定平台模型(PSM),PSM是包含实现细节的模型,可以通过将PIM和依赖于其的平台织合在一起来生成特定平台模型(PSM),PSM是包含实现细节的模型。模型。
基于状态的编程,或自动机式编程,是一种使用有限状态机描述程序行为的编程技术。状态机的转换图在软件开发的所有阶段(规范、实现、调试和文档编制)中都被使用。主要思想是以与技术过程自动化相同的方式构建计算机程序。通常将基于状态的编程与面向对象编程相结合,形成一种称为基于状态的面向对象编程的新组合方法。
表驱动方法是一种使用表来查找信息而不是使用逻辑语句(如if和case)的模式。在适当的情况下使用表驱动代码比复杂逻辑更简单,并且更容易修改。在使用表驱动方法时,程序员需要解决两个问题:在表或表中存储什么信息以及如何有效地访问表中的信息。
为了实现更多的灵活性,程序通常被构造为支持其变量的后期绑定时间。运行时配置是一种在程序运行时绑定变量值和程序设置的技术,通常是通过即时更新和读取配置文件来完成的。
国际化是准备程序(通常是交互式软件)以支持多个区域设置的技术活动。相应的活动,本地化,是修改程序以支持特定本地语言的活动。交互式软件可能包含几十个或几百个提示、状态显示、帮助消息、错误消息等。设计和构造过程应该考虑字符串和字符集问题,包括使用哪种字符集、使用哪种类型的字符串、如何在不更改代码的情况下维护字符串以及如何将字符串转换为不同语言而对处理代码和用户界面产生最小影响。
基于语法的输入处理涉及对输入令牌流进行语法分析,或解析。它涉及创建一个表示输入数据的数据结构(称为解析树或语法树)。解析树的中序遍历通常会给出刚刚解析的表达式。解析器检查符号表,以查找填充树的程序员定义变量。构建解析树后,程序将其用作计算过程的输入。
同步原语是由编程语言或操作系统提供的编程抽象,可促进并发和同步。众所周知的并发原语包括信号量、监视器和互斥体。
信号量是受保护的变量或抽象数据类型,提供了一种在并发编程环境中多个进程或线程之间控制对公共资源访问的简单但有用的抽象。
监视器是一个抽象数据类型,它提供一组由互斥执行的程序员定义的操作。监视器包含共享变量的声明和操作这些变量的过程或函数。监视器构造确保一次只有一个进程在监视器内活动。
互斥体(互斥)是一种同步原语,它只允许一个进程或线程一次访问共享资源。
中间件是一个广泛的分类,用于提供操作系统层以上但应用程序层以下的软件服务。中间件可以为软件组件提供运行时容器,以提供消息传递、持久性和网络中的透明位置。中间件可以被视为连接使用中间件的组件之间的连接器。现代面向消息的中间件通常提供企业服务总线(ESB),它支持多个软件应用程序之间的面向服务的交互和通信。
分布式系统是由物理上分离的、可能是异构的计算机系统组成的集合,这些系统通过网络连接以向用户提供对系统维护的各种资源的访问。分布式软件的构造与传统软件构造不同,因为它涉及并行性、通信和容错等问题。
分布式编程通常分为几种基本的架构类别:客户端-服务器、3层体系结构、n层体系结构、分布式对象、松散耦合或紧密耦合(参见计算基础知识KA的第14.3节和软件设计KA的第3.2节)。
异构系统由各种不同类型的专用计算单元组成,例如数字信号处理器(DSP)、微控制器和外围处理器。这些计算单元是独立控制的,并且彼此通信。嵌入式系统通常是异构系统。
异构系统的设计可能需要结合几种规范语言来设计系统的不同部分——换句话说,硬件/软件代码设计。关键问题包括多语言验证、协同仿真和接口。
在硬件/软件代码设计期间,软件开发和虚拟硬件开发通过逐步分解同时进行。硬件部分通常在现场可编程门阵列(FPGA)或专用集成电路(ASIC)中进行模拟。软件部分被转换为低级编程语言。
代码效率——由架构、详细设计决策、数据结构和算法选择决定——影响执行速度和大小。性能分析是通过收集程序执行时收集的信息来调查程序行为的调查,目标是识别可能需要改进的程序中的热点。
代码调优是在代码级别改进性能的做法,是修改正确代码以使其运行更高效的做法。代码调优通常涉及对影响单个类、单个例程或更常见的几行代码的小规模更改。有一套丰富的代码调优技术可供使用,包括用于调整逻辑表达式、循环、数据转换、表达式和例程的技术。使用低级语言是改进程序中某些热点的常见技术之一。
平台标准使程序员能够开发可在兼容环境中执行的可移植应用程序,而无需更改。平台标准通常涉及一组标准服务和API,兼容的平台实现必须实现这些标准。平台标准的典型示例是Java 2平台企业版(J2EE)和操作系统的POSIX标准(便携式操作系统接口),它代表了主要为基于UNIX的操作系统实现的一组标准。
先测试编程(也称为测试驱动开发—TDD)是一种流行的开发风格,其中在编写任何代码之前先编写测试用例。先测试编程通常可以比传统的编程风格更早地检测到缺陷并更容易地纠正它们。此外,首先编写测试用例会迫使程序员在编码之前考虑要求和设计,从而更早地暴露出要求和设计问题。
开发环境,或集成开发环境(IDE),通过集成一组开发工具,为程序员提供全面的软件构建设施。开发环境的选择可以影响软件构建的效率和质量。
除了基本的代码编辑功能外,现代IDE通常还提供其他功能,如从编辑器内进行编译和错误检测、与源代码控制的集成、构建/测试/调试工具、程序的压缩或概要视图、自动化代码转换和重构支持。
GUI(图形用户界面)构建器是一种软件开发工具,它使开发人员能够以所见即所得(WYSIWYG)模式创建和维护GUI。GUI构建器通常包括一个可视化编辑器,开发人员可以使用该编辑器设计表单和窗口,并通过拖放和参数设置管理部件的布局。一些GUI构建器可以自动生成与视觉GUI设计相对应的源代码。
因为当前的GUI应用程序通常遵循事件驱动的风格(其中程序的流程由事件和事件处理决定),GUI构建器工具通常提供代码生成助手,自动化事件处理所需的最重复的任务。支持代码将部件与触发应用程序逻辑函数的出站和入站事件连接起来。
一些现代IDE提供集成的GUI构建器或GUI构建器插件。还有许多独立的GUI构建器。
单元测试验证与其他可单独测试的软件元素(例如类、例程、组件)分离的软件模块的功能。单元测试通常是自动化的。开发人员可以使用单元测试工具和框架来扩展和创建自动化测试环境。使用单元测试工具和框架,开发人员可以将标准编码到测试中,以验证在各种数据集下单元的正确性。每个单独的测试都实现为一个对象,测试运行程序运行所有测试。在测试执行过程中,那些失败的测试用例将被自动标记和报告。
性能分析工具通常用于支持代码调优。最常见的性能分析工具是性能分析工具。执行性能分析工具在代码运行时监视代码,并记录每个语句执行了多少次,或程序在每个语句或执行路径上花费了多少时间。在运行时对代码进行性能分析可以洞察程序的运行方式,热点在哪里,开发人员应该将代码调优工作集中在哪里。
程序切片涉及计算一组可能影响指定变量值的程序语句(即程序切片)在某个感兴趣点上的计算,这被称为切片标准。程序切片可用于定位错误的源头、程序理解和优化分析。程序切片工具使用静态或动态分析方法为各种编程语言计算程序切片。
更多【软件工程-软件工程知识体系 Chapter3 软件构造】相关视频教程:www.yxfzedu.com