software-strategy-book/Ch1-4-SoftwareEngineering.tex

535 lines
58 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

% !TEX root = main.tex
\section{软件工程的诞生}
50年前1968年在德国的一个叫做Garmisch的小镇上由NATO科学委员会主导召开了一个小型研讨会有来自11个国家的50位代表参加。会议的议题是如何应对当时面临的所谓“软件危机”。在这个研讨会上诞生了“软件工程”这个学科领域[1]。软件危机指,在所需时间内编写出有用且高效的计算机程序存在很大困难。其原因出自,一计算机能力的迅速增长,二希望用软件来解决的现实问题的日益复杂,三当时可以采用的软件开发方法明显不能应对。导致软件的开发出现了许多问题。
Dijkstra在那个研讨会上就指出[2]:软件危机的主要原因是机器变得更强大,强大了好几个数量级!坦率地说:只要没有机器,编程就没有问题了; 如果只有一些比较弱的机器,编程就是简单的问题,但当有了能力巨大的计算机,编程就成为同样大的问题。总之,主要原因是机器能支持的计算能力和人对软件的预期,远远超出了程序员能够有效利用的能力和对问题的驾驭能力。当时谈到的软件危机表现为多种形式:软件开发效率低(如,项目超预算,项目时间过长,软件滞后交付),软件质量很差(如,很多方面不符合要求),项目难以管理(如,代码难以维护),等等。
50年前这次会议讨论的问题涉及软件开发的方方面面软件与硬件的关系、软件的设计、软件的生产、软件的分发、以及软件的服务等。这次会议成为软件工程学科的奠基性会议所讨论的核心议题成为软件工程学科经久不衰的开放性挑战问题比如1获取正确的软件需求2设计合适的系统架构3正确和有效地实现软件4能验证软件的质量5长期维护具有目标功能和高代码质量的软件系统。
1986 年,布鲁克斯(Brooks) 在《人月神话》中给出了“软件开发没有银弹”的预言[3]即由于软件本质上的复杂性在未来10 年内不存在任何技术或方法能够使软件生产力提升10 倍以上。1995 年布鲁克斯在重新发行的《人月神话》纪念版中再次重申“软件开发没有银弹”的预言在下一个10 年仍然成立[4]。布鲁克斯的观点得到了软件开发实践者和研究者的广泛关注和讨论。虽然有学者曾经宣称某项技术或方法有可能成为“银弹”,但实践表明这些技术或方法后来都没有成为“银弹”。
随着信息技术的发展软件技术的应用范围不断扩大应用领域不断深入50年前的软件和现代软件已经不可同日而语在最初出现软件的时候谁都没有预计到现在人们对软件的期望谁都没能想象出通过在互联网和物联网之上未来人机物融合系统将会在任何地方并由任何人来操控。软件工程50年前的核心挑战仍然还是当前的核心挑战问题表述几乎没有变化但问题在不同年代却被赋予了不同的内涵。“软件开发没有银弹” 的预言仍是软件工程研究者和实践者不可逾越之“墙”。
\section{软件工程的内涵和知识体系}
什么是软件工程如何理解软件工程Wikipedia\footnote{https://en.wikipedia.org/wiki/Software\_engineering}引用的简短描述涵盖了其主要关注点:软件工程是将\textbf{工程化的手段}并采用\textbf{系统化的方法}进行\textbf{软件开发}[5]。
具体一点来说,可以罗列一些大家公认的说法,比如:
\hangafter=1
\setlength{\hangindent}{2.6em}
• 系统地将科学知识、方法和经验应用于软件的设计,实施,测试和记录[6]。
\hangafter=1
\setlength{\hangindent}{2.6em}
• 应用系统的、规范的、可量化的方法,来开发、运行和维护软件[7]。
\hangafter=1
\setlength{\hangindent}{2.6em}
• 关注软件生产各个方面的工程学科[8]。
\hangafter=1
\setlength{\hangindent}{2.6em}
• 建立和使用合理的工程原理,以便经济地获得可靠且在计算机上高效工作的软件。
\hangafter=1
\setlength{\hangindent}{2.6em}
• 软件工程是一个包含过程、一系列方法和工具的框架[9]。
\hangafter=1
\setlength{\hangindent}{2.6em}
• 软件工程是处理构建大型和复杂软件系统的计算机科学领域,这些软件系统如此之大和复杂,使得其要有一组或多组工程师来构建[10]。
\hangafter=1
\setlength{\hangindent}{2.6em}
• 软件工程关注大型程序的构造,协作是大型程序设计的主要机制,中心主题是控制复杂度,管理软件的进化。其中,所开发软件的有效性是至关重要的,软件必须有效地支持用户[11]。
Dines Bjorner认为[12]理解软件工程需要同时回答“how”如何进行和“what”要做什么而上述关于软件工程的表述仅仅涉及其中一个问题的回答
\hangafter=1
\setlength{\hangindent}{2.6em}
• 软件工程是艺术、规范、工艺、科学、逻辑、和实践:
\hangafter=1
\setlength{\hangindent}{2.6em}
\ \ \ \ o 基于科学的洞察,去综合(即构建、构造)软件(即技术),和
\hangafter=1
\setlength{\hangindent}{1.6em}
\ \ \ \ o 分析(即学习、研究)现有的软件技术,为了探清和发现其可能的科学内容。
基于此,他给出了关于“软件工程”概念的具体刻画[12]
\hangafter=1
\setlength{\hangindent}{2.6em}
• 软件工程师需要建立和使用可靠的方法,以有效地构建令人满意的软件,该软件可以解决用户确认的问题
\hangafter=1
\setlength{\hangindent}{2.6em}
• 软件工程扩充了计算机科学领域,以涵盖软件系统的构造,这些软件系统常常非常大也非常复杂,需要一组或多组工程师协作完成
\hangafter=1
\setlength{\hangindent}{2.6em}
• 软件工程是一门学科它把通过学习和实践获得的数学知识加以判断优化成为应用数学的方式1理解问题领域2解决现实问题3为这些通常通过计算来解决的问题开发计算系统建立软件解决方案
\hangafter=1
\setlength{\hangindent}{2.6em}
• 软件工程由一下三部分组成1领域工程以理解问题领域2需求工程以理解问题及它们的解决方案的可能框架3软件设计以实现想要的解决方案
从上述分析可知,软件工程要解决的问题是\textbf{如何高效地开发出符合要求的产品}。这中间包含三个方面的含义。第一,软件工程的产出是一类产品,其产品形态是\textbf{软件},这决定了软件工程学科的研究对象。第二,软件工程需要高效高质地开发出这类产品,工程化是使产品开发得以高效的一种手段,工程化一般依赖于管理有序的\textbf{生产过程},生产过程中要依据的合适的\textbf{方法},以及可操作的\textbf{质量保证手段}。这构成了窄义的软件工程学科的研究范畴。第三,软件产品是用来解决现实世界的\textbf{领域相关问题}的,它的使用需要能为相关领域带来\textbf{价值},更进一步地,领域价值的评判已经超出窄义的软件工程的范畴,其论域范畴扩展到了应用领域中,因此,\textbf{领域工程}进入广义的软件工程学科范畴,同时,\textbf{需求工程}需求工程成为领域工程和窄义的软件工程的之间的桥梁。
软件工程学科所针对的关键问题包括1如何理解所面对的问题领域2如何理解当前需要软件来解决的问题以此推断可能的解决方案3如何高效高质地开发出能胜任的软件。
\begin{figure}[ht]
\centering
\includegraphics[scale=0.3]{fig1-4/fig1.png}
\caption{软件工程学科组成成分}
\label{fig:fig1}
\end{figure}
概述地说,软件工程的内涵可以用图\ref{fig:fig1}展示。其中内核三部分为软件工程的核心内容包括领域工程、需求工程和软件系统设计与实现三部分这三个部分形成广义上的软件工程的学科内涵。其中软件系统设计与实现是软件工程学科的主体内容也是软件工程50年来发展最快的部分。其针对的问题是如何高效高质地开发出能胜任的软件系统其知识和技术体系体现在软件工程的方法、过程、质量保证及其相应的支撑工具上这部分内容将在第3节予以描述。
软件工程相比与传统的工程学科其最大的不同在于它的跨行业性也就是涉及领域工程和需求工程就是解决解决软件的跨行业性其针对的问题包括如何理解所面对的问题领域领域工程和如何理解需要用软件技术来解决的问题需求工程。这两部分的内容将在第4节中描述。
图1外围中的圆圈中还列举了一些与软件工程有适度交叉的领域包括计算机科学与技术是软件工程的技术支撑。数学提供了软件工程研究特别是定量研究中所需的数学工具和理论支撑。管理科学和生态学为复杂软件系统的系统化和工程化管理以及软件开发和应用生态的建立和可持续发展提供指导。在成为人类社会生活的基础设施后软件系统需要遵循或受到各项法律法规的约束。系统科学则将成为软件工程应对复杂领域问题的系统方法学。
从学科知识体系的角度IEEE SWEBOK Guide V3.0[13]给出了软件工程的15个知识领域见图\ref{fig:fig2}),包括:软件需求、软件设计、软件构造、软件测试、软件维护、软件配置管理、软件工程管理、软件工程过程、软件工程模型和方法、软件质量、软件工程职业实践、软件工程经济学、计算基础、数学基础和工程基础。这个知识分类体系,除了基础性知识领域外,其它的大部分知识领域可以归属为上述的软件系统设计和实现的内容。软件需求知识领域可以归属为需求工程范畴,但需求分析仅仅是需求工程中的一个很小的部分。该知识分类体系没有涉及领域工程。
\begin{figure}[ht]
\centering
\includegraphics[scale=1]{fig1-4/fig2.png}
\caption{IEEE SWEBOK Guide V3.0软件工程知识体系}
\label{fig:fig2}
\end{figure}
\section{软件工程方法、过程、质量保障和工具}
从研究布局的角度看,软件工程的研究可以分为软件工程方法、软件工程过程、软件质量保障、以及软件工程工具这四个维度。本节下面的部分分别从这几个维度进行介绍。
\subsection{软件工程方法}
\subsubsection{概述}
在软件工程早期软件开发基本上没有可遵循的方法程序员只是依据自己的经验并根据需要解决的问题直接编写代码。根据M. H. Hamilton的回忆 [13],在她负责的早期飞行控制软件开发项目中,当时程序员主要关心的是,理解硬件和软件的关系以及如何利用这类知识来提升软件的性能。由于没有任何辅助工具,程序员最担心的是代码出错,需要不断地花时间进行手工调试。
在总结早期飞行控制软件开发经验的基础上M. H. Hamilton设计了一个通用系统语言Universal System Language, USL[14]其灵感来自她对Apollo软件开发过程中出现的错误模式或错误类别的认识。当时子系统间的接口错误占了软件错误的绝大部分而且这些错误通常是最难找到和调试正确的。USL给出了不同接口错误的类别定义通过这些系统定义来识别错误并在系统设计的时候预防它们。 USL定义了六个公理形成了控制逻辑的数学构造性理论的基础。该语言还在Hamilton TechnologiesInc推出的001 Tool Suite软件上得到实现。
软件工程方法是用于指导软件开发和维护的结构化方法,主要为了使软件开发和维护具有结构性,使软件开发和维护成为系统化可重复的过程,从而提高软件开发的成功率。主流的软件工程方法(如结构化方法和面向对象方法)都是在相应的程序设计方法基础上发展起来的。其中,程序设计方法主要关心程序的组织、构造和集成,而软件工程方法则将类似的思想(如对象和类的划分及其关系)拓展到软件分析和设计。随着软件和软件应用的发展,软件工程方法一直在不断地发展,其主要关注点从系统的功能设计和实现(结构化方法)。到面向现实世界问题实体对象的设计和实现(面向对象方法),再到面向现实世界问题求解非功能属性的设计和实现等,使软件开发方法的隐含面不断向现实世界发展。
除了系统化的软件开发方法,软件开发效率和质量是软件工程追求的一个目标,面向构件的软件工程尝试采用大规模复用的手段,提高软件的开发效率,以及提升所开发的软件的质量。面向服务的软件工程则是另一种基于复用的方法,将其它软件提供的服务作为可复用的构件,软件系统通过复用并无缝集成来自不同提供方的服务来获得。
各种不同的软件开发方法虽然在问题分解和解决方案组织等方面的思路不同但一般都遵循模块化原则即将软件划分为相对独立的模块允许不同的模块分别开发和测试并通过模块集成得到完整的软件解决方案。模块独立性一般可以使用内聚度和耦合度来衡量。满足模块独立性的软件设计可以使得软件的划分结构容易理解简化模块间接口同时降低不同模块间的相互影响。模块化原则在不同的软件开发方法中可以通过不同的方式实现例如程序和子程序、类以及构件划分等。1970年代末期兴起的模块互联语言Module Interconnection Language简称MIL[p1]可用于形式化地刻画构成一个完整的软件系统所需的各种模块之间联接关系的规格说明基于这种形式化描述可以验证系统的完整性和模块间兼容性。模块互联语言是一种结构化的设计语言。与之相似的还有各种体系结构描述语言Architecture Description Language简称ADL
除了上述软件开发方法之外,还有其它一些软件开发和软件工程模式,比如开源软件开发、基于搜索的方法以及敏捷开发等,它们都从不同的角度应对软件开发的问题,解决软件危机,尝试找到软件开发的“银弹”。
\subsubsection{结构化系统分析和设计方法 \protect\footnote{https://en.wikipedia.org/wiki/Structured\_systems\_analysis\_and\_design\_method}}
结构化系统分析和设计方法SSADM是一种系统化的软件分析方法它发展于20世纪70-80年代是一种用于分析和设计信息系统的瀑布方法。SSADM是不同流派的结构化方法的综合集成典型的包括Peter Checkland的软系统方法[15]Larry Constantine的结构化设计[16]Edward Yourdon的Yourdon结构化方法[17]Michael A. Jackson的Jackson结构化编程[18]和结构化设计[19]以及Tom DeMarco的 结构化分析[20]等。
SSADM倡导三种建模技术它们目前还是软件系统数据建模和分析的重要技术
\hangafter=1
\setlength{\hangindent}{2.6em}
• 逻辑数据建模:识别、建模和记录要设计的系统的数据需求的过程。建模结果为数据模型,包含实体(业务处理需要记录的信息),属性(与实体相关的事实)和关系(实体间的关联)。建模结果为实体关系模型。
\hangafter=1
\setlength{\hangindent}{2.6em}
• 数据流建模:识别、建模和记录数据如何在信息系统中流动的过程。展示过程(即将一种形式的数据转换为另一种形式的活动),数据存储(数据存留点),外部实体(将数据发送到当前系统或从系统接收数据的外部系统)和数据流向(数据通过什么路由流动)。建模结果为数据流模型。
\hangafter=1
\setlength{\hangindent}{2.6em}
• 实体事件建模:是一个双向过程,包括实体行为建模,即识别、建模和记录影响每个实体的事件以及事件发生的序列(形成实体的生命历程);和事件建模,即为每个事件设计一个协调实体生命历程的过程。建模结果为实体生命历程,和事件效果对应图。
\subsubsection{面向对象的分析和设计 \protect\footnote{https://en.wikipedia.org/wiki/Object-oriented\_analysis\_and\_design}}
面向对象方法起源于20世纪90年代早期有不同的面向对象方法它们通常与特定的计算机辅助软件工程CASE工具联系在一起。其中比较有代表性的包括Grady Booch的Booch方法[21]James Rumbaugh的OMT方法[22]Ivar Jacobson的OOSE方法[23]。但这三种不同体系下形成的软件制品彼此间难以理解和复用如何形成一个能够支撑从需求到实现的软件行业标准成为当时的一个亟需解决的问题。1994年他们一起合作开发了统一建模语言UML[24]并将他们的方法与其他各种见解和经验集成到Rational Unified ProcessRUP[25]中,自此统一过程成为面向对象分析和设计最流行的方法和参考模型,形成全面的迭代和增量过程的指南和框架,成为软件开发和项目管理的最佳实践。
面向对象方法强调模块化和可复用性,追求“开闭原则”(即对扩张开放、对修改封闭)的实现。如果模块支持扩展,或者模块提供标准化方法来添加新行为或描述新状态,则模块是开放的。这在面向对象方法中通过创建现有类的新子类来实现。如果模块具有明确定义的稳定接口,所有其他模块只能通过这个接口访问该模块,从而限制由于其它模块的改变而引入的交互和潜在错误,则该模块是封闭的。这在面向对象方法中通过定义调用对象上的方法来实现,方法可以是公共的或私有的,即,对象特有的某些行为不会暴露给其他对象。这减少了软件实现中的许多常见错误。
相比于结构化分析将过程和数据分开考虑,面向对象分析的特点是,关注于从问题领域中识别出来的对象,并围绕这些对象来组织系统需求,通过对象集成系统的行为(流程)和状态(数据)。在设计阶段,面向对象方法侧重于将实现约束作用于分析过程中得到的概念模型上,比如硬件和软件平台,性能要求,持久存储和事务,系统的可用性以及预算和时间所施加的限制等,分析模型中与技术无关的概念被映射到实现类和接口,进而得到解决方案域的模型,强调利用架构模式和设计模式等指导软件架构的设计[26]。
\subsubsection{基于构件的软件工程}
软件复用被视为解决软件危机,提高软件生产效率和软件质量的现实可行的途径[p2]。基本的软件复用对象主要是各种软件代码单元包括子程序subroutine、函数function、类class和构件component等。早在1968年Doug Mcllroy在NATO软件工程会议上发表的论文“大量生产的软件构件”中就提出了大规模软件复用的思想[p3]。早期流行的软件复用对象主要是各种函数库,例如美国自然科学基金会组织构建的数学函数库。随后,面向对象开发中所使用的类由于其良好的封装性以及对应客观世界的实体特性而逐渐成为一种主流的软件复用对象。
早期的软件复用方法所复用的代码单元较小同时缺乏系统性的过程和方法支持因此难以形成完整的软件开发方法。随着CORBA、EJB、COM/DCOM等软件构件标准的成熟和广泛应用基于构件的软件开发方法作为一种系统性的基于复用的软件开发方法被提出来了。构件是指软件系统中具有相对独立功能、可以明确辨识、接口由契约指定、和语境有明显依赖关系、可独立部署、且多由第三方提供的可组装软件实体[p4]。这种方法以软件构件作为基本的复用对象,将软件构造从传统以软件编码工作为主的方式转换为以软件构件集成和组装为主的方式。
与传统的函数和类等复用单元相比,软件构件具有多个方面的特性使得其更适合作为一种系统化的软件复用对象。软件构件一般粒度较大,实现了相对完整的业务功能,按照某种构件标准进行了良好的封装并且可以独立部署。另一方面,软件构件具有明确的构件描述、环境依赖和接口规约,用户通过构件描述查找构件并理解其使用方式,根据环境依赖对其进行部署和配置,同时按照接口规约请求构件的服务。此外,为了实现良好的可复用性,软件构件还应当具有较好的通用性和质量,易于组装并提供完善的文档和复用样例。
基于构件的软件开发过程主要包括构件的识别和开发、构件描述和管理、基于构件的应用开发三方面。构件的识别和开发针对特定业务或技术领域的共性需求和技术问题进行分析,从中识别并抽象出可复用构件的开发机会,并按照特定构件标准进行实现和封装。构件描述和管理对软件构件进行描述、分类、存储,并提供构件发布版本管理和检索机制,在此基础上通过建立软件构件库对外提供统一的构件上传、更新、检索等服务。基于构件的应用开发根据应用软件的需求检索并获取可复用构件,对其进行定制和适配,然后基于软件体系结构描述实现构件间的组装,从而实现应用软件的需求。
软件构件技术的发展还催生了商用成品构件Commercial Off-The-Shelf简称COTS的出现例如在信息系统中有着广泛应用的报表构件、文档处理构件等。商用成品构件一般都符合特定的构件标准并具有良好的可组装性由独立的构件开发厂商提供应用开发厂商通过购买获得构件使用权并通过黑盒的方法进行组装和复用。
\subsubsection{基于搜索的软件工程}
许多软件工程任务可以建模位计算搜索、组合优化问题基于搜索的软件工程就是用来解决这些软件工程任务的。这类方法最早在1976年出现当时Webb Miller 和 David Spooner尝试把优化算法用于浮点测试数据的生成[27]。1992年Xanthakis等将搜索算法用于解决软件测试问题[28]。2001年Harman 和 Jones正式基于搜索的软件工程[29]。
SBSE从问题的解空间出发将软件工程任务转换为可使用元启发式搜索优化算法来处理的计算搜索任务涉及定义搜索空间或一组可能的解决方案并使用度量函数即适应度函数来测量潜在解决方案的质量从而实现软件工程任务求解的自动化和智能化。
SBSE适用于软件开发过程的几乎所有阶段其中软件测试是主要的应用阶段之一其他软件工程任务包括需求分析软件设计软件开发和维护等。
\subsubsection{敏捷软件开发}
敏捷软件开发通过自组织和跨职能团队及其客户/最终用户的协作努力,使需求和解决方案不断演化发展的方法,它倡导适应式规划、演化式发展、尽早交付和持续改进,同时鼓励快速应变和灵活反应。
实际上迭代增量开发可追溯到1957年[30],而演化式项目管理[31]和自适应软件开发[32]也早在70年代就已经出现。90年代有很多批评针对一些僵化的对软件工程的过度监管、计划和微观管理等重量级方法许多轻量级方法得以发展其中包括快速应用开发RAD[33]统一过程UP和动态系统开发方法DSDMScrum、Crystal Clear和极限编程XP特征驱动开发等。他们都早于敏捷宣言但现在都被包含进敏捷软件开发方法。
2001年17位软件开发人员\footnote{Kent BeckWard CunninghamDave ThomasJeff SutherlandKen SchwaberJim HighsmithAlistair CockburnRobert C. MartinMike Beedle Arie van BennekumMartin FowlerJames GrenningAndrew HuntRon JeffriesJon KernBrian Marick和Steve Mellor。}在犹他州雪鸟度假村开会,讨论这些轻量级开发方法,随后他们发布了“敏捷软件开发宣言”,包含如下十二项原则:[22]1通过尽早和持续交付有价值的软件来实现客户满意度2即使在项目后期也需要拥抱不断变化的要求3经常性地按周而不是按月提供可工作的软件4业务人员和开发人员间密切合作5项目围绕有有动机目的的人建立他们需要得到信任6面对面交谈是最好的沟通方式7可工作的软件是项目进展的主要衡量标准8可持续地向前推进保持稳定的步伐9不断关注技术进展和良好设计10简单性 - 最大化未完成工作量的艺术 - 至关重要11最好的架构要求和设计来自自组织团队12团队反思如何变得更有效并相应地进行调整。
\subsection{软件工程过程和过程管理}
软件工程师要开发和维护软件,就要完成一系列的活动,比如需求、设计、构造、测试、配置管理等,软件工程过程主要就涉及这些活动。将软件的开发和维护,分解成这样一组活动,主要是为了便于管理。软件开发过程是为了实现事先定义的目标而建立起来的一组活动,这组活动之间有一定的先后顺序,并作为一个整体来实现事先定义的目标。这里所提及的目标就是软件项目管理试图要实现的目标,例如成本、工期以及质量等典型目标。软件过程管理的管理对象就是软件过程,管理的直接目的是为了让软件过程在开发效率、质量等方面有着更好性能绩效。
\subsubsection{系统生命周期}
系统生命周期是涉及系统存在所有阶段的一个视图,包括概念设计阶段,设计和开发阶段,生产和构建阶段,分发和运行阶段,维护和支持阶段,退役阶段,淘汰和处置阶段。
概念设计阶段确定需求,定义潜在解决方案,评估潜在解决方案以及开发系统规范,为系统设计提供全面的技术要求指导。设计和开发阶段进行所需系统功能的所有子系统的符合系统规范的设计,定义子系统间的接口,以及整体测试和评估要求,最后生成足以执行详细设计和开发的开发规范。详细设计和开发细化和初始系统规范,产生系统与其预计环境间的接口规范,以及对系统维护和支持要求的综合评估,负责完成产品、工艺和材料的规范。
在生产和施工阶段,产品将按照产品、工艺和材料规范中规定的要求制造或组装,并在目标环境中进行部署和测试,进行系统评估以纠正缺陷并使系统适应持续改进。完全部署后,系统将用于其预期的操作角色并在其操作环境中维护。最后还必须不断评估系统的有效性和效率,以确定产品何时达到其最大有效生命周期。 考虑因素包括:持续存在运营需求,运营要求与系统性能之间的匹配,系统淘汰与维护的可行性以及替代系统的可用性。
典型的生命周期模型包括瀑布模型、迭代式模型、增量模型、螺旋模型以及原型法等。对应系统的生命周期,有多种系统开发生命周期模型[33],主要包括瀑布模型、迭代模型、增量模型、螺旋模型以及原型法等。
\subsubsection{软件过程和软件过程管理}
软件过程是为了实现一个或者多个事先定义的目标而建立起来的一组实践的集合。软件过程有广义和窄义之分,广义的软件过程涉及三个维度,技术、人员以及流程,窄义的软件过程就是一组有先后顺序的活动,即流程。其中,流程即是这三个维度中的一维,更重要的,它是连接技术和人员的粘合剂,将技术、人员及流程三者融为整体,软件过程才能在软件开发中真正起到指导作用。窄义的软件过程则只单纯涉及软件开发流程。
软件过程与软件生命周期紧密相关,一个软件过程既可以覆盖从需求到交付的完整的软件生命周期,也可以仅仅包括其中某些特定开发阶段。例如,一个实现过程就只包括详细设计、编码、代码评审、编译以及单元测试等更为细小的开发步骤。甚至,为了确保代码评审工作的质量,也可以进一步定义、管理和改进代码评审过程。
软件过程管理涉及对软件开发过程的管理包括软件过程的建立、执行、监控、评估以及改进等活动。软件过程管理最重要的内容就是从众多企业的软件开发活动的经验教训中总结形成的可供参考的模型。最著名的软件过程管理参考模型是能力成熟度模型CMM以及其后续的集成模型CMMI[34]。
\subsection{软件质量保证}
软件是一种人工制品为确保其质量需要通过软件质量保证Software Quality Assurance, SQA机制持续对软件开发过程进行监控同时采用多种方法确保各种软件开发制品的质量。根据ISO/IEC 15504标准\footnote{https://www.iso.org/standard/38932.html}的定义,软件质量保证是一种独立的支持性过程,其目的是确保所有的软件开发制品、活动和过程都遵循预定义的计划和标准。软件质量保证是一个完整的体系,以软件质量标准为参照,以所采用的软件开发过程(如瀑布模型或敏捷开发过程)为基础,贯穿整个软件开发过程(包括需求定义、软件设计、编码、测试、集成和发布等),同时结合过程管理、版本与变更管理、测试、评审、程序分析与形式化验证等多种手段。
\subsubsection{软件质量标准}
目前已经存在一系列标准用于监控和评估软件生产过程过程以确保软件的质量ISO/IEC 15504其第一个版本专注于软件开发过程后来扩展到涵盖软件业务中的所有相关流程例如项目管理配置管理质量保证等是成熟度模型的参考模型评估者可以根据模型在评估期间收集证据全面确定所开发产品软件系统和IT服务的能力。其更新版本是ISO/IEC 33000\footnote{https://www.iso.org/standard/54175.html}。其它质量标准还包括ISO/IEC 25000\footnote{https://www.iso.org/standard/64764.html}、ISO/IEC/IEEE 29119\footnote{https://www.iso.org/standard/45142.html}等。
\subsubsection{形式化规约}
除了采用工程方法来组织、管理软件的开发过程,并根据标准检验过程的正确性外。还有一类工作就是深入探讨程序和程序开发过程的规律,建立严密的理论,以其用来指导软件开发实践,这类工作推动了形式化方法的深入研究,其目标是以严格的数学推演为基础,通过对系统的形式规约、验证和逐步精化来构造并实现软件,从而提高软件设计的可靠性和鲁棒性。通过对系统的形式规约、验证和逐步精化来构造并实现软件。其中,形式规约是使用形式语言构建所开发的软件系统的规约,对应软件生命周期不同阶段的制品,刻画系统不同抽象层次的模型和性质。形式化开发就是构造并证明形式规约之间的等价转换和精化关系,以系统的形式模型为指导,通过逐步精化,最后开发出满足需要的系统,也称为构造即正确(Correct by Construction)的开发。
特别值得一提的是南京大学徐家福教授领导的科研团队它从规约到实现开发了多个软件自动化系统。中科院唐稚松院士领导的科研团队提出了XYZ系统是由一个时序逻辑语言XYZ/E以及围绕该语言的一组软件工具组成XYZ/E第一个可执行的时序逻辑语言[35]。中科院董韫美领导的科研团队提出了基于复用的文法推断方法提出一种新的递归函数理论研究开发了支持系统MLIRF[36]。
\subsection{软件工程工具}
软件工程工具是辅助软件开发人员、运维人员、管理人员等不同软件开发过程参与者的各类软件产品的总称。软件开发工具软件工程工具从软件工程概念早期的编程工具、软件过程管理工具以及软件度量工具,逐步发展为服务于软件整个生命周期的整套工具链,并且在不同的软件工程环节存在多种可供选择的软件工程工具产品。丰富的软件工程工具一方面为软件开发人员提供了更加高效便捷的开发方法和能力,另一方面也给增加了软件开发人员的学习成本。同时,面向软件工程过程不同环节的软件工程工具,也促进了软件工程的领域细分,不同的软件工程工具对工具使用者的不同技能要求,使得软件工程技能培训和学习更加细化和专业化。
根据软件工程工具所服务的人员角色不同,可将软件工程工具分为软件开发工具、软件运维工具、软件开发管理工具等。后续将对各类软件工程工具的历史和现状进行简要回顾。
\subsubsection{软件开发工具}
早期的软件开发工具仅限于汇编器和编译器。20世纪五六十年代随着Fortran、Basic等高级语言的出现计算机程序逐步脱离了面向特定硬件系统的束缚更加接近于自然语言而易于开发人员书写。开发人员使用文本编辑工具编写代码后使用代码解释或编译工具将源代码转换为操作系统可以识别的代码进而实现预期的程序行为。广义上来说文本编辑器、汇编器、编译器都可以看作最原始的软件开发工具。
随着软件开发过程的成熟以及软件开发技术的发展,软件开发工具开始在基本的代码编辑和编译功能基础上提供代码元素高亮、即时语法检查和提示、调试等辅助功能,同时针对编码之外的软件开发活动的支持工具也不断涌现,主要包括以下几种类型。
\begin{itemize}
\item 分析和设计建模工具在规范化的建模语言基础上通过图形化的建模工具支持软件的需求分析和设计建模例如广泛使用的ER模型和UML建模工具等
\item 测试工具:针对单元测试、集成测试、性能测试等不同种类的测试所提供的测试用例生成、测试环境模拟、测试执行与测试结果分析等方面的工具支持;
\item 分析和验证工具:针对软件代码、模型等软件开发制品进行自动化分析和验证,发现潜在的质量问题或确认所期望的属性,例如各种代码缺陷检查工具、形式化验证工具等;
\item 逆向分析和度量工具:针对源代码或二进制代码进行逆向分析以恢复软件的高层视图从而辅助理解,或者度量代码的各种属性以获得关于代码质量的信息。
\end{itemize}
单一的软件开发工具很多时候由于缺少必要的上下文信息或与其他工具的联系而很难使用。因此基于多种软件开发工具形成的集成开发环境IDE逐渐发展起来。20世纪80年代通用编程语言Ada带有自己的编程支持环境APSE提供了编辑界面、编译器、测试器、连接加载器等功能模块将集成开发环境提升到一个新的阶段。此后微软Microsoft、宝蓝Borland等软件公司相继开发出各自的开发环境用于支持相应编程语言的开发与调试。IDE的出现为软件开发人员在开发过程中集中完成软件开发任务提供了统一的环境也为后续进一步扩展新的软件工程工具奠定了基础。例如1987年宝蓝公司推出的Turbo C开发环境在字符界面上提供了灵活的代码编写和调试环境使得开发人员能够一站式完成程序编写、测试和调试。1991年为了适应微软公司的视窗Windows操作系统界面风格宝蓝公司又推出Borland C++并在90年代后期推出Borland C++ Builder提升了集成开发环境的易用性和代码编译链接的效率。在这个工具的升级过程中不仅需要适应C/C++语言标准的变化、操作系统的变化还考虑了开发人员的易用性需求通过可视化的窗体设计器、对象观察器等可视化元素加入到开发环境中推出了VCL构件库引领了快速应用程序开发RAD开发方法大大降低了开发Windows应用程序的难度。
%从早期的基于字符界面的开发工具到以视窗为特征的图形界面集成开发环境,从软件企业开发的商用集成开发环境到开源社区主导的开放式插件式集成开发环境,软件开发工具随着程序语言、开发技术、开发过程的变化日益复杂。
%随着软件日益复杂和开发过程的不断演进,仅提供代码编辑、调试能力不足以支撑丰富的软件工程活动。
开放式架构的开源集成开发环境以插件的形式提供各类辅助支持包括在开发环境中提供各类代码静态扫描功能、代码重构功能、代码自动补全和框架自动生成功能等大大扩展了集成开发环境的能力范围使之能服务于不同的开发过程活动。例如最初由IBM公司主导开发的Eclipse在2001年开源转入非盈利组织Eclipse基金会管理后开源社区的大量开发者为其开发了众多实用的功能进而衍生出了MyEclipse、IBM Rational Software Architect等多种工具软件服务于不同层次和复杂程度的开发需求。
特别值得一提的是,在中国有一项重大工程就是青鸟工程[37],由北京大学牵头,从“六五”开始一直到“十五”,经过很长时间的科技攻关,这项工程有很多单位参加, 在“七五”期间有11个单位 100多位科技成员“八五”期间有22个单位338位科技成员遍布了全国各地。青鸟工程的目标是以实用的软件工程技术为依托建立软件产业基础推行软件工程化、工业化生产技术和模式提供软件工业化生产手段和设备形成规模经济所需的人才储备、技术储备、产品储备。它从基础研究到实用化、产品化技术的研究到工程化、工业化生产技术的研究。它的关键是创新这个创新不仅是概念的创新还是机制的创新和技术的创新目的就是使得手工作坊式通过工业化生产技术和工程化开发方法设计支撑环境与工具构建标准规范体系提出了青鸟软件生产线模式实现作坊式的开发方式到工业化生产方式变革这是中国软件产业建设的共性和基础性工作。
\subsubsection{软件运维工具}
软件的运行和维护是软件交付后的必要环节。在以桌面应用为主的上世纪90年代以前软件产品要么以商业现货commercial-off-the-shelf形式提供给最终用户要么以商用服务项目的形式在客户现场on-site提供支持。此时软件的运维主要是软件日志的收集与分析。通常只能通过现场日志的分析获知软件的可能问题进而在开发环境中进一步测试、验证、修改软件以修复相关问题。在这种模式下软件运维工具往往并不受重视并且通常是融合在软件开发工具中的即需要通过软件开发过程中写入必要的日志信息才能实现必要的运行维护工作。随着互联网应用和应用的服务化进程的开启21世纪以来服务化和云化的软件使得软件运维从客户端现场支持逐步转向后端、云端。此时的软件运行具有在线动态地特性不仅需要运行时的日志记录与分析还需要能快速响应特定的运行问题并快速给出维护方案、上线修复的软件产品。软件运维从简单的运行日志分析和调错逐步向实时监控、快速响应的反向发展这也带来了开发运维一体化DevOps的兴起。由此软件运维工具范围迅速扩大形成了涵盖开发、构建、测试、集成及交付、容器平台等个子领域的工具集。例如自动化构建是持续集成的重要支撑支持持续集成的工具包括开源工具Jenkins、商用工具Bamboo以及商用开源版本并存的Travis等。这些工具的特性分别适应特定的应用群体或用户运维人员可实现多种运维工具的按需选择。
\subsubsection{软件管理工具}
软件管理工具特指在软件开发过程中使用的不直接产出软件中间制品或最终制品的辅助工具。软件管理工具主要面向软件开发管理人员同时也服务于软件开发活动所有参与者。这些辅助工具包括项目进度管理工具如MS Project、软件版本管理工具如SVN、Git、ClearCase、在线细粒度任务安排和看板工具等对软件开发过程、制品进行。从软件工程概念提出依赖采用工程化的管理手段使得软件的开发过程变得可见、可控、可度量、可预测是这些工具的终极目标之一。这些工具随着软件工程学科发展和研究内容的变化而不断改进新的工具不断涌现体现了软件工程学科的活力。例如随着敏捷方法被软件工程实践逐步接受以软件工具形式出现的看板软件也发展起来开始作为传统的物理看板的补充在异地分布式团队等场景中广泛地使用。尽管目前此类软件仍然存在诸如易用性、可配置性等缺陷但作为新兴的软件工程工具若能通过触摸交互式高分辨率显示等技术改进实现随时随地的交互那么对精准高效地管理团队内部人员的开发进度、协调团队交互沟通都会具有非常重要的价值应用前景非常广阔。可见软件管理工具仍然是提升软件开发工程化能力的重要工具集。
\section{软件需求工程}
当软件变得复杂,需要对软件的需求进行分析,以此构造综合性的问题求解方案,当软件系统变得更加复杂,则需要有一整套的过程和相应技术,指导和帮助软件开发人员系统化地进行用户的需求识别和分析,确定软件能力需求,从而构造问题场景的整体的解决方案。从而出现独立的研究方向:需求工程[38]。需求工程有三个关注点:环境(可改进点)、期望需求(关注的改进方面)、和软件系统需求(可实现性)。
简单说,需求工程就是:现实世界中存在需要解决的问题、可改进的地方、或者可能蕴含的机会等,然后在圈定的范围内认知并明确刻画出想要解决的问题,最后依据当前可行的信息技术手段,设计出问题求解的方案,并认证该解决方案的可行性和有效性。因此需求工程的主要任务就是观察现实世界机会、识别和定位现实需求、分析和建模软件需求、验证和管理软件需求等。
由于需求工程的出发点是观察现实世界并进行问题识别,根据现实世界问题识别的不同角度,出现了不同的需求工程方法,主要的需求工程方法包括:面向目标的方法[39]、面向主体和意图的方法 [40]、面向情景的方法[41]、问题框架方法[42]、环境建模方法[43]等。这些方法的特点和需求工程技术见表1所列。
\begin{table}
\centering
\footnotesize
\caption*{表1. 代表性需求工程方法}
\begin{tabular}{|p{0.1\textwidth}<{\centering}|p{0.2\textwidth}<{\centering}|p{0.28\textwidth}<{\centering}|p{0.28\textwidth}<{\centering}|}%
\hline
方法& 问题视角& 软件需求获取手段& 软件需求获取手段\\
\hline
面向目标的方法& 现实世界中存在新的需要达成的业务目标& \makecell[l]{ • 识别高层目标\\
• 自顶向下,按照业务目标\\ \protect\quad 实现策略进行目标分解,\\ \protect\quad 直到获得可操作目标}
& \makecell[l]{• 可操作目标的可实现性分析\\
• 自底向上的逐层目标可满足\\ \protect\quad 性分析\\
• 目标冲突的检测和协商}
\\
\hline
面向主体和意图的方法& 现实世界存在需要维系的自治个体/组织的关系& \makecell[l]{• 个体/组织间依赖关系识别\\
• 个体/组织策略的目标建模\\
• 个体/组织的反依赖关系以\\ \protect\quad 及反依赖关系应对策略
}& \makecell[l]{• 依赖关系的可满足性和鲁棒\\ \protect\quad 性分析\\
• 依赖路径的脆弱性分析\\
• 反依赖关系的防御
}\\
\hline
面向情景的方法& 现实世界中的业务流程需要自动化支撑& \makecell[l]{• 现实场景抽象和模。\\
• 现实场景模型脆弱点分析\\ \protect\quad 和改进点确定,如活动改\\ \protect\quad 进和流程改进。\\
• 改进策略确定
}& \makecell[l]{• 场景流合理性分析\\
• 场景流可行性分析\\
• 场景流资源/环境依赖性\\ \protect\quad 分析\\
• 场景流最优化分析
}\\
\hline
问题框架方法& 软件处于环境中,软件的能力需求由需要和环境进行的交互决定& \makecell[l]{• 识别软件上下文(环境)\\
• 抽象环境实体的特征\\
• 在环境实体上确定用户\\ \protect\quad 需求,以此确定软件与环\\ \protect\quad 境实体的交互\\
• 根据交互特征识别问题\\ \protect\quad 框架
}& \makecell[l]{• 构建上下文图。环境实体\\ \protect\quad 识别\\
• 构建问题图。基环境实体于\\ \protect\quad 确定用户需求,系统/环境\\ \protect\quad 交互识别\\
• 进行问题投影。子问题识\\ \protect\quad 别,基本问题框架匹配
}\\
\hline
环境建模方法& 软件处于环境中,环境的行为模型和意图确定软件的功能和非功能需求& \makecell[l]{• 识别软件的上下文(环境)\\
• 环境模型已存在,继承环\\ \protect\quad 境实体模型,否则构建环\\ \protect\quad 境实体模型\\
• 按业务场景定义用户需求\\
• 确定系统和环境的交互,\\ \protect\quad 根据需求约束和环境实体\\ \protect\quad 约束,确定系统能力,包\\ \protect\quad 含功能和非功能性
}& \makecell[l]{• 特定领域的环境建模\\
• 业务场景定义及其环境\\ \protect\quad 约束叠加\\
• 基于业务场景逻辑的系统\\ \protect\quad 需求识别
}\\
\hline
\end{tabular}
\end{table}
\section{领域工程}
领域工程\footnote{https://en.wikipedia.org/wiki/Domain\_engineering},是支持软件开发中全面系统化复用领域知识的整个过程。领域工程的出发点是,大多数软件系统都不是全新的系统,领域工程可以通过使用同领域相似系统的模型和代码,提高新软件的开发效率额和质量,降低成本。因此,领域工程面向特定领域装煮鱼捕获和收集可复用的软件制品,以便在与之相对的应用工程中复用。与应用工程相对应,领域工程也分为分析、设计和实现三个阶段。
领域分析侧重于识别和定义领域,并生成领域模型。面向特征的领域分析方法[44]是具有代表性的领域分析方法。领域分析的来源是某领域过去产生的制品,包括现有系统及其如设计文档,需求文档和用户手册等制品。领域分析的目标是将根据已知的领域知识进行扩展,通过领域特征建模,识别领域的公共特征,以及存在的差异性,从而支持领域需求的可配置性。领域设计根据领域分析阶段生成的领域模型,产生领域中所有系统都能符合的通用系统架构模式,并确定模式的范围以及与模式相关的上下文,以适当限定架构适用的范围。最后领域实现是创建为能有效生成本领域客户化软件使用的过程和工具。
最早的代表性领域工程是产品线工程,以产品特征建模为基础,又称面向特征复用 [44]FORM通过领域工程过程支持开发可复用的体系结构和构件并支持使用领域工程生成的领域制品开发应用程序。 FORM首先分析出领域特定领域中应用程序在服务、操作环境、领域技术和实现技术等方面共性的或者差异性的功能特征。这个分析过程构建出来的模型被称为特征模型。 该模型则可用于定义参数化参考体系结构和在实际应用程序开发时可实例化的适当的可复用构件。
特别一提,我国陆汝钤院士提出并建立基于领域建模的软件工程[45],采用知识工程方法建模领域知识,并支持全过程领域模型驱动的软件开发。
\section{结束语}
随着信息技术的飞速发展,软件系统无处不在,其应用形态呈现出泛在化、社会化、情境化、智能化等特征,软件正逐步成为人类社会不可或缺的基础设施。软件工程方法和技术的进步支撑了整个的软件应用的展开,体现在软件系统的规模越来越大,所解决的问题越来越复杂、交互对象越来越多样,人们寄予越来越高的可靠性要求。现在,人机物融合应用模式的不断深入,“泛在系统”和“软件定义”也成为呼之欲出的着力点。这既孕育了软件工程学科的新的增长点,也给软件工程方法和技术带来了新的挑战,需要有新的软件工程方法和技术支撑。
早期代表性的研究工作包括,
2000年开始在互联网发展的环境下提出了并率先开展了研究面向互联网计算的新型软件——网构软件这是在面对互联网的发展而提出来的一个新型的软件开发环境。网构软件被列为国家科技计划的重要方向。从2002年起连续获得三期973计划项目支持在国际上也产生了广泛的学术影响。
\section{参考文献}
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[1] P. Naur and B. Randell, eds., Software Engineering: Report on a Conference Sponsored by the NATO Science Committee, Garmisch, Germany, 7th to 11th October 1968, NATO Scientific Affairs Div., Jan. 1969
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[2] E. W. Dijkstra, The Humble Programmer, Communication of ACM 15(10): 859-866, 1972
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[3] F. P. Brooks, The Mythical Man-Month, Addison-Wesley, 1975
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[4] F. P. Brooks, No Silver Bullet: Essence and Accidents of Software Engineering, Computer, 20(4): 10-19, 1987
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[5] P. Laplante, What Every Engineering Should Know about Software Engineering, Boca Raton: CRC, 2007, ISBN 978-0-8493-7228-5
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[6] Systems and software engineering -Vocabulary, ISO/IEC/IEEE std 24765:2010(E), 2010.
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[7] IEEE Standard Glossary of Software Engineering Terminology, IEEE std 610.12-1990, 1990.
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[8] Ian Sommerville, Software Engineering, Harlow, England: Pearson Education, 1982.
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[9] R. S. Pressman, Software Engineering: A Practitioners Approach, Mc Grew Hill, 2005
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[10] C. Ghezzi, M. Jazayeri and D. Mandrioli, Fundamentals of Software Engineering, Prentice-Hall, 2002
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[11] H. van Vliet, Software Engineering: Principles and Practice, John Wiley \& Sons, Ltd., 2000
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[12] Dines Bjorner著刘伯超、向剑文等译软件工程卷1-卷3清华大学出版社2010年
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[13] M. H. Hamilton, What the Errors Tell Us, Software Engineerings 50th Anniversary, IEEE Software, September/October 2018, 32-37
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[14] M. H. Hamilton and W. R. Hackler, Universal Systems Language: Lessons Learned from Apollo, IEEE Computer, Dec. 2008, 34-43
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[15] P. Checkland and J. Scholes, Soft Systems Methodology in Action, Wiley, 1990
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[16] E. Yourdon and L. Constantine, Structured Design: Fundamentals of a Discipline of Computer Program and System Design, Prentice-Hall, 1979
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[17] E. Yourdon, Modern Structured Analysis, Yourdon Press, 1989
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[18] M. Jackson, Principle of Program Design, Academic Press, 1975
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[19] M. Jackson, System Development, Prentice-Hall International, 1983
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[20] T. DeMarco, Structured Analysis and System Specification, Prentice Hall, 1979
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[21] G. Booch, R. A. Maksimchuk, M. W. Engle, J. Conallen, B. J. Young and K. A. Houston, Object-Oriented Analysis and Design with Applications (2nd Edition), Addison-Wesley, 1993
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[22] J. Rumbaugh, M. Blaha, W. Premerlani, F. Eddy and W. Lorensen, Object-Oriented Modeling and Design, Prentice Hall International, 1991
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[23] I. Jacobson, Object Oriented Software Engineering: A Use Case Driven Approach, Addison-Wesley Professional, 1992
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[24] I. Jacobson, G. Booch and J. Rumbaugh, The Unified Software Development Process, Addison Wesley Longman, 1998
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[25] P. Kruchten, The Rational Unified Process: An Introduction, Addison-Wesley, 2004
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[26] E. Gamma, R. Helm, R. Johnson and J. Vlissides, Design Patterns, Addison-Wesley Professional, 1994
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[27] W. Miller and D. L. Spooner, Automatic Generation of Floating-Point Test Data, IEEE Transactions on Software Engineering. SE-2 (3): 223226, 1976
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[28] S. Xanthakis, C. Ellis, C. Skourlas, A. Le Gall, S. Katsikas and K. Karapoulios, Application of genetic algorithms to software testing, Proceedings of the 5th International Conference on Software Engineering and its Applications: 625636, 1992
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[29] M. Harman and B. F. Jones, Search-based software engineering, Information and Software Technology. 43 (14): 833839, 2001
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[30] C. Larman and V. R. Basili, Iterative and Incremental Developments: A Brief History, IEEE Computer, 36(3): 47-56, 2003
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[31] T. Gilb, Evolutionary development, ACM SIGSOFT Software Engineering Notes. 6 (2): 17, 1981
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[32] E. A. Edmonds, A Process for the Development of Software for Nontechnical Users as an Adaptive System, General Systems, 19: 21518, 1974
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[33] J. Martin, Rapid Application Development, Macmillan, 1991.
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[34] M. B. Chrissis, M. Konrad and S. Shrum. CMMI: Guidelines for Process Integration and Product Improvement, Addison-Wesley Professional, 2003.
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[35] 徐家福吕建软件语言及其实现科学出版社2000
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[36] 陈海明,董韫美. 一个支持规约获取的形式规约语言.《计算机学报》第25卷第5期, 2002年5月, pp.459-466
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[37] 杨芙清中国软件工程五十周年纪念院士论坛报告2018年11月
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[38] K. Pohll, Requirements Engineering: Fundamentals, Principles and Techniques, Springer-Verlag, 2010.
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[39] A. van Lamsweerde, Requirements Engineering: From System Goals to UML Models to Software Specification, John Wiley, 2009
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[40] E. Yu, Social Modeling for Requirements Engineering, MIT Press, 2010
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[41] A. G. Sutcliffe, Scenario-Based Requirements Engineering, Proceedings of IEEE International Requirements Engineering Conference (RE2003): 320-329, 2003
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[42] M. Jackson, Problem Frames: Analyzing and Structuring Software Development Problems, Addison-Wesley, 2001
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[43] Z. Jin, Environment Modelling based Requirements Engineering for Software Intensive Systems, Elsevier, Morgan Kaufmann Publisher, 2017
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[44] K. C. Kang, S. Kim, J. Lee, K. Kim, E. Shin and M. Huh, FORM: A feature-oriented reuse method with domain-specific reference architectures, Annals of Software Engineering, 5: 143-168, 1998
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[45] R. Lu and Z. Jin, Domain Modeling based Software Engineering, Kluwer Academic Publishers, 2000.
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[p1] Ruben Prieto-Diaz, James M.Neighbors. Module interconnection languages. Journal of Systems and Software, Volume 6, Issue 4, November 1986, Pages 307-334.
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[p2] 杨芙清 . 1999. 软件复用与软件构件技术[J]. 电子学报, 27(2):6875.
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[p3] Mcllroy D. Mass produced software components. 1968 NATO conf. on Software Engineering. PP. 138-155
\noindent
\hangafter=1
\setlength{\hangindent}{2em}
[p4] 张效祥. 2005. 计算机科学技术百科全书[M].[S.l.]: 清华大学出版社有限公司.