开发过程⭐⭐⭐⭐

软件工程 ⭐⭐⭐⭐

瀑布模型⭐⭐

瀑布模型是一种线性顺序的软件开发模型,将软件开发过程划分为一系列阶段,每个阶段都有明确的输入和输出,并且按照顺序依次执行,如同瀑布流水一样。以下是各阶段的说明:

  • 需求分析:收集和确定用户对软件的功能、性能等方面的需求,形成需求规格说明书(SRS)。
  • 软件设计:根据需求分析的结果,进行软件的总体架构设计和详细设计,规划软件的模块结构和接口等。
  • 程序设计:进一步细化软件设计,确定具体的算法和数据结构等。
  • 编码实现:开发人员根据设计文档,使用编程语言编写代码,实现软件功能。
  • 单元测试:对软件中的各个单元模块进行测试,检查每个模块是否正确实现了相应功能。
  • 集成测试:将已通过单元测试的模块集成在一起进行测试,检查模块之间的接口和交互是否正常。
  • 系统测试:将整个软件系统作为一个整体进行测试,验证软件是否满足需求规格说明书中的要求。
  • 运行维护:软件上线运行后,对其进行维护,包括修复软件中的缺陷、优化性能、满足新的需求等。

优缺点:

优点是阶段明确,便于管理和控制

缺点是缺乏灵活性,一旦在开发后期发现前期的错误,修改成本较高

特点与应用:

严格区分阶段,每个阶段因果关系紧密相连

只适合需求明确的项目

变体(V模型)⭐

V 模型是一种典型的测试模型,强调测试活动与开发阶段的对应关系,整体形状像一个 V 字。以下是对各阶段的介绍:

测试贯穿于始终,测试分阶段,测试计划提前

  • 开发阶段:从需求分析开始,依次经过概要设计、详细设计,最终到编码。需求分析确定软件的功能和性能要求;概要设计规划软件的整体架构和模块划分;详细设计对每个模块进行具体的设计;编码则是用编程语言实现软件。
  • 测试阶段:与开发阶段相对应,分别是单元测试、集成测试、系统测试和验收测试。单元测试针对单个模块进行测试;集成测试验证模块之间的接口和交互;系统测试将整个软件系统作为一个整体测试;验收测试由用户或客户进行,确认软件是否满足需求。

原型模型⭐⭐⭐

原型模型适用于需求不明确的项目,它主要包含两个阶段:

  • 原型开发阶段:在需求分析后,快速开发出一个可以运行的软件原型。这个原型可能只具备部分核心功能,主要用于展示软件的基本架构和操作方式,以便获取用户的反馈,明确用户的真实需求。
  • 目标软件开发阶段:根据从原型中获取的反馈和明确后的需求,进行正式的软件设计、程序设计、编码实现、单元测试、集成测试、系统测试以及运行维护等工作。

分类:

  • 抛弃型原型:构建原型只是为了更好地理解需求,在需求明确后,原型会被抛弃,然后重新开发目标软件。
  • 演化型原型:以初始原型为基础,不断进行改进和扩展,逐步演化为最终的目标软件 。

优缺点:

优点是能快速获取用户反馈,减少因需求不明确带来的开发风险;

缺点是如果对原型的修改和管理不当,可能会导致项目后期难以控制。

相关模型

以原型为中心结合其他模型演化成其他模型

增量与迭代⭐

软件开发中的迭代与增量概念:

  • 增量型:增量开发模型,将软件系统按功能模块拆分成多个增量构件,每次完成一部分增量构件,逐步增加软件功能,最终形成完整软件。
  • 迭代型:迭代开发模型,通过多次迭代,每次对软件进行改进和优化,不断完善软件的功能和质量。
  • 增量与迭代:统一过程(UP)和敏捷开发方法都强调增量和迭代的思想,在软件开发过程中结合这两种方式,以便更好地应对需求变化,提高开发效率和软件质量。

螺旋模型⭐⭐⭐

螺旋模型以快速原型为基础,结合了瀑布模型的系统性和顺序性,同时强调了风险分析。以下是具体介绍:

  • 模型结构:螺旋模型呈螺旋状,每旋转一圈代表一个项目阶段。从中心向外,包含多个环节,
    • 目标设定(决定目标、方案和限制)
    • 风险分析(评价方案、识别风险、消除风险)
    • 开发和有效性验证(包括需求计划、软件需求、产品设计等一系列开发与测试活动)
    • 评审
  • 特点总结
    • 以快速原型为基础并结合瀑布模型,
    • 充分考虑了风险问题,通过多次循环迭代的方式,在每个阶段都进行风险评估,降低项目风险,逐步完善软件产品。

特点与应用:

该模型支持大型软件开发,适用于面向规格说明、面向过程和面向对象的软件开发方法, 也适用于几种开发方法的组合。

构件组装模型(CBSD)⭐⭐

软件开发中的构件组装模型,开发流程如下:

开发流程

  1. 需求分析和定义开始

  2. 接着设计构件组装

  3. 之后建立构件库

  4. 构件库中的构件通过构件获取构件管理来维护。

  5. 基于这些标准和构件库来构建应用软件

  6. 最后进行测试和发布

    image-20250224161920992

优缺点:

优点

  • 易扩展,方便增加新功能;
  • 易重用,可复用已有的构件,减少开发工作量;
  • 能降低成本;
  • 安排任务更灵活,不同团队可负责不同构件。

缺点

  • 构件设计对架构师经验要求高;
  • 设计欠佳的构件难以重用;
  • 过于强调重用可能会牺牲性能等其他指标;
  • 第三方提供的构件质量难以把控。

基于构件的软件工程(CBSE)

  • 核心理念:CBSE 体现了 “购买而不是重新构造” 的哲学,即尽量复用已有的构件,而非一切从零开发,以此提高软件开发效率。
  • 构件特征
    • 可组装性:构件与外部的交互都要通过公开定义的接口,这样能保证不同构件间可以顺利组装。
    • 可部署性:构件以二进制形式存在,可作为独立实体在平台上运行,方便在不同环境中部署使用。
    • 文档化:有详细的文档说明,方便用户判断该构件是否符合自身需求。
    • 独立性:构件可在没有特殊依赖的情况下进行组装和部署,降低了构件间的耦合度。
    • 标准化:构件要符合特定的标准化模型,便于统一管理和复用 。

基于构件的软件工程(CBSE)中构件的组装方式,具体内容如下:

  • 顺序组装:按照先后顺序调用已有的构件,通过这种方式,利用两个现有的构件组合创造出一个新的构件,强调了构件调用的顺序性 。
  • 层次组装:在调用构件时,被调用构件提供的接口必须与调用构件的请求接口兼容,这样才能保证构件之间能够正确交互和协同工作,重点在于接口的兼容性。
  • 叠加组装:将多个构件合并形成一个新的构件,新构件整合了原来构件的功能,并对外提供新的接口,实现了功能的整合与新接口的输出。 图中的手绘部分可能是讲解时的辅助示意。

快速应用开发模型 (RAD)

RAD(快速应用开发,Rapid Application Development)结合了 SDLC(瀑布) 和 CBSD(基于构建) 的特点,旨在快速开发应用程序。它包含了五个主要阶段:

  1. 业务建模:确定业务流程、业务规则和数据流动。
  2. 数据建模:定义数据对象、数据结构和它们之间的关系。
  3. 过程建模:明确处理数据的过程和逻辑。
  4. 应用生成:使用工具和技术快速创建应用程序。
  5. 测试与交付:对应用进行测试,确保其质量,并交付给用户。

【能快速的原因】: RAD 能快速开发应用的原因在于它整合了其他方法的优势,通过并行处理和使用可复用构件,加快了开发进程 。

统一过程(UP)⭐⭐⭐

统一过程主要包含四个阶段⭐:

初始阶段

  • 重点在于定义最终产品的视图和业务模型,明确系统的整体范围,也就是确定要开发的软件是什么,以及它需要满足哪些业务需求。

细化阶段

  • 主要工作是设计并确定系统架构,同时制定详细的工作计划和资源需求。这个阶段为后续的开发工作奠定了基础架构

构造阶段

  • 此阶段进行剩余构件和应用程序功能的开发,并将这些构件集成为产品,随后进行详细测试,确保软件各部分能正常协同工作。

移交阶段

  • 确保软件对最终用户是可用的,进行 β 测试(即发布给部分真实用户进行测试),然后制作产品发布版本,将软件交付给用户使用。

特点:

  • 用例驱动:从用户的使用场景出发,确定软件功能需求。
  • 以架构为中心:在开发过程中始终围绕已确定的系统架构进行。
  • 迭代和增量:通过多次迭代逐步完善软件,每次迭代增加新的功能或改进现有功能 。

九个核心工作流

  1. 业务建模:在初始阶段占比较大,随着项目推进,工作量逐渐减少。主要是对业务流程、规则等进行建模。
  2. 需求:初始阶段开始,在细化阶段达到较高水平,后续逐渐降低,用于确定和梳理软件需求。
  3. 分析与设计:在细化和构造阶段工作量较大,对软件进行分析和设计架构。
  4. 实现:主要集中在构造阶段,进行代码编写和构件实现。
  5. 测试:在构造和移交阶段工作量较多,用于检测软件的质量和功能。
  6. 部署:在移交阶段工作量达到高峰,将软件部署到生产环境。
  7. 配置与变更管理:贯穿整个项目过程,确保项目配置的准确性和变更的可控性。
  8. 项目管理:在各阶段都有涉及,对项目进度、资源等进行管理。
  9. 环境:在项目前期和后期都有一定工作,负责搭建和维护开发、测试、生产等环境。

敏捷方法⭐⭐⭐

软件开发方法演进

软件开发方法从无软件开发方法到传统软件开发方法,再到敏捷方法的演进过程。

无软件开发方法的特点是无序、不可控

传统软件开发方法例如结构化方法,具有预设性,以开发过程为本,将整体开发分为不同阶段。

敏捷宣言

  1. 强调个体和交互胜过过程和工具;
  2. 可工作的软件胜过大量的文档;
  3. 客户合作胜过合同谈判;
  4. 响应变化胜过遵循计划 。

特点

具有适应性以人为本,采用增量迭代小步快跑的开发模式,更适合小型项目

多种敏捷开发方法

  • 极限编程(XP):秉持沟通、简单、反馈、勇气的价值观,采用近螺旋式的开发方式,强调在开发中不断调整和优化。
  • 水晶方法:突出 “机动性”,能够根据不同类型的项目特点,灵活采用有效的敏捷过程,适应性较强。是一个系列
  • SCRUM:重点在于项目管理,通过明确的角色分工(产品负责人、敏捷教练、团队)和固定的迭代流程(计划会议、每日站会等)来推进项目。
  • 特征驱动开发方法(FDD):认为软件开发依赖人、过程、技术三要素,定义了项目经理、首席架构设计师等 6 种关键项目角色,各负其责推动开发。
  • 开放式源码:其特点是程序开发人员地域分布广泛,与其他强调集中办公的敏捷方法不同,依赖远程协作和开源社区的力量。
  • ASD 方法:核心包含猜测、合作与学习三个非线性且重叠的开发阶段,强调在开发过程中不断探索、协作和积累经验。
  • 动态系统开发方法(DSDM):倡导以业务为核心,确保开发的软件能切实满足业务需求,提升业务价值 。

极限编程(XP)

极限编程的 4 大价值观
  • 沟通:强调加强团队成员之间面对面的沟通,以便快速准确地传递信息,减少误解。
  • 简单:提倡不过度设计,只实现当前需求必要的功能,使代码和设计保持简洁,便于维护和扩展。
  • 反馈:注重及时反馈,无论是来自团队内部成员之间,还是客户的反馈,以便及时调整开发方向和解决问题。
  • 勇气:鼓励团队成员拥有接受变更的勇气,因为在软件开发过程中需求变化不可避免,要能够灵活应对。
极限编程的 12 条过程实践规则(不考,可以用于论文)
  • 简单设计:保持设计简洁,只满足当前需求。
  • 测试驱动:先编写测试用例,再进行代码开发,确保代码质量。
  • 代码重构:定期优化代码结构,提高代码的可维护性和可扩展性。
  • 结对编程:两名程序员共同在同一台计算机上编写代码,互相审查和交流。
  • 持续集成:频繁地将代码集成到共享仓库,进行自动构建和测试。
  • 现场客户:让客户参与到开发过程中,随时提供需求和反馈。
  • 发行版本小型化:发布小而频繁的版本,便于快速迭代和修复问题。
  • 系统隐喻:使用形象的比喻来描述系统的架构和功能,便于团队成员理解。
  • 代码集体所有制:团队成员对所有代码都有修改和维护的责任。
  • 规划策略:制定合理的项目规划和迭代计划。
  • 规范代码:遵循统一的代码规范,提高代码的可读性。
  • 40 小时工作机制:避免长时间加班,保证团队成员的工作效率和生活质量 。

Scrum

将整个待办列表分成若干个迭代

  1. 需求收集与整理:产品负责人收集需求并整理到产品待办列表中。
  2. 迭代计划会议:团队从产品待办列表中选择本次迭代要完成的任务,形成迭代待办事项。
  3. 迭代开发:迭代周期通常为 1 - 4 周,在此期间目标保持不变。团队按照计划进行开发工作,每天通过每日站会沟通进度和问题。
  4. 迭代评审会议:迭代结束后,展示潜在可发布的产品增量,收集反馈。
  5. 迭代回顾会议:团队回顾本次迭代过程,总结经验教训,提出改进措施。
  6. 下个迭代准备:敏捷教练协助整理下个迭代版本的产品待办列表,开始新的迭代循环 。

逆向工程⭐⭐

逆向工程与系统开发流程

现有系统出发,通过再工程对系统进行处理。再工程过程中,逆向工程是设计的恢复过程,先分析现有系统,考虑新需求后,再通过正向工程构建新系统。这一过程体现了从旧系统到新系统的转变,利用逆向工程获取旧系统的相关信息,辅助新系统的开发。

逆向工程的级别

逐步提高👆

  • 实现级:涉及程序的抽象语法树、符号表以及过程的设计表示,主要关注程序代码层面的基础结构和表示。
  • 结构级:包含反映程序分量之间相互依赖关系的信息,如调用图、结构图、程序和数据结构,强调程序各部分之间的关联和组织形式。
  • 功能级:涵盖反映程序段功能及程序段之间关系的信息,例如数据和控制流模型,侧重于程序的功能逻辑和数据流向。
  • 领域级:包含反映程序分量或程序诸实体与应用领域概念之间对应关系的信息,如实体关系模型,将程序与实际应用领域的概念相联系 。

相关概念

  • 重构 / 重组(Restructuring):是在同一抽象级别上转换系统的描述形式,比如对代码进行优化整理,不改变系统整体功能和抽象层次,只是调整代码结构或表达方式。
  • 设计恢复(Design recovery):借助工具从已有程序中提取数据设计、总体结构设计和过程设计等方面的信息,为后续对程序的理解和修改提供基础。
  • 逆向工程(Reverse engineering):分析程序,在比源代码更高的抽象层次上建立程序的表示过程,本质是恢复设计信息的过程,有助于理解现有系统的设计思路和架构。
  • 正向工程(Forward engineering):不仅从现有系统中恢复设计信息,还利用这些信息对现有系统进行改变或重构,以提升系统的整体质量,比如优化性能、增强功能等。
  • 再工程 / 重构工程(Re - engineering):是对现有系统重新开发的过程,包含**逆向工程(获取现有系统信息)、考虑新需求以及正向工程(基于信息和新需求改造系统)**三个步骤 。

净室软件工程

  • 基本概念:净室指的是无尘、洁净,受控污染级别的环境。在软件开发中,它使用盒结构规约(或形式化方法)进行分析和设计建模,强调通过正确性验证而非传统测试来发现和消除错误,并运用统计测试获取软件可靠性的出错率信息。
  • 技术手段
    • 统计过程控制下的增量式开发:采用控制迭代的方式逐步开发软件,保证开发过程的稳定性和可预测性。
    • 基于函数的规范和设计:运用盒子结构,定义了三种抽象层次。
      • 视图(黑盒,关注外部行为)
      • 有限状态机视图(状态盒,描述状态变化)
      • 过程视图(明盒,展示具体过程)
    • 正确性验证:这是净室工程的核心,确保软件设计和实现的正确性。
    • 统计测试和软件认证:运用统计学原理进行测试,当总体数据量过大时,采用抽样方法进行测试和软件认证 。

需求工程 ⭐⭐

需求工程的概述

  • 软件需求定义:软件需求是用户对系统在功能、行为、性能、设计约束等方面的期望,明确了开发的目标和方向。
  • 需求工程主要活动阶段划分
    • 需求开发
      • 需求获取:通过各种方式收集用户的需求信息。
      • 需求分析:对获取到的需求进行深入研究和分析,理清需求之间的关系和细节。
      • 形成需求规格(形成 SRS):将分析后的需求整理成规范的需求规格说明书(SRS) 。
      • 需求确认与验证(形成需求基线):对需求规格进行评审,确保其准确无误,经过评审的 SRS 就形成了需求基线
    • 需求管理对需求基线进行管理,包括:
      • 变更控制(处理需求的变更)
      • 版本控制(管理不同版本的需求)
      • 需求跟踪(跟踪需求的实现情况)
      • 需求状态跟踪(了解需求所处的状态)

需求获取

需求获取方法

  • 用户面谈:通常是与 1 到 3 个有代表性的用户进行交流,便于了解用户主观想法,交互性好。但成本较高,需要有相关领域知识支撑才能有效进行。
  • 需求专题讨论会(JRP):这是一种高度组织的群体会议,让各方人员共同参与,能充分了解各方想法,消除分歧,交互性也不错,但同样成本较高。
  • 问卷调查:适用于用户数量众多,无法一一进行访谈的情况,其成本较低,可以大规模收集用户信息。
  • 现场观察:针对较为复杂的业务流程和操作,通过实地观察来获取需求,能直观了解实际操作情况。
  • 原型化方法:通过构建简易系统,帮助解决早期需求不确定的问题,让用户直观感受并提出反馈,完善需求。
  • 头脑风暴法:一群人围绕新业务展开讨论,发散思维,虽然不一定产生全新观点,但能集思广益挖掘需求 。

软件需求的分层

  • 业务需求:从整体全局角度出发,反映组织或客户对软件系统的高层次目标和期望。
  • 用户需求:站在用户视角,描述用户使用软件要完成的任务和期望。
  • 系统需求:侧重于计算机化实现,将用户需求转化为计算机系统可理解和执行的需求,进一步细分为
    • 功能需求(软件应具备的具体功能)
    • 性能需求(非功能方面,如响应时间、吞吐量等)
    • 设计约束(对软件设计的限制条件)

项目管理维度划分需求

  • 基本需求:明示的、常规的需求,是软件必须满足的基础部分。
  • 期望需求:隐含的需求,虽然未明确表述,但用户期望软件具备。
  • 兴奋需求:超出用户预期的需求,即便没有也不影响软件基本使用,有的话会让用户更满意 。

需求分析

需求工程中需求开发阶段的需求分析内容,运用结构化分析(SA)方法,通过不同模型和工具来梳理软件需求:

  • 数据字典:处于核心位置,是对数据元素、数据结构、数据流、数据存储、加工逻辑、外部实体等数据相关信息的定义和描述集合,为其他模型提供数据基础和解释。
  • 功能模型:使用数据流图来表示,包含数据流(数据的流动方向)、加工(对数据的处理操作)、数据存储(数据的存储位置)和外部实体(与系统交互的外部对象),用于描述系统的功能和数据处理流程
  • 数据模型:通过 E - R 图(实体 - 关系图)呈现,涉及实体(系统中的对象)和联系(实体之间的关系),用于表达数据之间的关联和组织形式
  • 行为模型:借助状态转换图描述,涵盖状态(包括初态和终态)和事件(引起状态变化的因素),用于展现系统在不同条件下的行为变化 。

需求定义

  • 严格定义法(需求明确稳定,各方沟通顺畅的项目):
    • 假定所有需求都能预先定义
    • 开发人员和用户之间能准确清晰交流,
    • 可以通过图形或文字充分呈现最终系统。
  • 原型法(需求模糊、需要用户参与反馈的项目):
    • 认识到并非所有需求在开发前都能被精准说明
    • 项目参与者间常存在交流困难。
    • 需要构建实际、可供用户参与的系统模型
    • 需要合适的开发环境。
    • 原型法允许反复迭代,当需求确定后,再遵循严格的开发方法。

需求验证

  • 需求验证方式:包含需求评审和需求测试。需求评审又分为正式评审和非正式评审,用于检查需求的完整性、一致性等。
  • 最终确认:通过需求验证后,需要用户签字确认,这也是项目验收的标准之一,确保需求符合用户预期 。

需求跟踪

  • 跟踪方向:包括正向跟踪和反向跟踪。正向跟踪是从用户原始需求到软件需求,再到下游工作产品的过程;反向跟踪则是逆向回溯,用于确认下游工作产品是否满足上层需求。
  • 跟踪矩阵框架:右侧表格是一个需求跟踪矩阵的框架,列出了元素、功能点、设计元素、代码模块、测试用例等,用于记录不同开发阶段元素与用例之间的对应关系,以便全面跟踪需求在整个开发过程中的实现情况 。

需求变更

  • 识别问题:当在项目中发现需求相关的问题时,开始进入需求变更管理流程。
  • 问题分析和变更描述:对识别出的问题进行详细分析,描述清楚需要变更的内容,为后续步骤提供基础。
  • 变更分析和成本计算:评估变更对项目的影响,包括技术、进度、资源等方面,并计算变更所需的成本。“CCB”(Change Control Board,变更控制委员会)会在此环节参与决策,判断变更是否可行。
  • 变更实现:在获得批准后,实施需求变更,最终得到修改后的需求。 整个流程确保需求变更有序进行,减少对项目的负面影响。

统一建模语言(UML)⭐⭐

UML 有3个重要组成部分:构造块,规则,公共机制

UML 中的构造块⭐

  • 事物:UML 模型的基本元素。
    • 结构事物是模型中最静态的部分,用于定义概念或物理元素。
    • 行为事物:代表时间和空间上的动作,用于描述系统的动态行为。
    • 分组事物:可以看作是一种容器,用于组织模型元素,使模型更易于管理.
    • 注释事物:是 UML 模型的解释部分,用于对模型中的元素进行描述、说明和标注.
  • 关系:定义了事物之间的联系,如关联、依赖、泛化、实现等关系。
  • : UML 包含多种图,如用例图、类图、顺序图等,用于从不同视角展示系统模型。

UML 中的规则:

  • 范围:为一个名字赋予特定含义的语境,规定了名字在哪个范围内有效。
  • 可见性:描述了如何使用或看见名字,即元素在模型中的可访问性。
  • 完整性:关注事物如何正确、一致地相互联系,确保模型的逻辑正确性和一致性。
  • 执行:指运行或模拟动态模型时的具体含义,涉及到模型在实际运行中的行为表现。

UML 中的公共机制:(元素达成共识)

  • 规格说明(对事物语义细节的描述,是模型核心)
  • 修饰(用于表达更多信息)
  • 公共分类(如类与对象、接口与实现)
  • 扩展机制(允许添加新规则) ,另外提到了范围、可见性、完整性和执行等概念。

UML(统一建模语言)图的分类和简要介绍

  • 静态图(结构图)

    :主要用于描述系统的静态结构。

    • 类图:展现一组类、接口、协作及其之间的关系,体现系统的静态设计视图。
    • 对象图:展示一组对象以及它们之间的关系,是类图的实例。
    • 构件图:描述一个封装的类及其接口,显示系统的物理组成部分。
    • 部署图:表示软硬件之间的映射关系,展示系统的物理部署情况。
    • 制品图:呈现系统的物理结构,如可执行文件、库等。
    • 包图:由模型分解的组织单元构成,展示这些单元之间的依赖关系,用于管理模型的复杂性。
    • 组合结构图:描述类或构件内部的结构。
  • 动态图(行为图)

    :侧重于描述系统的动态行为。

    • 用例图:描述系统与外部参与者之间的交互,展现系统的功能需求。
    • 顺序图:强调按时间顺序展示对象之间的交互。
    • 通信图(协作图):突出对象之间的交互协作关系。
    • 状态图:描述对象状态的转换变迁。
    • 活动图:类似于程序流程图,可展示并行行为。
    • 定时图:强调实际时间,关注对象状态在时间上的变化。
    • 交互概览图:是顺序图和活动图的混合,用于展示交互流程的总体情况。

4 + 1 视图:

  • 用例视图(use - case view):处于中心位置,面向最终用户,是需求分析模型,用于描述用户对系统的功能需求。
  • 逻辑视图(logical view):面向系统分析、设计人员,关注类与对象,体现系统的功能逻辑。
  • 实现视图(implementation view):面向程序员,涉及物理代码文件和组件,描述系统的具体实现。
  • 进程视图(process view):面向系统集成人员,主要关注线程、进程和并发等方面,体现系统运行时的动态行为。
  • 部署视图(deployment view):面向系统和网络工程师,描述软件到硬件的映射,即系统在硬件环境中的部署方式 。

系统分析与设计⭐⭐

软件系统建模

阐述了从现有系统到新系统的建模转换步骤:

  • 现有系统建模(这一过程主要是对现有系统的理解和抽象表达):
    1. 从 “现有系统” 出发,先对其物理层面进行分析,形成 “物理系统”,
    2. 通过模型化构建 “物理模型”,
    3. 再经过抽象化提炼出系统的本质逻辑,得到 “逻辑模型”,
  • 新系统设计
    1. 在需求分析的基础上得到逻辑模型
    2. 经过调整和优化后,通过实例化将逻辑模型转化为物理模型
    3. 再进一步具体化得到新系统的物理系统
    4. 最终实现 “新系统”。
image-20250226165748979

人机界面设计

人机界面设计的 “黄金三法则” 展开介绍,为设计友好、易用的人机交互界面提供了原则性指导,具体内容如下:

一、置于用户控制之下

  • 自主的交互定义:“以不强迫用户进入不必要的或不希望的动作的方式来定义交互方式”,这意味着在设计界面交互时,要充分尊重用户的意愿和选择,避免设置强制性的操作流程,让用户能自由决定操作的方向和内容。
  • 灵活的交互操作:“提供灵活的交互” 以及 “允许用户交互可以被中断和撤销”,赋予用户在操作过程中随时调整和反悔的权利。比如在文件编辑过程中,用户可以随时中断当前操作去处理其他任务,也能撤销之前的误操作,增强操作的灵活性和容错性。
  • 个性化交互体验:“当技能级别增加时可以使交互流水化并允许定制交互”,考虑到不同用户的操作熟练程度差异,对于技能水平较高的用户,提供更流畅、高效的交互方式,还支持用户根据自身习惯定制交互设置,提升个性化体验。
  • 技术细节隔离:“使用户隔离内部技术细节”,将复杂的技术实现细节隐藏起来,用户无需了解底层技术原理,只需关注界面所呈现的功能和操作,降低使用门槛。
  • 直接交互方式:“设计应允许用户和出现在屏幕上的对象直接交互”,让用户能够直接对界面上的元素进行操作,如直接拖动图标、点击按钮等,增强操作的直观性和便捷性。

二、减少用户的记忆负担

  • 降低记忆要求:“减少对短期记忆的要求”,避免在界面中设置过多需要用户临时记住的信息和操作步骤,让用户能轻松完成任务,无需耗费大量精力去记忆。
  • 合理设置缺省:“建立有意义的缺省”,根据大多数用户的使用习惯和常见场景,为界面元素设置合理的默认值,减少用户手动输入和选择的操作,节省时间和精力。
  • 直观的捷径定义:“定义直觉性的捷径”,提供一些符合用户直觉和操作习惯的快捷方式,方便用户快速执行常用操作,提高操作效率。
  • 隐喻式视觉布局:“界面的视觉布局应该基于真实世界的隐喻”,采用与现实生活场景或事物相似的视觉元素和布局方式,让用户能够凭借已有的生活经验快速理解界面的功能和操作方式,降低学习成本。
  • 渐进式信息揭示:“以不断进展的方式揭示信息”,根据用户的操作流程和需求,逐步展示相关信息,避免一次性呈现过多信息造成用户信息过载和认知负担。

三、保持界面的一致性

  • 任务情境关联:“允许用户将当前任务放入有意义的语境”,使界面的设计和操作逻辑能够与用户当前的任务和使用场景相匹配,让用户能够快速理解和融入操作情境,提高操作的连贯性和效率。
  • 应用系列统一:“在应用系列内保持一致性”,对于同一软件系列或相关应用,在界面风格、交互方式、操作逻辑等方面保持统一,使用户在切换不同应用时能快速上手,减少重新学习的成本。
  • 尊重用户期望:“如过去的交互模型已建立起了用户期望,除非有迫不得已的理由,不要改变它”,如果某种交互方式已经被用户熟悉和习惯,形成了固定的使用期望,那么在后续的设计中应尽量保持一致,避免随意更改导致用户操作不习惯和困惑。

结构化设计⭐⭐⭐

结构化设计的内容

  • 概要设计(外部设计):将功能需求分配给软件模块,明确每个模块的功能以及它们之间的调用关系,最终形成模块结构图。
  • 详细设计(内部设计):针对每个具体任务,选择合适的技术手段和处理方法 。

结构化设计原则

  • 模块独立性原则:追求高内聚(模块内部功能联系紧密)和低耦合(模块之间相互依赖程度低),这样的设计使模块更易于维护和扩展。
  • 保持模块的大小适中:模块不能过大导致复杂度高难以理解和维护,也不能过小造成管理成本增加。
  • 多扇入,少扇出:扇入指模块被其他模块调用的次数,多扇入说明模块的通用性强;扇出指模块调用其他模块的个数,少扇出表示模块的复杂度低。
  • 深度和宽度均不宜过高:深度表示模块结构中的控制层数,宽度表示一层中最大的模块个数,控制这两个指标可避免系统结构过于复杂。

内聚类型

按内聚程度从高到低进行排列和说明:

  • 功能内聚:属于高内聚,模块完成单一功能,模块内各个部分协同工作,缺少任何一部分都无法完成该功能,体现了高度的完整性和专一性。
  • 顺序内聚:处理元素相互关联,且必须按照特定顺序执行前一个处理的输出是后一个处理的输入,具有一定的逻辑性和顺序性。
  • 通信内聚:所有处理元素集中在同一个数据结构区域上,即这些处理操作都与同一批数据相关,虽然内聚程度不如功能内聚和顺序内聚,但也有一定的关联性 。
  • 过程内聚:处理元素相关,并且要按特定次序执行,与顺序内聚类似,但它更侧重于过程的执行顺序。
  • 时间内聚(瞬时内聚):模块包含的任务需要在同一时间间隔内执行,例如系统初始化模块,其中的各项任务在系统启动时一同执行 。
  • 逻辑内聚:完成逻辑上相关的一组任务,比如一个模块负责处理各种类型的错误提示,这些任务在逻辑上都与错误处理相关,但彼此之间的联系并不紧密。
  • 偶然内聚(巧合内聚):属于低内聚,模块完成的一组任务之间没有关系或仅有松散关系,这种内聚方式的模块独立性差,不利于软件的维护和扩展。

耦合类型

按耦合程度从低到高排列并说明:

  • 非直接耦合:属于低耦合两个模块间无直接联系,它们通过主模块的控制和调用来关联,独立性强,修改一个模块对另一个影响小。
  • 数据耦合:模块间借助参数表传递简单数据,是较松散的耦合,模块间依赖度低,利于维护和修改。
  • 标记耦合:模块间通过参数表传递记录信息(数据结构),比数据耦合的耦合度稍高,因为数据结构变化可能影响多个模块。
  • 控制耦合:模块传递的信息含控制内部逻辑的内容,这使模块间关联增强,一个模块的修改可能影响到接收控制信息的模块。
  • 外部耦合:一组模块访问同一全局简单变量,且不通过参数表传递,模块对外部环境有依赖,增加了模块间的关联度。
  • 公共耦合:多个模块访问同一个公共数据环境,如公共数据区,一个模块对公共数据的修改可能影响其他模块,耦合度较高。
  • 内容耦合:高耦合,一个模块直接访问另一个模块内部数据、不经正常入口转入内部、代码重叠或一个模块有多个入口,模块间联系紧密,维护和修改困难。

四个要素:

  • 输入和输出模块的输入来源与输出去向都是同一个调用者。模块从调用者处获取数据作为输入,经过内部处理后,将处理结果返回给调用者。这样明确了模块与外部的交互方式,保证数据的有序流动。
  • 处理功能:即模块将输入数据转换为输出数据所执行的具体工作。它定义了模块的核心任务,通过特定的算法或逻辑实现数据的加工处理。
  • 内部数据是仅在模块内部被引用的数据。这些数据不与其他模块共享,用于支持模块内部的处理功能,对外部是隐藏的,增强了模块的独立性和数据安全性。
  • 程序代码指实现模块功能的具体代码。通过编写程序代码来完成处理功能,是模块功能得以实现的载体,不同的编程语言可用于编写这些代码 。

面向对象设计⭐⭐⭐

基本工程

面向对象设计的基本过程,主要包括分析模型设计师的设计工作设计模型三个部分:

  • 分析模型:包含用例模型领域模型的分析模型
    • 用例模型用于描述系统的功能需求,从用户角度展示系统提供的功能;
    • 领域模型则是对问题领域内的概念类或现实世界对象的可视化表示,反映业务领域中的实体及其关系。
  • 设计师的工作:设计师基于分析模型开展一系列工作,包括
    • 设计用例实现方案,即确定如何实现用例模型中的功能;
    • 设计技术支撑实施,考虑技术层面的支持;
    • 设计用户界面,关注用户与系统的交互;
    • 细化设计模型,完善整个设计架构 。
  • 设计模型:最终产生的设计成果,包含
    • 架构图(用包图表示系统的架构结构)
    • 用例实现图(用交互图展示用例的具体实现过程)
    • 类图(精确完整地描述系统中的类及其关系)
    • 以及其他如状态图(描述对象状态变化)、活动图(展示业务流程或操作流程)等模型。

类的分类

主要分为边界类控制类实体类

  • 边界类负责系统与外部的交互,比如机器接口(如 API 接口)和人机交互(用户界面)。
    • 它的作用是在系统和外部环境之间建立联系,例如显示屏、窗体、打印机接口、通信协议、对话框、菜单、购物车、报表、二维码等都属于边界类的实例。
  • 控制类用于实现应用逻辑、业务逻辑和数据访问逻辑
    • 对系统的操作流程和业务规则进行控制。比如身份验证器就是控制类的一个例子。
  • 实体类:主要用于表示数据
    • 对应现实世界中的实体对象。像学员类、课程类,它们用于存储和管理相关的数据信息,反映实体的属性和特征。

七大设计原则:

  • 单一职责原则:强调每个类应该只有一个明确的职责,即设计目的单一的类,这样可以降低类的复杂度,提高可维护性。
  • 开放 - 封闭原则:指软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。即可以通过添加新代码来扩展功能,而不是修改现有代码,增强了软件的稳定性和可扩展性。
  • 李氏(Liskov)替换原则要求子类必须能够替换其基类,并且程序的正确性不受影响,保证了继承体系中对象的可替换性,维持程序的正常运行。
  • 依赖倒置原则:提倡依赖于抽象接口,而非具体实现类,编程时针对接口而非具体类,有助于降低模块间的耦合度,提高系统的灵活性和可维护性。
  • 接口隔离原则:认为使用多个专门的接口比使用一个庞大的总接口更好,避免类被迫实现不需要的接口方法,使系统更加灵活和易于维护。
  • 组合重用原则:建议尽量使用组合关系,而非继承关系来实现代码重用。组合方式能使类之间的耦合度更低,更灵活地构建系统。
  • 迪米特(Demeter)原则(最少知识原则):规定一个对象应该对其他对象有尽可能少的了解,减少对象之间的交互和依赖,降低系统的复杂性和维护成本。

软件测试⭐⭐

软件测试类型

  • 测试分类维度:软件测试分为动态测试静态测试
    • 动态测试是在计算机运行程序的情况下进行测试;
    • 静态测试则通过人工监测和计算机辅助分析,不实际运行程序
  • 测试方法
    • 动态测试方法:包含白盒测试法黑盒测试法灰盒测试法
      • 白盒测试关注程序内部结构和代码逻辑;
      • 黑盒测试从用户角度,注重软件功能;
      • 灰盒测试结合了白盒和黑盒的特点。
    • 静态测试方法:有桌前检查、代码审查和代码走查,这些方法主要进行静态分析
  • 静态分析内容:
    • 控制流分析:检查是否存在未使用语句、无法到达的语句或调用不存在的子程序。
    • 数据流分析:查找引用未定义变量、对未使用过的变量再次赋值等问题。
    • 接口分析:确保模块之间、子程序和函数之间接口的一致性,包括形参与实参的数量、顺序、类型等。
    • 表达式分析:排查括号不配对、数组引用越界、除数为零等错误 。

白盒测试与黑盒测试两种软件测试方法,具体内容如下:

白盒测试

也叫结构测试,主要用于单元测试阶段关注程序内部结构和代码逻辑。包含以下几种测试类型:

  • 控制流测试属于逻辑覆盖测试,其中语句覆盖最弱,路径测试覆盖最强。通过对程序控制流程的分析来设计测试用例。
  • 数据流测试:分析数据在程序中的流动情况,检测数据的定义和使用是否正确。
  • 程序变异测试:也叫错误驱动测试,通过对程序代码进行变异,观察测试用例能否检测出变异后的错误。

黑盒测试

也叫功能测试,主要用于集成测试、确认测试和系统测试阶段,把软件看成一个不透明的盒子,从功能角度进行测试。包含以下几种测试方法:

  • 等价类划分:将输入数据划分为有效等价类和无效等价类,不同等价类能揭示不同问题,通过选取有代表性的数据进行测试。
  • 边界值分析:对输入或输出的边界值进行测试,例如当取值范围是时,选取 0、1、10 和 11 作为测试数据。
  • 错误推测:依靠测试人员的经验和直觉,推测软件可能出现的错误并设计测试用例。
  • 判定表:适合描述多个逻辑条件取值组合下的复杂情况,明确对应要执行的不同动作。
  • 因果图:依据输入条件和输出结果之间的因果关系来设计测试用例 。

软件测试阶段以及 V 模型

V 模型

展示了软件开发过程与软件测试阶段的对应关系,从左到右依次是软件开发的需求分析、概要设计、详细设计、编码阶段,每个阶段对应右侧的测试阶段:

  • 需求分析对应验收测试。
  • 概要设计对应系统测试。
  • 详细设计对应集成测试。
  • 编码对应单元测试。

测试阶段

  • 单元测试:依据详细设计文档,对单个模块进行测试,检查模块的功能、性能、接口等是否符合设计要求。
  • 集成测试:依据概要设计文档测试模块之间的接口,验证模块组合后能否正常工作。
  • 系统测试:依据需求文档,在真实环境下进行测试,验证完整的软件配置项能否与系统正确连接,确保软件系统整体符合需求。
  • 确认测试:同样依据需求文档,验证软件与需求的一致性,包含内部确认测试、Alpha 测试(在开发环境下由用户进行的测试)、Beta 测试(在实际使用环境下由用户进行的测试)以及验收测试 。
  • 回归测试:在软件发生变更后进行,检查变更部分的正确性以及是否符合变更需求,避免变更对软件原有功能产生负面影响。

集成测试策略

集成测试策略分类

  • 一次性组装:将所有模块一次性组合起来进行测试。这种策略风险较高,因为一旦出现问题,定位和修复错误较为困难,很难确定是哪个模块或接口导致的问题。
  • **增量式组装:**逐步将模块添加到已测试的模块集合中进行测试,测试较为全面。它又可细分为:
    • 自顶向下:从顶层模块开始,逐步向下集成。由于下层模块可能还未完成,所以需要使用桩模块来模拟下层模块的功能。
    • 自底向上:从底层模块开始,逐步向上集成。此时需要驱动模块来调用底层模块进行测试。
    • 混合式:结合了自顶向下和自底向上的方法,既需要桩模块也需要驱动模块。

集成测试流程

测试用例输入到驱动模块,驱动模块调用被测模块,被测模块在运行过程中可能会调用桩模块(模拟其依赖的其他未完全实现或未集成的模块),最终得出测试结果 。 桩模块用于模拟被测模块所调用的模块,驱动模块则用于模拟调用被测模块的模块。

系统测试

  • 功能测试:验证软件是否满足需求规格说明中定义的各项功能,确保软件能正常执行其预期任务。
  • 性能测试:评估软件系统在不同条件下的性能表现,包含多个子测试类型:
    • 负载测试:检测系统在各种工作负载下的性能,了解系统在不同压力程度下的运行情况。
    • 压力测试测试系统的上限,找出系统的瓶颈或无法接受的性能点,确定系统能够承受的最大压力。
    • 强度测试:测试系统的下限,观察在系统资源极低(如内存、CPU 资源严重不足)的情况下,软件是否仍能正常运行。
    • 容量测试:也叫并发测试,确定系统能够同时支持的最大在线用户数,评估系统在高并发场景下的性能。
    • 可靠性测试:通过如**平均无故障时间(MTTF)**等参数,衡量系统在规定条件下和规定时间内完成规定功能的能力。
  • 其他测试:
    • 健壮性测试:检查软件在遇到异常情况(如输入错误数据、网络中断等)时,是否具备适当的处理能力,不会崩溃或产生不可恢复的错误。
    • 用户界面测试:评估软件界面的易用性、美观性和一致性,确保用户能够方便、高效地与软件进行交互。
    • 安全性测试:检测软件系统是否存在安全漏洞,防止数据泄露、非法访问等安全问题,保障系统和用户数据的安全。
    • 安装与反安装测试:测试软件的安装过程是否顺利,以及反安装(卸载)后是否能彻底清除所有相关文件和配置信息,不会对系统造成不良影响。

软件维护

遗留系统的演化策略

依据技术水平和业务价值两个维度,将遗留系统分为四种类型,并对应不同策略:

  • 高水平低价值:此类遗留系统技术水平高,但业务价值低,常形成 “信息孤岛”。针对这种情况,采用 “集成” 策略,把它们整合到新系统中,实现信息共享,避免数据孤立。
  • 高水平高价值:这类系统技术和业务价值都高,可进行 “改造”,包括增强系统功能和改造数据模型,使其更好地适应新需求和环境。
  • 低水平低价值技术和业务价值均低的遗留系统,适合 “淘汰” 策略,直接舍弃,避免浪费资源维护和升级。
  • 低水平高价值:虽然技术水平低,但业务价值高,采用 “继承” 策略,在开发新系统时,要完全兼容其功能模型和数据模型,保留其高价值的业务功能 。

新旧系统之间的三种转换策略

  • 直接转换策略直接停用现有系统,启用新系统。这种方式简单直接,成本较低,但风险较大,一旦新系统出现问题,可能会对业务造成严重影响,适合对新系统有充分信心且业务允许短时间中断的情况。
  • 并行转换策略现有系统和新系统同时运行一段时间。在这段时间内,对比两者的运行结果,确保新系统稳定可靠后,再停用现有系统。该策略风险较低,但需要双倍的资源来维持两个系统的运行,成本较高,适用于对系统可靠性要求极高的业务。
  • 分段转换策略将新系统的转换过程分为多个阶段,逐步替换现有系统的各个部分。这种策略结合了直接转换和并行转换的优点,既可以降低风险,又不会像并行转换那样耗费过多资源,适用于规模较大、业务复杂的系统转换 。

数据转换与迁移过程(了解)

  • 抽取:从旧数据库中提取相关数据。这是数据迁移的第一步,需要确定要抽取的数据范围和抽取方式。
  • 转换:对抽取出来的数据进行格式、结构或内容上的转换,使其符合新数据库的要求。因为旧系统和新系统的数据标准、类型等可能不同,所以转换步骤很关键。
  • 装载:将转换后的数据加载到新数据库中,完成数据的迁移。

三种数据迁移的时机和方式:

  • 系统切换前通过工具迁移:在新系统正式启用前,利用专门的数据迁移工具将旧数据库中的数据迁移到新数据库。
  • 系统切换前采用手工录入:对于少量关键数据或者工具无法处理的数据,在系统切换前安排人工手动录入到新系统数据库中。
  • 系统切换后通过新系统生成:在新系统投入使用后,新产生的数据直接按照新系统的规则生成并存储在新数据库中 。

影响可维护性的因素

  • 可理解性:指通过阅读软件的源代码以及相关文档,能够轻松了解软件具备的功能和运行机制的程度。可理解性高的软件,维护人员能更快上手,降低维护难度。
  • 可修改性:表示对软件进行修改操作的难易程度。若软件架构设计良好、代码结构清晰,那么在修复缺陷或增加功能时会更便捷,可修改性就高。
  • 可测试性:用于衡量验证软件程序正确性的难易情况。一般来说,设计简单、复杂度低的软件,其可测试性较好,因为复杂的软件在测试时需要考虑更多情况,难度更大。
  • 可靠性:软件可靠性越高,出现故障和错误的概率就越低,相应地,需要进行维护的可能性也就越小,能减少维护成本和工作量。
  • 可移植性:是指将软件从一个运行环境转移到另一个新环境,并能正确运行的难易程度。当软件运行环境发生变化(如更换操作系统、硬件平台等)时,可移植性好的软件能更轻松地适应新环境,从而降低因环境变化引发的维护需求 。

软件维护的四种类型

  • 正确性维护:主要任务是识别并纠正软件中存在的错误或缺陷,也就是通常所说的 “修 BUG”。由于测试的局限性,不可能发现软件中的所有错误,因此在软件使用过程中需要进行正确性维护来修复这些潜在问题。
  • 适应性维护:当软件运行的外部环境(如操作系统升级、硬件更换)或数据环境(如数据库结构变更)发生变化时,为了使应用软件能够继续正常运行,需要进行适应性维护,让软件适应这些新的变化。
  • 完善性维护:基于用户提出的新需求,对软件进行功能扩充或性能改善的维护工作。例如增加新的功能模块、优化软件的运行速度等,以提升软件的整体质量和用户体验。
  • 预防性维护:着眼于未来,为了应对将来可能出现的软硬件环境变化,主动为软件增加一些预防性的新功能,使软件能够更好地适应未来的各类变化,避免被快速淘汰。比如将专用软件改造为通用软件,以扩大其适用范围 。