软件工程基础知识
- 5.1 软件工程
- 5.1.1 软件工程定义
- 5.1.2 软件过程模型
- 5.1.3 敏捷模型
- 敏捷开发的特点
- 敏捷方法的核心思想
- 主要敏捷方法简介
- 5.1.4 统一过程模型 (RUP)
- RUP的生命周期
- RUP中的核心概念
- RUP的特点
- 5.1.5 软件能力成熟度模型
- 5.2 需求工程
- 5.2.1 需求获取
- 需求获取的基本步骤
- 需求获取方法
- 5.2.2 需求变更
- 变更控制过程
- 变更控制委员会
- 5.2.3 需求追踪
- 5.3 系统分析与设计
- 5.3.1 结构化方法
- 结构化分析
- 结构化设计
- 结构化编程
- 数据库设计
- 5.3.2 面向对象方法
- 面向对象分析
- 面向对象设计
- 面向对象编程
- 数据持久化与数据库
- 5.4 软件测试
- 5.4.1 测试方法
- 5.4.2 测试阶段
- 5.5 净室软件工程
- 5.5.1 理论基础
- 5.5.2 技术手段
- 5.5.3 应用与缺点
- 5.6 基于构件的软件工程
- 5.6.1 构件和构件模型
- 5.6.2 CBSE过程
- 5.6.3 构件组装
- 5.7 软件项目管理
- 5.7.1 项目管理概述
- 5.7.2 软件进度管理
- 5.7.3 软件配置管理
- 5.7.4 软件质量管理
- 软件质量保证
- 软件质量认证
- 5.7.5 软件风险管理
5.1 软件工程
5.1.1 软件工程定义
软件工程过程是指为获得软件产品,在软件工具的支持下由软件工程师完成的一系列软件工程活动,包括以下4个方面。
- P(Plan)——软件规格说明。规定软件的功能及其运行时的限制。
- D(Do)——软件开发。开发出满足规格说明的软件。
- C(Check)——软件确认。确认开发的软件能够满足用户的需求。
- A(Action)——软件演进。软件在运行过程中不断改进以满足客户新的需求。
5.1.2 软件过程模型
软件要经历从需求分析、软件设计、软件开发、运行维护,直至被淘汰这样的全过程,这个全过程称为软件的生命周期。
- 瀑布模型
已经有了蓝图,按部就班地去完成,中间客户的需求根本不会改变。 - 原型化模型
这个就比较惯着客户了,先给出一个小样,不断地去修改完善,有时候也不会完善了,就是给客户一个灵感来源。
- 螺旋模型
螺旋模型 (Spiral Model) 是在快速原型的基础上扩展而成。不断地修修补补。
5.1.3 敏捷模型
敏捷开发的特点
敏捷型方法是“适应性” (adaptive) 而非“预设性” (predictive)
敏捷型方法是“面向人的” (People-oriented) 而非“面向过程的” (Process-oriented)
敏捷方法的核心思想
- 敏捷方法是适应变化的方法,强调利用变化来发展和完善自身,与传统方法的可预测性不同。
- 敏捷方法以人为核心,注重充分发挥人的特性,而不是过于强调过程的限制。
- 敏捷方法采用迭代增量式的开发过程,通过制订版本发行计划和小型化发布版本来满足客户需求。每个发行版都在前一版本的基础上进行功能需求扩充。
主要敏捷方法简介
- 极限编程 (Extreme Programming,XP):强调快速适应变化,注重团队协作和高质量软件交付。
- 水晶系列方法:以阶段性发布为特点,注重需求的不断修订和完善,迭代开发。
- Scrum:基于迭代、循序渐进的敏捷开发框架,强调团队协作、适应变化和持续交付价值。
- 特征驱动开发方法 (Feature Driven Development,FDD):侧重于对软件需求的分析和设计,通过特征列表来组织和规划开发过程。
5.1.4 统一过程模型 (RUP)
RUP的生命周期
RUP的软件开发生命周期是一个二维模型,包括9个核心工作流。这些核心工作流包括:
- 业务建模:理解待开发系统所在机构及其商业运作,并评估待开发系统对机构的影响。
- 需求:定义系统功能和用户界面,使客户和开发人员理解系统需求,为项目预算和计划提供基础。
- 分析与设计:将需求分析结果转化为分析与设计模型。
- 实现:将设计模型转换为实现结果,对开发的代码进行单元测试,并将不同模块集成为可执行系统。
- 测试:检查子系统之间的交互和集成,验证是否正确实现所有需求,并对发现的质量缺陷提出改进建议。
- 部署:打包、分发和安装软件,升级旧系统;培训用户和销售人员,并提供技术支持。
- 配置与变更管理:跟踪和维护系统开发过程中产生的所有制品的完整性和一致性。
- 项目管理:为软件开发项目提供计划、人员分配、执行和监控的指导,为风险管理提供框架。
- 环境:为软件开发机构提供过程管理和工具支持的软件开发环境。
RUP将软件开发生命周期划分为多个循环,每个循环生成一个新版本的产品。每个循环由4个连续的阶段组成:
- 初始阶段:定义最终产品视图和业务模型,并确定系统范围。
- 细化阶段:设计和确定系统的体系结构,制定工作计划和资源要求。
- 构造阶段:构建产品并进一步演化需求、体系结构和计划,直至提交产品。
- 移交阶段:将产品交付给用户使用。
每个阶段由一个或多个连续的迭代组成,迭代不是重复做相同的事情,而是针对不同用例的细化和实现。每个迭代都是一个完整的开发过程,需要根据当前阶段和上次迭代的结果适当裁剪核心工作流中的行为。
在每个阶段结束前,有一个里程碑评估工作进展。如果未能通过里程碑评估,决策者需要决定是取消项目还是继续该阶段的工作。
RUP中的核心概念
RUP中定义了一些核心概念,这些概念对于理解RUP方法非常重要:
- 角色(Role):描述某个人或小组在软件开发过程中的行为和责任。RUP预定义了多种角色,如体系结构师、设计人员、实现人员、测试员和配置管理人员,并详细说明了每个角色的工作和责任。
- 活动(Activity):是具有明确目的的独立工作单元,描述了软件开发过程中的具体行动。
- 制品(Artifact):指活动生成、创建或修改的信息,也可翻译为产品或工件。制品包括各种文档、模型和代码等。
- 工作流(Workflow):描述了有意义的连续活动序列,每个工作流产生有价值的产品,并展示了角色之间的关系。
除了这四个核心概念外,RUP还涉及其他基本概念,如工具教程(Tool Mentor)、检查点(Checkpoints)、模板(Template)和报告(Report)等。这些概念之间的关系可以用类图来描述,帮助理解RUP方法的运作方式。 RUP 2003版本对这些概念有更详细的解释,有助于理解这些概念在软件开发过程中的实际应用。
RUP的特点
RUP(Rational Unified Process)是一种用例驱动的、以体系结构为中心的、迭代和增量的软件开发过程。它具有以下特点:
- 用例驱动:RUP中的开发活动都以用例作为驱动,包括需求分析、设计、实现和测试等。通过用例来定义和描述系统的功能需求,从而指导开发过程。
- 以体系结构为中心:RUP将开发活动围绕软件体系结构展开。软件体系结构是软件设计过程中的一个重要层次,涉及系统的总体组织、通信协议、数据存取等方面的设计。RUP强调在设计阶段独立于具体的编程语言,关注系统整体的组织和控制。
- 迭代与增量:RUP采用迭代和增量的方式进行软件开发。项目被分为多个迭代过程,每次迭代只关注部分需求,进行分析、设计、实现、测试和部署等活动。每次迭代都在已完成部分的基础上增加新功能,直至最终完成整个项目。这种方式有助于早期处理风险、指导开发、应对需求变更、提供可运行系统和提高开发效率。
通过上述特点,RUP能够更灵活地应对需求变化和风险管理,提高开发效率和项目成功的信心。同时,它也强调了用例驱动、体系结构设计和迭代增量开发这些在软件开发中的重要原则。
5.1.5 软件能力成熟度模型
软件能力成熟度模型(CMM)和软件能力成熟度模型集成(CMMI)旨在提高软件生产率和质量。CMMI是基于CMM开发而来的,包括5个成熟度级别,共18个关键过程域,52个过程目标和3168种关键时间。不同级别代表着企业在软件开发过程中的成熟度水平,从初始级到优化级。CMMI可以指导软件开发过程的改进和评估。
5.2 需求工程
需求工程是软件工程领域中的一个重要子领域,其目标是通过系统地描述待开发系统及其行为特征和相关约束,从而确定客户需求,定义设想中系统的所有外部特征。软件需求的定义包括了业务需求、用户需求和功能需求(包括非功能需求)。在经典的瀑布软件过程模型中,将需求分析作为软件开发的第1个阶段,明确指出该阶段的输出成果为用户原始需求说明书和软件需求描述规约。软件需求开发的最终文档经过评审批准后,则定义了开发工作的需求基线,构筑了计划产品功能需求和非功能需求的一个约定。需求管理是一个对系统需求变更、了解和控制的过程,其主要活动包括控制对需求基线的变动、保持项目计划与需求一致、控制单个需求和需求文档的版本情况、管理需求和联系链,以及跟踪基线中的需求状态。
5.2.1 需求获取
需求获取的基本步骤
需求获取是软件开发过程中非常重要的一步,下面是需求获取的基本步骤:
- 开发高层的业务模型:了解目标系统的应用领域,并建立业务模型来描述用户的业务过程,确定初始需求。
- 定义项目范围和高层需求:在项目开始之前,与所有涉众共同确定项目范围和高层需求,描述系统边界和参与者关系。
- 识别用户角色和用户代表:确定所有涉众,并选出每类涉众的用户代表与其一起工作,包括传统用户、客户、测试人员、维护人员、市场人员等。
- 获取具体的需求:针对每个涉众,获取具体、完整和详细的需求,确保对系统的需求理解准确。
- 确定目标系统的业务工作流:具体到待开发的应用系统,确定系统的业务工作流和主要的业务规则,采取多种方法获取所需信息。
- 需求整理与总结:整理和总结获取的需求资料,确定软件系统的综合要求,包括功能需求、性能需求、环境需求、可靠性需求、安全保密需求、用户界面需求等。
需求获取的目标是明确“做什么”,而不是“怎样做”,以确保开发出满足用户需求的软件系统。在整个过程中,与用户和其他利益攸关方的密切合作和沟通至关重要,以避免理解错误或遗漏的需求,确保项目的成功交付。
需求获取方法
需求获取是软件开发中非常重要的一步,不同类型的软件项目需要采用不同的需求获取方法。常见的需求获取方法包括用户面谈、需求专题讨论会、问卷调查、现场观察、原型化方法和头脑风暴法。
- 用户面谈是最常见也是最有效的需求获取方法,通过与用户直接交流,能够深入理解用户需求。在进行面谈前需要做好充分的准备,并将收集到的信息转化为适当的模型和文档。
- 需求专题讨论会是通过集中相关涉众进行集体讨论的方式,可以在短时间内达成共识并统一意见。有助于建立高效团队、揭露和解决问题,并快速产生初步的系统定义。
- 问卷调查可用于确认假设和收集统计倾向数据,但在设计问卷时需注意问题不能事先决定,问题背后的假设对答案造成偏颇。
- 现场观察是通过观察用户实际执行业务的过程来全面了解需求细节,可以进行手工操作或在原有业务系统上执行。
- 原型化方法适用于需求不确定的情况,通过开发系统原型并与用户多次迭代反馈解决需求不确定性问题,特别是在人机交互界面等方面。
- 头脑风暴法适用于新业务拓展的软件项目,通过多人发散思维产生新观点和设想,确定具体需求。
根据具体项目需求和情况,软件开发团队可以选择合适的需求获取方法或结合多种方法进行需求获取。
5.2.2 需求变更
需求变更在软件开发中是常见的,但需要控制变更的范围和影响。如果变更不加控制地持续进行,会导致项目混乱、进度延误和质量问题。为了控制需求变更,以下几点是重要的原则:
- 评估变更:对已提出的需求变更进行仔细评估,判断其合理性和影响范围。只有经过评估后的合理变更才应该被采纳。
- 选择决策者:在决定是否采纳变更时,选择合适的人员来进行判定。这些人员需要具备相关领域的知识和经验,能够全面评估变更的影响。
- 及时通知:变更应及时通知所有相关人员,包括开发团队、测试团队和相关的利益相关者。这样可以确保所有人了解变更,并根据需要做出相应调整。
- 控制过程:需求变更应按照一定的程序进行,确保变更过程被控制和记录。这可以包括变更请求的提交、评审和批准流程,以及变更状态的跟踪和管理。
通过以上控制措施,软件开发组织可以更好地管理需求变更,确保项目的进展和质量。同时,精确描述软件需求并进行适当的评估和控制也是重要的原则。
变更控制过程
变更控制委员会
变更控制委员会(CCB)是由项目中涉及到的各方共同组成的决策机构,负责裁定接受哪些变更。CCB应该有一个总则,用于描述其目的、授权范围、成员构成、做出决策的过程及操作步骤。CCB应包括项目所有者代表、用户代表、实施方的决策人员等。
在决策变更时,CCB需要考虑变更的利弊并做出合理的决定。制定决策过程的描述应包括必须到会的人数或做出有效决定必须出席的人数、决策的方法、主席是否可以否决该集体的决定等。一旦做出决策,应指派相应的人员及时更新请求的状态。
当项目接受重要的需求变更时,需要重新协商约定。协商的内容可能包括推迟交货时间、要求增加人手、推迟实现较低优先级的需求,或者质量上进行折中。
综上所述,CCB是一个重要的决策机构,需要根据总则和操作步骤来制定决策、交流情况,并重新协商约定。通过CCB的管理,可以更好地控制需求变更,确保项目的进展和质量。
5.2.3 需求追踪
需求跟踪是一个重要的过程,旨在建立和维护需求与产品实现之间的一致性。它包括正向跟踪和逆向跟踪两种方式,并通过需求跟踪矩阵来保存需求与后继工作成果的对应关系。跟踪能力的信息使得变更影响分析更加便利,有利于确认和评估需求变更所需的工作量。
需求跟踪的目的是确保所有工作成果符合用户需求,并提供明确查阅需求到产品实现整个过程的能力。为了实现可跟踪能力,需求需要统一标识,以便进行准确查阅。需求跟踪是一项手工操作任务,需要组织提供支持。
在实际项目中,通常采用专门的配置管理工具来实现需求跟踪。这些工具可以帮助组织管理和更新跟踪信息,确保其与实际情况保持一致。需求跟踪是一个劳动强度较大的任务,但对于优秀的需求规格说明书来说,具备跟踪能力是一个重要特征。
5.3 系统分析与设计
系统分析阶段是将复杂的对象分解为简单的组成部分,找出它们之间的关系的过程,其目标是将用户需求表达为系统需求规格说明书。系统设计的目标是根据系统分析结果完成系统构建,包括绘制系统蓝图、权衡各种技术和资源、制定详细的设计方案等,其主要内容包括概要设计和详细设计。
5.3.1 结构化方法
结构化分析
结构化分析是一种系统分析方法,通过使用数据流图和数据字典等工具,对系统的功能需求进行分析和描述。下面是结构化分析的主要步骤和工具:
- 分析业务情况,绘制数据流图:
- 根据当前的物理模型,绘制反映业务流程的数据流图。
- 通过分析输入、加工和输出数据流,将问题清晰地展现出来。
- 推导逻辑模型:
- 基于物理模型的数据流图,推导出等价的逻辑模型的数据流图。
- 这一步骤将问题从物理层面抽象到逻辑层面,更好地描述系统的功能需求。
- 设计逻辑系统,生成数据字典:
- 设计新的逻辑系统,生成数据字典和基元描述。
- 数据字典对系统中使用的数据项、数据结构、数据流、数据存储等进行定义和描述。
- 建立人机接口,提出物理模型的数据流图:
- 建立人机接口,根据需求提出可供选择的目标系统的物理模型的数据流图。
- 这一步骤关注系统与用户的交互和界面设计。
- 分析各种方案的成本和风险:
- 对各种方案进行成本和风险的分析和评估。
- 根据成本和风险等级,对各种方案进行比较和选择。
- 选择一种方案:
- 根据成本、风险和其他因素,选择一个最合适的方案。
- 建立完整的需求规约:
- 建立完整的需求规约,描述系统的功能需求。
- 需求规约是后续设计、编码和实现系统的基础。
数据流图和数据字典是结构化分析中常用的工具。数据流图通过图形化方式描述数据的流向和加工过程,而数据字典则定义和描述了系统中使用的所有数据元素。通过结构化分析,可以更清晰地理解系统的功能需求,并为后续的设计和开发提供指导。
结构化设计
结构化设计(Structured Design, SD)是一种面向数据流的设计方法,主要分为概要设计和详细设计两个阶段。概要设计阶段的任务是确定软件系统的结构,对系统进行模块划分,并确定每个模块的功能、接口和模块之间的调用关系。详细设计阶段则是为每个模块设计实现的细节。
在结构化设计中,模块是系统的基本单位,具有相对独立且单一功能的特点。模块的设计应遵循信息隐藏和抽象原则,即将模块的实现细节封装起来,对外部只暴露简单的接口信息。模块之间应该具有低耦合、高内聚的特性,即模块之间联系较弱、模块内部联系紧密。
系统结构图(Structure Chart, SC)是概要设计阶段的工具,用于反映系统的功能实现和模块之间的联系与通信。系统结构图展示了系统的总体结构和模块之间的层次关系。在详细设计阶段,可以使用图形工具、表格工具或语言工具来描述模块的实现细节。图形工具包括程序流程图、PAD图和NS流程图,表格工具可以列出操作和条件的详细信息,语言工具如PDL可以用于描述具体算法。
详细设计的目标是实现模块功能的正确逻辑算法,并保证算法描述简明易懂。设计过程中需要分析确定输入/输出数据的逻辑结构,找出输入和输出数据之间的对应关系,根据一定的规则导出程序结构图,并将基本操作和条件分配到程序结构图中。设计结果可以使用图形工具、表格工具或语言工具进行表示,如程序流程图、PAD图、NS流程图、表格等。
总而言之,结构化设计是一种以模块为基本单位的设计方法,通过模块划分和模块之间的联系来实现系统的功能。概要设计阶段确定系统结构和模块划分,详细设计阶段设计模块的实现细节。设计过程中遵循高内聚、低耦合的原则,并使用合适的工具来表示设计结果。
结构化编程
结构化程序设计(Structured Programming, SP)是一种由E.W. Dijikstra在1965年提出的程序设计方法。它将软件系统划分为若干功能模块,强调程序的结构性,易读易懂,并且能够减少出错率和维护费用。
结构化程序设计采用自顶向下、逐步求精的设计方法,各个模块通过“顺序、选择、循环”的控制结构进行连接,并且只有一个入口和一个出口。
其原则可概括为:程序=(算法)+(数据结构),即算法和数据结构分开设计,以算法为主体。
结构化程序设计的原则可以归纳为32个字:自顶向下,逐步细化;清晰第一,效率第二;书写规范,缩进格式;基本结构,组合而成。
数据库设计
数据库设计是根据用户需求,在特定的数据库管理系统上建立数据库结构的过程。它包括需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库实施以及数据库的运行和维护。本节主要讨论数据库的概念结构设计。
概念结构设计 概念结构设计是根据用户需求描述的现实世界,通过对实体事物进行分类、聚集和概括,建立抽象的概念数据模型,反映各部门的信息结构、信息流动情况、信息间的互相制约关系以及信息的储存、查询和加工要求。通常使用实体-联系图(E-R图)表示。
- 实体:具体可区分的事物,可以是人、物,也可以是抽象的概念与联系,用矩形框表示。
- 属性:实体所具有的特性,用椭圆形表示,并用无向边与相应的实体连接起来。
- 联系:反映实体内部或实体之间的关联,用菱形表示,用无向边与有关实体连接起来,同时标明联系的类型(1:1, 1:n 或 m:n)。
E-R图的基本作图步骤包括确定实体集合、选择每个实体集包含的属性、确定实体集之间的联系、确定实体集的关键字、确定联系的类型。
E-R图中的联系存在一对一约束、一对多约束和多对多约束,用来描述实体集之间的数量约束。一对一联系表示两个实体集具有一对一的联系,一对多联系表示一个实体集的值与另一个实体集的多个值对应,而多对多联系表示两个实体集的值彼此对应。联系也可能有属性,如学生选修某门课程所取得的成绩。
以上是数据库概念结构设计的基本内容。
5.3.2 面向对象方法
面向对象(Object-Oriented, OO)开发方法是一种建立在“对象”概念基础上的软件开发方法学,其本质是参照人们认识现实系统的方法,完成软件系统的分析、设计与实现。该方法强调使用人类在现实生活中常用的思维方法来认识和描述客观事物,使得最终建立的系统能够映射问题域,反映问题域中固有的事物及其关系。
面向对象开发方法的核心观点包括:
- 对象组成:认为客观世界由对象组成,对象具有属性和操作。
- 分类、联系:对象可以根据其属性进行分类,对象之间的联系通过传递消息来实现。
- 封装、继承和多态:对象具有封装性(将数据和操作封装在一个单元内)、继承性(子类可以继承父类的属性和行为)、以及多态性(不同对象对相同消息作出不同响应)。
面向对象开发方法是以用例驱动的、以体系结构为中心的、迭代的和渐增式的开发过程。
其主要包括需求分析、系统分析、系统设计和系统实现4个阶段,但各个阶段的划分不像结构化开发方法那样清晰,而是在各个阶段之间迭代进行的。
面向对象分析
面向对象的分析方法(Object-Oriented Analysis, OOA)是一种根据面向对象思想来分析问题的方法。它与结构化分析有较大区别。OOA强调在系统调查资料的基础上,针对面向对象方法所需素材进行归类分析和整理,而不是对管理业务现状和方法的分析。
OOA模型由5个层次(主题层、对象类层、结构层、属性层和服务层)和5个活动(标识对象类、标识结构、定义主题、定义属性和定义服务)组成。它定义了两种对象类之间的结构:分类结构和组装结构。分类结构描述一般类和特殊类之间的关系,而组装结构反映对象之间的整体和部分关系。
OOA的基本原则包括抽象、封装、继承、分类、聚合、关联、消息通信和粒度控制。抽象是从多个事物中抽取共同的本质特征,封装将对象的属性和服务结合为一个不可分的单位并隐藏内部细节,继承使得特殊类拥有一般类的全部属性和服务,分类划分具有相同属性和服务的对象为一类,聚合将复杂事物看作简单事物的组装体,关联表示事物之间的联系,消息通信要求对象只能通过消息进行通信,粒度控制是控制问题域视野的原则。
OOA大致上遵循确定对象和类、确定结构、确定主题、确定属性和确定方法这5个基本步骤。确定对象和类包括抽象出数据及其处理方式的对象和描述多个对象共同属性和方法的类。确定结构涉及问题域的复杂性和连接关系。确定主题是对事物总体概貌和总体分析模型的确定。确定属性是指数据元素,用来描述对象或分类结构的实例。确定方法是在收到消息后进行的处理方法。
需要注意的是,以上总结仅为面向对象分析方法的一般概述,并不详尽。具体实施时还需要考虑其他细节和技术。
面向对象设计
在OOD中,还需要注意以下几点:
- 继承和多态是实现可扩展性的重要手段。通过继承,可以将相同的属性和方法在父类中定义,然后在子类中进行扩展和修改;通过多态,可以以统一的方式处理不同类型的对象。
- OOD强调模块化和分层设计。模块化设计可以降低系统的复杂度,易于维护和修改;分层设计可以将系统划分为不同的层次,使得不同的层次之间关注点不同,提高了系统的可维护性和可扩展性。
- OOD还强调设计模式的使用。设计模式是一种被反复使用的、普遍认可的解决特定问题的方法或套路。合理使用设计模式可以提高代码的可读性、可维护性和可复用性。
- 最后要注意OOD的实现要考虑系统的性能、安全和可靠性等方面,如数据结构和算法的选择、异常处理、日志记录等。
面向对象编程
面向对象程序设计(Object Oriented Programming,OOP)是一种编程架构,其基本原则是将计算机程序组合成单个能够起到子程序作用的对象。OOP的目标是实现软件工程的重用性、灵活性和扩展性。OOP由对象、类、继承、多态和消息构成,其中核心概念是类和对象。
面向对象程序设计方法模拟人类的思维方式,使得软件开发方法尽可能接近人类解决现实问题的方式,将客观世界中的实体抽象为问题域中的对象,从而使描述问题的问题空间与问题的解决方案空间在结构上尽可能一致。
OOP以对象为核心,认为程序由一系列对象组成。类是对现实世界的抽象,包括表示静态属性的数据和对数据的操作,而对象是类的实例化。对象通过消息传递相互通信,模拟现实世界中不同实体间的联系,是面向对象程序设计的基本模块。
OOP的基本特点包括封装、继承和多态:
- 封装:将数据及与数据相关的操作语言组装到一起封装在一个类中,实现软件结构的高内聚、低耦合。
- 继承:指一个对象针对另一个对象的独有特点、能力进行复制或延续,分为单继承和多继承,以及取代继承、包含继承、受限继承和特化继承。
- 多态:当不同对象同时接收到相同消息时,所表现出的动作是各不相同的,或者在一组对象的一个类中,可以使用相同调用方式对相同函数名进行调用,即便这些函数所执行的动作是不同的。
数据持久化与数据库
面向对象开发方法中的对象只存在于内存中,如果需要永久保存对象的状态,就需要进行对象的持久化。对象持久化是将对象保存到数据库或其他可永久保存的存储设备中。为了降低系统的耦合度,多层软件设计中引入了持久层,负责实现数据持久化的逻辑。关系数据库是目前最常用的数据库类型,因此将对象持久化到关系数据库中需要进行对象和关系的映射,这就是对象关系映射(ORM)的概念。主流的持久化技术框架包括Hibernate、iBatis和JDO等。Hibernate是一个全自动的ORM框架,可以使用对象编程思维操作数据库;iBatis是一个小巧且灵活的解决方案,需要手动编写SQL实现;JDO是一种描述对象持久化语义的标准API,可以在不同数据底层上运行,提供了透明的对象存储功能。
5.4 软件测试
软件测试是通过人工或自动化手段对软件系统进行运行和测定的过程。其主要目的是验证软件是否满足规定的需求,并发现实际结果与预期结果之间的差异。
软件测试的工作主要包括以下几个方面:
- 发现软件错误:通过执行各种测试用例,包括功能测试、性能测试、安全测试等,发现软件中存在的错误和缺陷,以便及时修复。
- 定义和实现软件组装过程:有效地定义和实施软件的组装过程,将各个组件从低层到高层有机地组合在一起,确保软件的正确性和完整性。
- 验证软件是否满足技术要求:根据任务书和系统定义文档中规定的技术要求,验证软件是否达到了这些要求,包括功能、性能、安全等各个方面。
- 提供风险评估依据:软件测试可以为开发人员提供信息,帮助他们评估软件的风险,并做出相应的准备和调整,以确保软件的质量和稳定性。
- 贯穿整个软件开发过程:软件测试应该贯穿整个软件开发的过程,从需求分析、设计、编码到测试和维护,保证整个过程都是高质量的。
总之,软件测试的目的是确保软件的质量,确认软件按照用户期望的方式进行工作。它不仅发现软件错误,还为开发人员提供风险评估依据,并贯穿于整个软件开发过程中。这样能够确保软件达到预期要求并具备高质量。
5.4.1 测试方法
软件测试方法可以根据不同的分类标准进行划分。以下是几种常见的分类方法:
- 根据程序执行状态:
- 静态测试(Static Testing, ST):在不运行软件的情况下,通过检查源代码、文档和设计等静态元素来评估软件的质量。
- 动态测试(Dynamic Testing, DT):在运行软件时,通过执行测试用例并观察程序的实际执行结果来评估软件的质量。
- 根据测试对象的知识:
- 黑盒测试(Black Box Testing):测试人员只关注软件的输入和输出,而不考虑内部实现细节,主要验证软件功能是否符合规格说明。
- 白盒测试(White Box Testing):测试人员具有对软件内部结构和实现的了解,根据程序的逻辑路径和数据流来设计测试用例,主要验证软件的逻辑正确性和代码覆盖率。
- 灰盒测试(Gray Box Testing):介于黑盒测试和白盒测试之间,测试人员部分了解软件的内部结构和实现,以此为基础设计测试用例。
- 根据测试的执行方式:
- 人工测试(Manual Testing, MT):测试人员通过手动执行测试用例来评估软件的质量,包括手动输入测试数据、观察输出结果等。
- 自动化测试(Automatic Testing, AT):利用测试工具和脚本自动执行测试用例,收集和分析测试结果,提高测试效率和准确性。
总之,根据不同的分类标准,软件测试方法可以被划分为静态测试和动态测试、黑盒测试、白盒测试和灰盒测试,以及人工测试和自动化测试。这些分类方法可根据具体的测试需求和目标选择适合的测试方法。
5.4.2 测试阶段
- 单元测试是对软件模块进行测试,集中在功能单一、结构简单的模块上。
- 集成测试验证模块组装的正确性和需求功能的实现性。
- 系统测试则是对整个软件系统进行测试,包括功能测试、性能测试、验收测试等。
- 性能测试是通过模拟多种负载条件来测试系统性能指标。
- 验收测试是最后一个阶段的测试,验证软件是否符合用户需求和合同要求。
除了传统的测试种类外,还有一些新型测试种类如AB测试、Web测试中的链接测试、表单测试等。
5.5 净室软件工程
净室软件工程是一种以经济方式生产高质量软件的工程技术,其理念在于通过严格的工程过程,在规约和设计阶段消除错误,并以“净”的方式制作软件。这种方法强调在开发过程中建立正确性的需要,避免依赖于成本高昂的错误消除过程。净室软件工程的过程模型是在代码增量积聚到系统的过程中进行统计质量验证,甚至提倡开发者不需要进行单元测试,而是进行正确性验证和统计质量控制。它是基于理论、面向工作组、经济实用和高质量软件生产的方法。
5.5.1 理论基础
净室软件工程的理论基础主要包括函数理论和抽样理论。
函数理论将程序视为从定义域到值域的映射,强调完备性、一致性和正确性的特性,通过函数理论的推理来验证程序的正确性。
抽样理论则提出由于不可能对软件的所有可能应用进行测试,因此可以通过统计学手段对软件的所有可能使用情况进行抽样,并对样本进行测试,根据结果分析软件的性能和可靠性。
5.5.2 技术手段
净室软件工程应用的技术手段主要有以下四种:
-
统计过程控制下的增量式开发:将整个开发过程划分为一系列较小的累积增量,通过受控迭代的工程原理来控制开发过程,使开发人员能够集中精力在工作的一部分上,而无需同时考虑所有事情。
-
基于函数的规范与设计:采用盒子结构方法,根据函数理论定义了行为视图、有限状态机视图和过程视图这三个抽象层次。规范从外部行为视图开始,经过状态机视图转化为过程视图,实现了信息隐藏和实现分离的软件工程原则。
-
正确性验证:将正确性验证视为净室软件工程的核心。通过使用正确性验证技术,净室项目的软件质量得到极大提高。
-
统计测试和软件认证:净室测试方法采用统计学原理,通过确定使用模型来代表系统所有可能的使用情况,并从中生成测试用例。由于测试用例是总体的随机样本,可以进行有效的统计推导,评估系统的操作性能。
净室软件工程是一种形式化的软件开发方法,能够生成高质量的软件。它利用盒子结构规约进行分析和设计建模,并将正确性验证作为主要机制来发现和消除错误,而不是依赖于传统的测试方法。
5.5.3 应用与缺点
净室软件工程在20世纪90年代初取得了一系列成功案例,包括IBM生产的海量存储控制单元适配器、NASA哥达德飞行控制中心的软件工程实验室以及美国陆军的项目,都取得了显著的投资回报和质量提升。然而,净室软件工程也存在一些缺点:
- 需要较多数学知识,正确性验证步骤困难且耗时,开发成本较高;
- 开发小组不进行传统的模块测试,可能导致未预期的错误;
- 净室软件工程仍带有传统软件工程的一些弊端。
5.6 基于构件的软件工程
基于构件的软件工程(CBSE)是一种通过使用可复用构件来设计和构建软件系统的方法,强调软件复用和分布对象技术。CBSE的理念是购买已有构件而不是重新构建,将软件开发的重点从编写程序转移到组装构件,以加快系统构建速度、减轻维护负担并降低开发成本。CBSE正在改变大型软件系统的开发方式,将工程师的关注点从实现转移到集成,基于对大型软件系统的共性假设,通过开发可复用的软件组件来满足这些共性。
5.6.1 构件和构件模型
在软件复用领域,构件(Component-Based Software Engineering, CBSE)被认为是一个独立的软件单元,可以与其他构件组成一个软件系统。不同的专家对构件的定义存在一些差异,但无论如何定义,用于CBSE的构件应该具备以下特征:
- 可组装型:构件必须通过公开定义的接口进行外部交互,并对自身信息进行外部访问。
- 可部署性:构件必须是自包含的,能够作为独立实体在提供其构件模型实现的构件平台上运行,且无需在部署前编译。
- 文档化:构件必须完全文档化,用户可以根据文档来判断构件是否满足需求。
- 独立性:构件应该是独立的,可以在无其他特殊构件的情况下进行组装和部署,如果需要其他构件提供服务,则应当有显示声明。
- 标准化:在CBSE过程中使用的构件必须符合某种标准化的构件模型。
构件模型定义了构件实现、文档化以及开发的标准,为构件开发者确保构件的互操作性和为中间件的构件执行基础设施供应商支持构件操作而设立。目前主流的构件模型包括Web Services模型、Sun公司的EJB模型和微软的.NET模型。
构件模型包含以下要素信息:
- 接口:构件通过构件接口来定义,包括操作名、参数以及异常等。
- 使用信息:为使构件远程分布和访问,必须给构件一个特定的、全局唯一的名字或句柄,并包括构件的元数据。
- 部署:规定构件如何打包使其部署成为一个独立的可执行实体,包括有关包中内容的信息和它的二进制构成的信息。
构件模型还提供了一组被构件使用的通用服务,包括平台服务和支持服务。平台服务允许构件在分布式环境下通信和互操作,而支持服务是很多构件需要的共性服务,例如身份认证服务。
中间件实现共性的构件服务,并提供这些服务的接口,构件被部署在一个容器中,容器是支持服务的一个实现加上一个接口定义,构件必须提供该接口定义以便和容器整合在一起。
5.6.2 CBSE过程
CBSE过程的主要目标是通过构件复用来提高软件开发的效率和质量。它强调在开发过程中识别、选择和集成可复用的构件,并在不同的阶段进行适配和定制,以满足系统需求。与传统的软件开发过程相比,CBSE过程具有以下几点不同之处:
- 需求分析:CBSE过程要求在早期阶段完整地定义系统需求,以便尽可能多地识别出可复用的构件。而在增量式开发中,需求可以逐步完善。
- 需求修改:CBSE过程中,根据已发现的可复用构件,可以对需求进行修改和细化。如果可复用构件无法满足用户需求,可以考虑调整需求或寻找其他支持相关需求的构件。
- 系统体系结构设计:CBSE过程在系统体系结构设计完成后,会进一步进行构件搜索和设计精化的活动。可能需要寻找备选构件或对构件进行修改以适应功能和架构需求。
- 构件集成:CBSE过程中的开发阶段主要是将已找到的构件进行组装。这涉及将构件与构件模型基础设施集成,并可能需要开发适配器来协调不匹配的构件接口。
在CBSE过程中,系统体系结构设计阶段尤为重要,因为选择合适的构件模型和实现平台将决定可选构件的范围和限制。通过CBSE过程,可以更好地利用已有的构件资源,加快开发速度,提高软件质量,并促进软件复用的可持续性。
5.6.3 构件组装
构件组装是将可复用的构件通过直接集成或编写适配器来创建系统或其他构件的过程。常见的组装方式有顺序组装、层次组装和叠加组装。
-
顺序组装:按照顺序调用已存在的构件,将它们组装在一起创建新的构件。需要编写适配器代码来确保构件之间的接口兼容性。
-
层次组装:一个构件直接调用另一个构件提供的服务。被调用构件必须提供调用构件所需的服务,需要编写适配器代码进行接口转换。
-
叠加组装:将两个或多个构件组合在一起创建新构件,新构件具备原构件的功能并提供新的接口。原构件之间不相互依赖或调用。
在构件组装过程中,可能会遇到接口不兼容的情况,包括参数不兼容、操作不兼容和操作不完备。为了解决这些问题,可以编写适配器构件来使两个构件的接口一致。
在选择组装方式时,需要考虑系统的功能需求、非功能需求以及构件替换的难易程度,以确保系统能够满足需求并具有良好的可扩展性。
5.7 软件项目管理
5.7.1 项目管理概述
在软件项目管理中,进度管理是关键的一环,它涉及到软件开发过程中每个阶段的时间安排和任务分配,以确保项目按时完成。配置管理则是为了控制软件开发过程中的变更,包括版本控制、配置项管理和变更控制等方面。质量管理则是为了保证软件开发过程中的质量,包括需求分析、设计、编码、测试和维护等方面。风险管理则是为了识别和评估项目中的各种风险,并采取相应的措施来降低风险影响。
5.7.2 软件进度管理
软件项目进度管理中的两个关键概念:工作分解结构和任务活动图。
-
工作分解结构(WBS)
工作分解结构是将项目按一定原则分解成任务,再将任务分解为具体工作的过程。WBS树形结构以可交付成果为导向,对项目要素进行分组,并是制订进度计划、资源需求、成本预算、风险管理计划和采购计划等的重要基础。WBS的常见分解方式包括按产品的物理结构、功能、实施过程、实施单位、项目目标等分解方式,并指出了任务分解的基本要求。
-
任务活动图
任务活动图是在完成工作分解结构之后,根据每个活动的定义和活动间的关系得到的图表,用于确定活动之间的相互关系和活动执行的前后顺序。活动定义包括确定完成项目所必须进行的具体活动,明确活动的前驱、持续时间、必须完成日期、里程碑或交付成果。根据活动顺序可以得到对应的任务活动图,通常采用甘特图等方式来展示和管理项目活动。
5.7.3 软件配置管理
软件配置管理(Software Configuration Management, SCM)是一种技术,旨在标识、组织和控制软件变更。它应用于整个软件工程过程,以应对软件开发中不可避免的变更,减少混乱并提高生产效率。SCM的核心内容包括版本控制和变更控制。
- 版本控制(Version Control):
- 追踪程序代码、配置文件和说明文档等文件变更。
- 记录变更的时间、负责人和内容,每次变更都会增加文件的版本号。
- 有效解决多人协同开发中的版本同步和开发通信问题,提高协同开发效率。
- 通过分支与合并的方法,解决不同版本软件的错误修正问题。
- 变更控制(Change Control):
- 管理变更流程,确保变更有序进行。
- 处理来自外部和内部的变更要求,如客户需求变更和内部错误修正。
- 处理来自外部的需求变更可能更具挑战性,因为IT项目中需求变更的概率大且工作量巨大。
通过版本控制和变更控制,SCM能够使错误降到最低,并提高生产效率,从而确保软件开发过程的有序进行。
5.7.4 软件质量管理
软件质量是指软件与明确和隐含的需求相一致的程度。它包括软件符合功能和性能需求、开发标准以及专业软件应具备的隐含特征的程度。
从管理角度来看,影响软件质量的因素可分为三组,反映了用户在使用软件产品时的不同倾向和观点:
- 产品运行:
- 关注软件在运行过程中的稳定性、可靠性和性能表现。
- 包括对软件的功能是否正确、响应时间是否合理、资源利用是否高效等方面的评估。
- 目标是确保软件能够按照预期运行,满足用户的实际需求。
- 产品修改:
- 关注软件的可维护性和可扩展性。
- 包括对软件代码结构的清晰性、模块化程度、文档化程度等方面的评估。
- 目标是使软件易于修改和扩展,以适应不断变化的需求和环境。
- 产品转移:
- 关注软件的可移植性和可部署性。
- 包括对软件在不同操作系统、平台或环境下的适应性和兼容性的评估。
- 目标是确保软件可以顺利地转移到不同的环境中,并能够正常工作。
通过关注这三个方面,管理者可以综合考虑软件质量的多个维度,从而提高软件的质量水平,满足用户的需求。
软件质量保证
软件质量保证(Software Quality Assurance,SQA)是通过建立有计划、系统化的方法向管理层保证制定的标准、步骤、实践和方法能够正确地被所有项目采用的过程。其目的在于使软件过程对管理人员可见,并通过对软件产品和活动进行评审和审计来验证软件是否符合标准。SQA致力于一开始就避免缺陷产生,主要目标包括事前预防工作、在缺陷引入时捕获、作用于过程而不是最终产品、以及贯穿于所有活动。
软件质量保证的关注点主要在于预防缺陷的产生,并且以独立审查的方式监控软件开发任务的执行,提供反映产品和过程质量的信息和数据,以提高项目透明度并辅助软件工程取得高质量的软件产品。SQA的主要作用是给管理者提供预定义的软件过程的保证,确保选定的开发方法、标准和规程得到遵循和执行。
软件质量保证的主要任务包括SQA审计与评审,SQA报告以及处理不符合问题。SQA审计涉及对软件工作产品、软件工具和设备的审计,评价其是否符合组织规定的标准;SQA评审旨在确保软件工作组的活动与预定的软件过程一致,以及确保软件过程在软件产品的生产中得到遵循。SQA报告应记录工作结果并向相关人员发布,处理不符合问题也是SQA的重要任务,需要及时向有关人员和高级管理者反映。
软件质量认证
质量认证是用来检验企业整体质量水平的,ISO 9000和CMM是目前国内软件企业主要采用的质量认证标准。ISO 9001认证是指组织具有提供满足顾客要求和适用法规要求的产品的能力;CMM是软件生产过程标准和软件企业成熟度等级认证标准。
5.7.5 软件风险管理
软件项目风险管理是软件项目管理的重要内容,其主要目标是预防风险。风险管理包括风险估计(风险辨识、风险分析、风险排序)和风险控制(风险管理计划、风险处理、风险监督)两大阶段。美国Boehm、Charette以及卡内基梅隆大学软件研究所提出了不同的软件风险管理体系,其中卡内基梅隆大学的风险管理体系是一个基于实践的全面风险管理体系,并将软件需求方作为软件风险管理的要素。