软考高级架构考点——软件工程:软件过程模型 ⭐️⭐️⭐️⭐️、基于构件的软件⼯程 ⭐️⭐️、逆向⼯程 ⭐️、净室软件⼯程 ⭐️、需求⼯程 ⭐️⭐️、系统分析与设计 ⭐️⭐️、软件测试 ⭐️⭐️、系统运⾏与软件维护 ⭐️
!important
1 软件过程模型 ⭐️⭐️⭐️⭐️
软件过程模型(Software Process Model,SPM):软件过程是制作软件产品的一组活动以及结果,这些活动主要由软件人员来完成。软件活动主要有:
- 软件描述:必须定义软件功能以及使用的限制。
- 软件开发:即软件的设计和实现,软件工程人员制作出能满足描述的软件。
- 软件有效性验证:软件必须经过严格的验证,以保证能够满足客户的需求。
- 软件进化:软件随着客户需求的变化不断地改进。
按照传统的软件生命周期方法学,可以将软件生命周期(系统生命周期,System Development Life Cycle,SDLC)划分为软件定义、软件开发、软件运行与维护3个阶段。其主要活动阶段包括:可行性分析与计划制订、需求分析、软件设计(概要设计和详细设计)、软件实现(编码)、测试、维护等活动,其中软件开发阶段包括软件设计、实现与测试。
1.1 瀑布模型
瀑布模型(Waterfall Model)将SDLC中的各个活动规定为线性顺序连接的若⼲阶段(如图所示)。

特点:
- 严格区分阶段,每个阶段因果关系紧密相连
- 只适合需求明确的项⽬
缺点:
- 软件需求完整性、正确性难确定(大部分开发项目需求不明确)
- 严格串⾏化,很⻓时间才能看到结果
- 瀑布模型要求每个阶段⼀次性完全解决该阶段⼯作,这不现实
效果奇差,项目失败率95%
1.2 原型模型
原型模型(Prototype Model)即典型的原型开发⽅法,一般用在需求阶段,适合需求不明确的项目。

原型模型两个阶段:
- 原型开发阶段
- ⽬标软件开发阶段
从原型的最终结果来分,可以分为:
- 【抛弃型原型】/快速原型(Rapid Prototyping)/探索式原型:达到预期⽬的后,原型本身被抛弃。抛弃式原型主要⽤在解决需求不确定性、⼆义性、不完整性、含糊性等。
- 【演化型原型】:为开发增量式产品提供基础,逐步将原型演化成最终系统,主要⽤在必须易于升级和优化的场合,适合于Web项⽬。
在本章开头的“原型及相关模型之间的关系”图中,增量模型融合了瀑布模型的基本成分和原型。
从原型是否实现功能来分,可以分为:
- ⽔平原型(也称为⾏为原型):⽤来探索预期系统的⼀些特定⾏为,并达到细化需求的⽬的。⽔平原型通常只是功能的导航,但未真实实现功能。主要⽤在界⾯上。
- 垂直原型(也称为结构化原型):实现了⼀部分功能。垂直原型主要⽤在复杂的算法实现上。
1.3 V模型
V模型(V-Shape Model)是⼀种测试的开发模型,强调测试贯穿项⽬始终,⽽不是集中在测试阶段。(详见软件测试阶段)

W模型(W-Shape Model)强调测试和开发【并⾏进⾏】。
1.4 增量模型与迭代模型
增量模型(Incremental Model)与迭代模型(Iterative Model)的区别如图例所示。

增量:顺次添加个体。迭代:整体逐渐变好
两者常同时出现
增量模型与瀑布模型对比:
- 优点:降低了实现需求变更的成本。相较瀑布模型而言,重新分析和修改文档的工作流要少很多。在开发过程中更容易得到客户对已完成的开发工作的反馈意见。客户可以对软件的已有版本进行评价,并可以判断项目进度(通常难以直接从软件设计文档中评价项目、判断项目进度)。即使未实现所有功能,也可以在早期即向客户交付有用的软件,相较瀑布模型而言,客户可以更早地使用软件。
- 缺点:过程不可见。管理人员需要常规的交付物来掌握进度。若系统是快速开发的,则要产生每一个版本的文档,很不划算。伴随新增量的加入,系统结构会退化。
- 敏捷方法建议定期对软件重构。面对大型、复杂以及长生命周期的系统,增量模型的以上缺点更为突出。
- 大型系统不同部分由不同团队开发,需要稳定的框架或体系结构,这种体系结构需要事先进行计划而不是增量地开发。
1.5 螺旋模型
螺旋模型(Spiral Model)以快速原型为基础,叠加了瀑布模型(前一层的结果是后一层的原型)。如图所示,将开发流程分成了4个象限,特别地,螺旋模型考虑了【⻛险分析】。

- 演化模型跟螺旋模型,增量模型,原型法开发的关系?
- 答
- 与原型化的关系:原型化可分为两种——抛弃式原型和演化式原型,其中最终演化成⼀个产品的就演变成为演化模型。
- 螺旋模型是通过演化模型和瀑布模型的结合所产⽣的,并且螺旋模型强调了⻛险管理。
- 增量模型是原型模型和瀑布模型所结合⽽产⽣的。
- 螺旋模型和增量模型的区别?
- 答:螺旋模型“⼀直旋下去”,旋到最后才是⼀个产品,⽽增量模型每⼀个增量都发布了⼀个可操作的产品。
1.6 构件组装模型、基于构件的软件⼯程(CBSE)
更多构件相关内容详见软件架构设计-构件与中间件技术
构件组装模型(Component Model)的基本思想为先构造构件,再将这些构件组装起来。
流程:
- 需求分析定义
- 设计构件组装(体系结构设计)
- 建立构件库
- 构建应用软件
- 测试和发布
优点:易扩展、易重⽤、降低成本、安排任务更灵活。
缺点:构件设计要求经验丰富的架构师、设计不好的构件难重⽤、强调重⽤可能牺牲其它指标(如:性能)、第三⽅构件质量难控制。
示例:方舱医院、乐高积木

基于构件的软件⼯程(Component-Based Software Engineering,CBSE)是一种基于分布对象技术、强调通过可复用构件设计与构造软件系统的软件复用途径。CBSE拓宽了构件组装模型的思想,体现了“购买⽽不是重新构造”的哲学,方方面面都考虑到构件。
CBSE的构件应具备的特征:
- 可组装性:所有外部交互必须通过公开定义的接⼝进⾏。
- 可部署性:构件总是⼆进制形式的,能作为⼀个独⽴实体在平台上运⾏。
- ⽂档化:⽤户根据⽂档来判断构件是否满⾜需求。
- 独⽴性:可以在⽆其他特殊构件的情况下进⾏组装和部署。
- 标准化:符合某种标准化的构件模型。
构件(Component)是软件系统中具有一定意义的、相对独立的可重用单元。与对象相比,构件可以基于对象实现,也可以不作为对象实现。CBSE中的构件可以是COTS(Commercial-Off-The-Shelf)构件,也可以是通过其他途径获得的构件(如自行开发)。
容器(Container)用于管理构件并使构件获取容器提供的服务,客户程序可以在运行状态下利用接口动态确定构件所支持的功能并调用。容器是构件模型的基础设施,它提供了构件运行所需的支持服务(如事务管理、安全性、持久化等),并定义了构件与容器之间的接口。容器的作用是管理构件的生命周期、提供运行时环境,并确保构件能够与其他构件协同工作。
在软件复用领域,一般观点认为构件是一个独立的软件单元,可以与其他构件构成一个软件系统。然而也有其他专家提出了其他的构件定义。不管构件如何定义,用于CBSE的构件应具备以下特征:
- 可组装型:对于可组装的构件,所有外部交互必须通过公开定义的接口进行。同时它还必须对自身信息的外部访问。
- 可部署性:软件必须是自包含的,必须能作为一个独立实体在提供其构件模型实现的构件平台上运行。构件总是二进制形式,无须在部署前编译。
- 文档化;构件必须是完全文档化的,用户根据文档来判断构件是否满足需求。
- 独立性:构件应是独立的,应可在无其他特殊构件的情况下进行组装和部署,如确实需要其他构件提供服务,则应显式声明。
- 标准化:构件标准化意味着在CBSE过程中使用的构件必须符合某种标准化的构件模型。构件模型包含了一些【模型要素】,这些要素信息定义了构件接口、在程序中使用构件需要知道的信息,以及构件应该如何部署——
- 【接⼝】:构件通过构件接⼝来定义,构件模型规定应如何定义构件接⼝以及在接⼝定义中应该包含的要素,如操作名、参数以及异常等。
- 【使⽤信息】:为使构件远程分布和访问,必须给构件⼀个特定的、全局唯⼀的名字或句柄。构件元数据是构件本身相关的数据,⽐如构件的接⼝和属性信息。⽤户可以通过元数据找到构件提供的服务。构件模型的实现通常包括访问构件的元数据的特定⽅法。构件是通⽤实体,在部署的时候,必须对构件进⾏配置来适应应⽤系统。
- 【部署】:构件模型包括⼀个规格说明,指出应该如何打包构件使其部署成为⼀个独⽴的可执⾏实体。部署信息中包含有关包中内容的信息和它的⼆进制构成的信息。
基于构件的软件开发中的两种模型:
- 逻辑构件模型:用功能包描述系统的抽象设计,用接口描述每个服务集合,以及功能之间如何交互以满足用户需求,它作为系统的设计蓝图以保证系统提供适当的功能
- 物理构件模型:用技术设施产品、硬件分布和拓扑结构、以及用于绑定的网络和通信协议描述系统的物理设计,这种架构用于了解系统的性能、吞吐率等许多非功能性属性
CBSE过程的主要步骤:
- 系统需求概览:明确系统的需求和目标。
- 识别候选构件:寻找可复用的构件来满足需求。
- 根据发现的构件修改需求:根据可用的构件调整系统需求。
- 体系结构设计:设计系统的整体架构,确定构件的组装方式。
- 构件定制与适配:对构件进行定制或编写适配器以解决接口不兼容问题。
- 组装构件,创建系统:将构件组装成完整的系统。构件的组装⼀般都要借助胶⽔代码,根据组装维度可分为如下几类:
- 顺序组装:按顺序调⽤已经存在的构件,可以⽤两个已经存在的构件来创造⼀个新的构件。
- 层次组装:被调⽤构件的“提供”接⼝必须和调⽤构件的“请求”接⼝兼容。(分层)
- 叠加组装:多个构件合并形成新构件,新构件整合原构件的功能,对外提供新的接⼝。
组装可能出现3种不兼容:参数不兼容、操作不兼容、操作不完备。
1.7 快速应⽤开发(RAD)
快速应⽤开发(Rapid Application Development,RAD)在⽣命周期中引入基于构件的开发,由此实现快速开发。
组成:SDLC(瀑布模型)、CBSD(基于构件)
过程:业务建模 → 数据建模 → 过程建模 → 应⽤⽣成 → 测试与交付

适⽤性:RAD对模块化要求⽐较⾼,如果某项功能不能被模块化,则其构件就会出问题;如果⾼性能是⼀个指标,且必须通过调整结构使其适应系统构件才能获得,则RAD也有可能不能奏效;RAD要求开发者和客户必须在很短的时间完成⼀系列的需求分析,任何⼀⽅配合不当都会导致失败;RAD只能⽤于管理信息系统的开发,不适合技术⻛险很⾼的情况。
1.8 统⼀过程(UP/RUP)
在软考中,UP、RUP都指统⼀过程
统一过程((Rational) Unified Process,(R)UP)是一种迭代增量式的软件开发方法论,它强调将系统开发过程分为一系列的迭代周期,在每一轮迭代中都要进行测试与集成。
核心特点:
- ⽤例驱动
- 以架构为中⼼
- 迭代和增量
- 优点:
- 降低了在一个增量上的开支风险。如果开发人员重复某个迭代,那么损失只是这一个开发有误的迭代的花费。
- 降低了产品无法按照既定进度进入市场的风险。通过在开发早期就确定风险,可以尽早来解决而不至于在开发后期匆匆忙忙。
- 加快了整个开发工作的进度。因为开发人员清楚问题的焦点所在,他们的工作会更有效率。
- 由于用户的需求并不能在一开始就作出完全的界定,它们通常是在后续阶段中不断细化的。因此,迭代过程这种模式使适应需求的变化会更容易些。
- 优点:
统⼀过程把⼀个项⽬分为4个不同的阶段:
- 初始(构思/初启):定义最终产品视图和业务模型;确定系统范围。
- 细化(精化):设计及确定系统架构(建立完善的架构);制定⼯作计划及资源要求。
- 构造:开发剩余构件和应⽤程序功能,把这些构件集成为产品,并进⾏详细测试。
- 移交:确保软件对最终⽤户是可⽤的,进⾏β测试,制作产品发布版本。

9个核⼼⼯作流与上述4个阶段组成二维工作流程,如下所示(其中需求、分析与设计、实现、测试、部署正是日常软件开发的核心步骤):
- 业务建模
- 需求
- 分析与设计
- 实现
- 测试
- 部署
- 配置与变更管理
- 项目管理
- 环境

1.9 敏捷开发
敏捷开发(Agile Development)以原型开发思想为基础,采用迭代增量式开发,是⼀种以⼈为核⼼、迭代、循序渐进的开发⽅法,适⽤于⼩团队和⼩项⽬,具有⼩步快跑的思想。
特点:
- “适应性”(Adaptive)而非“预设性”(Predictive)
- 以人为本:面向人(People-Oriented)而非面向过程(Process-Oriented)
- 增量迭代,⼩步快跑
- 发行版本小型化,适合小型项目(不适合开发团队较为庞大的项目)
- 适合需求变化较大或者开发前期对需求不是很清晰的项目

敏捷宣⾔:
- 个体和交互胜过过程和⼯具
- 可⼯作的软件胜过⼤量的⽂档
- 客户合作胜过合同谈判
- 响应变化胜过遵循计划
常⻅的敏捷开发⽅法:
- 极限编程(ExtremeProgramming,XP):⼀些对费⽤控制严格的公司中的使⽤,⾮常有效,近螺旋式的开发⽅法。
- 4⼤价值观:沟通【加强⾯对⾯沟通】、简单【不过度设计】、反馈【及时反馈】、勇⽓【接受变更的勇⽓】
- 12条过程实践规则:简单设计、测试驱动、代码重构、结对编程、持续集成、现场客户、发⾏版本⼩型化、系统隐喻、代码集体所有制、规划策略、规范代码、40⼩时⼯作机制
- ⽔晶⽅法(Crystal):提倡“机动性”的⽅法,拥有对不同类型项⽬⾮常有效的敏捷过程。
- SCRUM:侧重于项目管理,明确定义了可重复的⽅法过程。
- 功用驱动开发方法/特征驱动开发⽅法(Feature Driven Development,FDD):认为有效的软件开发需要3要素——【⼈、过程、技术】(要素 ⇒ 特征)
- 定义了6种关键的项⽬⻆⾊:项⽬经理、⾸席架构设计师、开发经理、主程序员、程序员和领域专家。
- 编程开发人员分成首席程序员和“类”程序员
- 开放式源码(Open Source):程序开发⼈员在地域上分布很⼴【其他⽅法强调集中办公】。
- ASD⽅法:其核⼼是三个⾮线性的、重叠的开发阶段:猜测、合作与学习。
- 动态系统开发⽅法(Dynamic Systems Development Method,DSDM):倡导以业务为核⼼。
2 逆向工程 ⭐️
逆向⼯程(Reverse Engineering)是设计的恢复过程,通过分析已有的程序,寻求比源代码更高级的抽象表现形式。一般认为,凡是在软件生命周期内将软件某种形式的描述转换成更为抽象形式的活动均可称为逆向工程。可分为如下4个等级:
- 实现级:包括程序的抽象语法树、符号表、过程的设计表示。(程序的实现过程)
- 结构级:包括反映程序分量之间相互依赖关系(结构)的信息,例如调⽤图、结构图、程序和数据结构。
- 程序分量:程序和相关的数据结构信息,泛指函数,过程和类的代码等
- 功能级:包括反映程序段功能及程序段之间关系的信息,例如数据和控制流模型。
- 领域级:包括反映程序分量或程序诸实体与应⽤领域概念之间对应关系的信息,例如实体关系模型。

与逆向⼯程相关的概念有重构、设计恢复、再⼯程和正向⼯程。各概念的对比如下:
- 重构/重组(Restructuring):在【同⼀抽象级别】上转换系统描述形式。
- 设计恢复(Design Recovery):借助⼯具从已有程序中抽象出有关数据设计、总体结构设计和过程设计等⽅⾯的信息。
- 逆向⼯程(Reverse Engineering):分析程序,⼒图在⽐源代码更⾼抽象层次上建⽴程序的表示过程,逆向⼯程是设计的恢复过程。
- 正向⼯程(Forward Engineering)。不仅从现有系统中恢复设计信息,⽽且使⽤该信息去改变或重构现有系统,以改善其整体质量。
- 再⼯程/重构⼯程(Re-engineering):对现有系统的重新开发过程,包括逆向⼯程、新需求的考虑过程和正向⼯程三个步骤。
3 软件开发方法 ⭐️
软件开发方法是指软件开发过程所遵循的办法和步骤,从不同的角度可以对软件开发方法进行不同的分类。
3.1 形式化方法
形式化方法(Formal methods)是一种具有坚实数学基础的方法,从而允许对系统和开发过程做严格处理和论证,适用于那些系统安全级别要求极高的软件的开发。
根据描述方式,形式化方法可以分为模型描述和性质描述两类。【拓展】
形式化方法的主要优越性在于它能够数学地表述和研究应用问题及软件实现。但是它要求开发人员具备良好的数学基础。用形式化语言书写的大型应用问题的软件规格说明往往过于细节化,并且难以为用户和软件设计人员所理解。由于这些缺陷,形式化方法在目前的软件开发实践中并未得到普遍应用。
3.2 净室软件⼯程
净室软件⼯程(Cleanroom Software Engineering,CSE)是软件开发的一种形式化方法,可以开发较高质量的软件。净室即⽆尘室、洁净室,即⼀个受控污染级别的环境。
CSE使⽤盒结构规约(或形式化⽅法)进⾏分析和设计建模,并且强调将正确性验证,⽽不是测试,作为发现和消除错误的主要机制。使⽤统计的测试来获取认证被交付的软件的可靠性所必需的出错率信息。CSE强调在规约和设计上的严格性,还强调统计质量控制技术,包括基于客户对软件的预期使用测试。
技术⼿段:
- 统计过程控制下的增量式开发:控制迭代
- 基于函数的规范和设计:盒⼦结构
- 定义3种抽象层次:⾏为视图(⿊盒) → 有限状态机视图(状态盒) → 过程视图(明盒)
- 正确性验证(净室⼯程的核⼼)
- 统计测试和软件认证:使⽤统计学原理,总体太⼤时必须采⽤抽样⽅法。
缺点:
- 太理论化,正确性验证的步骤⽐较困难且耗时。
- 开发⼩组不进⾏传统的模块测试,这是不现实的。
- 脱胎于传统软件⼯程,不可避免带有传统软件⼯程的⼀些弊端。
4 需求工程 ⭐️⭐️
软件需求(Software Requirements)是指⽤户对系统在功能、⾏为、性能、设计约束等⽅⾯的期望。
分类:

老教材分2层,新教材分5层
其中需求分析可分为结构化需求分析与面向对象需求分析。
4.1 需求获取
需求获取(Requirement Elicitation)涉及的内容如下图所示:

4.1.1 需求分类与获取方法
需求按层次分类:
- 业务需求:反映企业或客户对系统高层次的目标要求,通常来自项目投资人、购买产品的客户、客户单位的管理人员、市场营销部门或产品策划部门等。通过业务需求可以确定项目视图和范围,项目视图和范围文档把业务需求集中在一个简单、紧凑的文档中,该文档为以后的开发工作奠定了基础。(整体全局)
- 用户需求:用户的具体目标,或用户要求系统必须能完成的任务,即用户能用系统来做些什么。通常采取用户访谈和问卷调查等方式,对用户使用的场景(Scenarios)进行整理,从而建立用户需求。(用户视角)
- 系统需求:从系统的角度来说明软件的需求,可细分为如下几类:
- 功能需求(行为需求):规定了开发人员必须在系统中实现的软件功能,用户利用这些功能来完成任务,满足业务需要。功能需求通常通过系统特性的描述来表现,所谓特性,是指一组逻辑上相关的功能需求,表示系统为用户提供某项功能(服务),使用户的业务目标得以满足
- 非功能需求:系统必须具备的属性或品质,又可细分为软件质量属性(例如性能、可维护性、效率等)和其他系统架构设计中的非功能需求。(计算机化)
- 设计约束:例如“要求采用国有自主知识产权的数据库”等需求。
质量功能部署(Quality Function Deployment,QFD)是一种将用户要求转化成软件需求的技术,其目的是最大限度地提升软件工程过程中用户的满意度(来自项目管理制度,“该做的都得做,不该做的绝不做”)。为了达到这个目标,QFD将软件需求分为以下三类:
- 常规需求(基本需求):用户认为系统应该做到的功能或性能,实现越多用户会越满意。(明示)
- 期望需求:用户想当然认为系统应具备的功能或性能,但并不能正确描述自己想要得到的这些功能或性能需求。如果期望需求没有得到实现,会让用户感到不满意。(隐含)
- 意外需求(兴奋需求):用户要求范围外的功能或性能(但通常是软件开发人员很乐意赋予系统的技术特性),实现这些需求用户会更高兴,但不实现也不影响其购买的决策。意外需求是控制在开发人员手中的,开发人员可以选择实现更多的意外需求,以便得到高满意、高忠诚度的用户,也可以(出于成本或项目周期的考虑)选择不实现任何意外需求。(多余)
需求获取方法:
- ⽤户⾯谈:1对1-3,有代表性的⽤户,了解主观想法,交互好。成本⾼,要有领域知识⽀撑。
- 联合需求计划(Joint Requirements Planning,JRP):⾼度组织的群体会议,各⽅参与,了解想法,消除分歧,交互好,成本⾼。主要意图是【收集需求】(而不是对需求进行分析和验证)。实施JRP时应把握以下主要原则:
- 在JRP实施之前,应制订详细的议程,并严格遵照议程进行。
- 按照既定的时间安排进行。
- 尽量完整地记录会议期间的内容。
- 在讨论期间尽量避免使用专业术语。
- 充分运用解决冲突的技能。
- 会议期间应设置充分的间歇时间。
- 鼓励团队取得一致意见。
- 保证参加JRP的所有人员能够遵守事先约定的规则。
- 问卷调查:⽤户多,⽆法⼀⼀访谈,成本低。
- 现场观察:针对较为复杂的流程和操作。
- 原型化⽅法:通过简易系统⽅式解决早期需求不确定问题。
- 头脑⻛暴法:⼀群⼈围绕新业务,发散思维,不断产⽣新的观点。
4.1.2 需求抽取
拓展
需求抽取(Requirement Extraction)通常为一个迭代过程,目的是理解利益相关者(Stakeholders)所做的事情以及他们会如何使用一个新系统来支持他们的工作。(常见于ABSD)
从系统利益相关者那里抽取和理解需求是一个困难的过程,主要原因有:
- 利益相关者经常不知道他们想从一个计算机系统中得到什么,除了一些非常宽泛的说法;他们经常难以表述清除想让系统做的事;他们可能会提出一些不切实际的要求,因为他们不知道哪些可行哪些不可行。
- 一个系统中的利益相关者会很自然地用其自己的话来表达需求,其中隐含着一些关于其自己工作的知识。
- 不同的利益相关者有各种不同的需求,他们会以不同的方式表达他们的需求。
- 政治性因素可能影响系统的需求。
- 进行需求分析时所处的经济和业务环境是动态的,不可避免地会在分析过程中发生变化。
需求抽取和分析的过程主要分为以下四个步骤:
- 需求发现和理解
- 需求分类和组织
- 需求优先级排序和协商
- 需求文档化
需求抽取有两个基本方法:
- 访谈:开发者和其他人谈论他们做的事情。
- 观察或人种学调查:观察人们做自己的工作来了解他们使用哪些制品、他们如何使用这些制品等。
4.2 结构化需求分析(SA)
结构化分析(Structured Analysis,SA)又称为面向功能的软件开发方法或面向数据流的软件开发方法,主要工具有DFD、STD、E-R图等(如下图所示)。除此之外,最中心的数据字典(Data Dictionary)是描述数据(数据项、数据结构、数据流、数据存储、处理逻辑等)的信息集合,是对系统中使用的所有数据元素的定义的集合。

在结构化分析中,主要进行三个方面的建模:功能建模(DFD)、行为建模(STD)和数据建模(ER图)。
4.2.1 数据流图(DFD) ☀️
数据流图(Data Flow Diagram,DFD)是极为常用的结构化分析工具,能够分层地进行功能建模。
组成元素:
- 数据流:由一组固定成分的数据组成,表示数据的流向。每个数据流通常有一个合适的名词,反映数据流的含义。
- 加⼯:描述了输入数据流到输出数据流之间的变换,即输入数据流做了什么处理后变成了输出数据流。
- 数据存储(文件):暂时存储的数据,每个文件都有名字。流向文件的数据流表示写文件,流出的表示读文件。
- 外部实体:存在于软件系统外的人员或组织。
图元如下:

数据流图具有层次结构,十分契合结构化思想。可将父图拆解为若干子图,如下图所示:

其中,最上层的图称为顶层图(详细内容见下图上半部分),可表示的信息十分有限。保持外部实体不变,对顶层图的系统进行拆解/细化可得其子图,即0层图(详细内容见下图下半部分)。该0层图又可拆解为3个加工子图(见下图1、2、3,亦即上图最低层)。

数据流图中的平衡:父图与子图之间的平衡、子图内平衡。(输入/输出一一对应,不可缺失)
异常现象:
- 黑洞:一个加工只有输入数据流而无输出数据流。
- 奇迹:一个加工只有输出数据流而无输入数据流。
- 灰洞:若一个加工的输入数据流无法通过加工产生输出流。

案例分析题型与技巧:
- 详细分析试题说明:根据题干,从整体上分析各成分之间的关系
- 利用数据平衡原则:不建议直接看整体,先单个结点地利用平衡原则进行分析。
- 补充内容
- 补充实体:
- 人物角色:客户、管理员、主管、经理、老师、学生……
- 组织机构:银行、供应商、募捐机构……
- 外部系统:银行系统、工资系统、后台数据库(当要开发的是中间件时)……
- 补充存储:“(?)文件”“(?)表”“(?)库”“(?)清单”“(?)档案”
- 补充数据流
- 数据平衡原则
- 顶层图与0层图对比,是否有顶层图有,但0层图无的数据流,或反之。
- 检查图中每个加工是否存在只有入没有出,或只有出没有入,或根据输入的数据无法产生对应的输出的情况。
- 按题目说明与图进行匹配:说明中的每一句话,都能与图中有对应关系。标出说明中的实体与数据流来缩小对应范围,找出纰漏。
- 补充加工名:因为加工用于处理数据流,故可以在说明中标出该加工涉及到的数据流,再在该数据流名所在的句子中,找“动词+名词”的结构,分析是否可作为加工。
- “动词+名词”例:生成报告、发出通知、批改作业、记录分数。(存在例外情况。如物流跟踪、用户管理等)
4.2.2 状态转换图(STD)
状态转换图(State Transform Diagram,STD)即“流程图”,用于进行结构建模。了解即可。
组成元素:
- 状态(初态、终态)
- 事件
示例:

4.2.3 E-R图
E-R图(Entity Relationship Diagram,实体关系图)用于进行数据建模。详见数据库系统篇,此处不多赘述。
示例:

4.3 ⾯向对象需求分析(OOA) ☀️
面向对象分析(Object-Oriented Analysis,OOA)在面向对象方法论的指导下逐渐取代了SA。目前广为使用的OOA建模工具为UML图,极为重要,以下将详细介绍UML这种建模语言。
UML(Unified Modeling Language,统一建模语言)整合了所有OOA建模方法,平台无关、语言无关。UML 2.0基础结构的设计目标是定义一个元语言的核心——基础架构库(Infrastructure Library)。通过对此核心的复用,除了可以定义一个自展的UML元模型(Meta Model)——定义了构造UML模型各种基本元素的基础结构——也可以定义其他元模型,包括MOF(Meta-Object Facility,元对象机制)和CWM(Common Warehouse Model,公共仓库模型)。由于共用核心库,故UML和MOF、CWM在体系结构上更加一致。同时,基础架构库还提供了定制UML更强有力的机制,允许用户定义针对不同平台(如.NET、J2EE等)和领域(如电信、金融、系统工程)的语言。
UML组成如下所示:
- 构造块
- 事务
- 结构事物:最静态的部分。包括:类、接口、协作、用例、活动类、构件和节点。
- 行为事物:代表时间和空间上的动作。包括:消息、动作次序、连接。
- 分组事物:看成是个盒子。包括:包、构件。
- 注释事物:UML模型的解释部分,描述、说明和标注模型的元素。
- 关系
- 图
- 事务
- 规则
- 范围:给一个名字以特定含义的语境
- 可见性:怎样使用或看见名字
- 完整性:事物如何正确、一致地相互联系
- 执行:运行或模拟动态模型的含义是什么
- 公共机制
- 规格说明:事物语义的细节描述,是模型真正的核心
- 修饰:通过修饰来表达更多的信息
- 公共分类:类与对象、接口与实现
- 扩展机制:允许添加新的规则
在初步的业务需求描述已经形成的前提下,基于UML的需求分析过程大致可分为以下步骤:
- 利用【用例及用例图】表示【需求】。从业务需求描述出发获取执行者和场景;对场景进行汇总、分类、抽象,形成用例;确定执行者与用例、用例与用例图之间的关系,生成用例图。【例】
- 利用【包图和类图】表示目标软件系统的【总体框架结构】。根据领域知识、业务需求描述和既往经验设计目标软件系统的顶层架构;从业务需求描述中提取“关键概念”,形成领域概念模型;从概念模型和用例出发,研究系统中主要的类之间的关系,生成类图。【包】
4.3.1 UML图的分类
UML2.0中常用的14种图:
静态图(结构图):
- 类图(Class Diagram):⼀组类、接⼝、协作和它们之间的关系。(呈现类的关系)
- 对象图 (Object Diagram):⼀组对象及它们之间的关系。对象图描述了在类图中所建立的事物实例的静态快照。(呈现对象的关系,形式上与类图完全一致)
- 构件图(Component Diagram):类图的变体,描述一个封装的类及其接口、端口,以及由内嵌的构件和连接件构成的内部结构。构件图用于表示系统的静态设计实现视图。对于由小的部件构建大的系统来说,构件图相当重要。
- 包图:软件体系结构图。把共同工作的元素(例如多个类或构件)放到一个包中。由模型本身分解⽽成的组织单元,以及它们之间的依赖关系。
- 部署图 (Deployment Diagram):描述对运行时的处理节点及在其中生存的构件的配置。给出了架构的静态部署视图,通常一个节点包含一个或多个部署图。(软硬件之间映射)
- 制品图:系统的物理结构。
- 组合结构图
动态图(行为图)(顺序图、通信图、定时图、交互概览图合称交互图):
- ⽤例图:描述一组用例、参与者及它们之间的关系。系统与外部参与者的交互。
- 顺序图(Sequence Diagram):强调对象之间消息发送的顺序(操作标有序号),同时显示对象之间的复杂交互过程。
- 通信图(Communication Diagram):强调对象之间存在的消息收发关系,而不专门突出这些消息发送的时间顺序。
- 定时图:用于展示交互过程中的真实时间信息,具体描述对象状态变化的时间点以及维持特定状态的时间段。强调实际时间。
- 状态图(State Diagram):对类描述的补充,针对复杂对象。用于展现此类对象所具有的可能状态(即结点),以及某些事件发生时其状态转移情况。
- 活动图(Activity Diagram):一种特殊的状态图,描述一个操作中要进行的各项活动(与状态图不同)的执行流程。同时,也常被用来描述一个用例的处理流程或者某种交互流程。将进程或其他计算结构展示为计算内部一步步的控制流和数据流,强调对象间的控制流程。存在并行行为。
- 交互概览图:用例实现图
4.3.1.1 用例图
用例图(Use Case Diagram)属于动态图,描述一组用例、参与者及其之间的关系,从用户角度描述系统功能。
组成:
- 参与者:外部触发因素(包括用户、组织、外部系统、时间、温度等)
- 用例:功能单元

用例的3种关系:
- 包含(Include):当可以从两个或多个用例中提取公共行为时,可以使用包含关系来表示。
- 扩展(Extend):如果一个用例混合了两种或两种以上不同场景,即根据情况可能发生多种分支,则可以将这个用例分为一个基本用例和一个或多个扩展用例。
- 泛化(Generalization):当多个用例共同拥有一个类似的结构和行为的时候,可以将它们的共性抽象成父用例,其他的用例作为泛化关系中的子用例。
【参与者和用例】之间有关联关系,用例与用例、【参与者与参与者】之间有泛化关系(继承关系)。
【技巧】箭头
A -(do)→ B的含义:“It is A that 'does' B.”(后同)
用例建模的流程:
- 识别参与者(必须)
- 合并需求获得用例(必须)
- 细化用例描述(必须),如下图的用例规约所示:

- 调整用例模型(可选):根据上述3种关系
【例】某软件公司拟为物流企业开发一套库存管理系统,该系统的部分需求陈述如下:
(1)库存管理系统主要包括货物入库管理、货物出库管理、仓库管理、统计报表和系统管理等功能。
(2)库存管理系统的用户包括仓库管理员、仓库经理和系统管理员,用户必须在注册后才能使用系统功能;用户可以选择使用邮件注册或电话注册。
(3)仓库管理员在进行出入库操作前必须先登录;仓库经理可以通过系统查看统计报表,如果前一个月的报表未生成,则系统自动生成统计报表,否则直接显示。
(4)系统管理员可以在系统中设置仓库温度范围,当仓库内温度超过最高值或者低于最低值时,系统自动调用温控管理操作,连接温度调节系统进行制冷或加热。
(5)仓库管理功能要求每个月1日零点对前一个月货物入库和出库记录进行数据汇总操作。项目组决定构造用例模型以描述系统需求。
问题1(6分):
用例建模的首要任务是识别系统中的参与者。请根据题目中所描述的需求,识别出系统中有哪些参与者?
问题2(7分):
用例建模的主要工作是书写用例规约。用例规约通常包括哪几部分内容?
问题3(12分):
建立了用例模型后,可以利用用例之间的关系调整用例模型,用例之间的关系包括哪几种?对于每种关系,请根据题目中所描述的需求分别给出一组用例。
【解】
问题1:用例的参与者:仓库管理员、仓库经理、系统管理员、时间、温度、温度调节系统。
问题2:用例名称、简要说明、事件流、非功能需求、前置条件、后置条件、扩展点、优先级。
问题3:用例之间的关系包括:包含关系、扩展关系、泛化关系。“出入库操作”与“登录”属于包含关系;“查看统计报表”与“生成统计报表”属于扩展关系;“用户注册”与“邮件注册”和“电话注册”属于典型的泛化关系。
4.3.1.2 类图与对象图
类图与对象图均属静态图。
类图(Class Diagram):⼀组类、接⼝、协作和它们之间的关系(呈现类的关系)。完整精确。
对象图 (Object Diagram):⼀组对象及它们之间的关系。对象图描述了在类图中所建立的事物实例的静态快照(呈现对象的关系,形式上与类图完全一致)。

组成:
- 类名:方法名,属性名
- 多重度(比数据库-ER图中不同实体间的各种联系更详细)
1:一个集合中的一个对象对应另一个集合中一个对象。0..*或*:表示一个集合中的1个对象对应另一个集合中的任意多个对象。(可以不对应)1..*:表示一个集合中的1个对象对应另一个集合中的任意多个对象。(至少对应一个)n..m:表示一个集合中的n个对象对应另一个集合中的m个对象
- 关系(详细绘图教程见Mermaid图教程):
- 泛化/继承(Generalization):特殊/一般关系(
特殊 --|> 抽象)。- 根据继承中包含的内容,继承可分为取代继承、包含继承、受限继承、特化继承。
- 实现(Realization):接口与类之间的关系(
接口 ..|> 实现类)。 - 依赖(Dependency):一个事物发生变化影响另一个事物(
类A ..> 类B(被依赖))。 - 关联(Association):描述了一组链,链是对象之间的连接(
类A -- 类B)。 - 聚合(Aggregation):整体与部分生命周期不同,部分可以独立存在(
部分类 --o 整体类)。(汽车与车轮) - 组合(Composition):整体与部分生命周期相同,部分不能独立存在(
部分类 --* 整体类)。(公司与部门)
- 泛化/继承(Generalization):特殊/一般关系(
classDiagram
Animal <|-- Dog
Animal <|.. IDomestic
KINA ..> Hyplus
Site -- Server
汽车 o-- 轮胎
公司 *-- 部门

4.3.1.3 交互图(顺序图、通信图、定时图)
交互图(Interaction Diagram)均属动态图,常用于表示用例实现图。包含如下3种:
顺序图(Sequence Diagram,序列图)强调对象之间消息发送的顺序(操作标有序号),同时显示对象之间的复杂交互过程。顺序图将显示的重点放在消息序列上,即强调消息是如何在对象之间被发送和接收的,其中循环、选择等复杂交互使用序列片段表示。
组成:
- 生命线:时间线(纵轴)
- 对象:位于最上方
- 消息:消息类型分为以下5种——
- 同步消息:同步消息的发送者等待消息接收对象将消息处理完成后再继续。
- 异步消息:异步消息的发送者发送完消息后不等待接收方就继续自己的处理。
- 返回消息:当一个对象将消息发送给另一个对象后,另一个对象返回的虚线有向边;表示原消息已处理的消息。
- 参与者创建消息:表示对消息传递目标对象的创建。
- 参与者销毁消息:表示对消息传递目标对象的删除。
- 调用
- 返回

通信图 (Communication Diagram,UML1.0中称为协作图)强调对象之间存在的消息收发关系,而不专门突出这些消息发送的时间顺序。(其他方面考的很少)

定时图(计时图;UML2.0新增)强调实际时间,用于展示交互过程中的真实时间信息,具体描述对象状态变化的时间点以及维持特定状态的时间段。(其他图都无法做到)

还有一种交互图:交互概览图
4.3.1.4 状态图与活动图
状态图(State Diagram)属于动态图,是对类描述的补充。用于展现此类复杂对象所具有的可能状态(即结点),以及某些事件发生时其状态转移情况(内部行为)。

【例】在订单处理的过程中,会员可以点击“取消订单”取消该订单。如果支付失败,该订单将被标记为挂起状态,可后续重新支付,如果挂起超时30分钟未支付,系统将自动取消该订单。订单支付成功后,系统判断订单类型:
(1)对于常规订单,标记为备货状态,订单信息发送到货运部,完成打包后交付快递发货;
(2)对于定制订单,会自动进入定制状态,定制完成后交付快递发货。会员在系统中点击收货按钮后变为收货状态,结束整个订单的处理流程。
整个过程的UML图如下所示,要求填充S1、S2、S3、S4、S5处的内容。

【解】该图为状态图,要填充的S1~S5均为状态。
本题较为简单,可直接根据原文获得答案:S1为“挂起状态”,S2为“备货状态”,S3为“定制状态”,S4为“收货状态”,S5为“订单收货状态”。(后续例题会提高亿些难度)
活动图(Activity Diagram)是一种特殊的状态图,描述一个操作中要进行的各项活动(与状态图不同)的执行流程(流程化处理)。同时,也常被用来描述一个用例的处理流程或者某种交互流程。将进程或其他计算结构展示为计算内部一步步的控制流和数据流,强调对象间的控制流程。
神似程序流程图,但存在如下巨大区别:
- 活动图是面向对象的,流程图是结构化的
- 如下图所示,活动图存在黑粗线,表示之间的分支可以并行。
- 活动图更凸显系统控制行为的表现,而流程图更关注业务流程

下图称为泳道式活动图,各泳道上的活动仅由对应的角色去完成,能够一目了然地表现各角色的职能:

流程图的环路复杂度计算式为
V(G) = E - N + 2
其中E为边数,N为结点数。或使用以下计算式
V(G) = P + 1
其中P为图中判定结点的数目。
【例】某软件公司为电子商务企业开发一套网上交易订单管理系统,以提升服务的质量和效率。在项目之初,项目组决定来用面向对象的开发方法进行系统开发,并对系统的核心业务功能进行了分析,具体描述如下:
注册用户通进商品信息页面在线浏览商品,将需要购买的商品添加进购物车内,点击“结算”按钮后开始录入订单信息。
用户在订单信息录入页面上选择支付方式,填写并确认收货人、收货地址和联系方式等信息。点击“提交订单”按钮后产生订单,并开始进行订单结算。
订单需要在30分钟内进行支付,否则会自动取消,用户也可以手工取消订单。
用户支付完成,经确认后,系统开始备货,扣除该商品可接单数量,并移除用户购物车中的所有商品资料。
生成订单表单,出货完毕,订单生效。为用户快递商品,等待用户接收。
用户签收商品,交易完成。
问题1(12分):
识别设计类是面向对象设计过程中的重要工作,没计类表达了类的职责,即该类所担任的任务。请用300字以内的文字说明设计类通常分为哪三种类型,每种类型的主要职责,并针对题干描述案例涉及的具体类为每种类型的设计类举出2个实例,
问题2(3分):
在面向对象的设计过程中,活动图 (Activity Diagram)阐明了业务用例实现的工作流程。请用300字以内的文字给出活动图与流程图(flow chart)的三个主要区别。
问题3(10分):
在面向对象的设计过程中,状态图(Statechart Diagram)描述了一个实体基于事件反应的动态行为。请根据题干描述,填写下图中的(a)~(e)空白,完成订单处理的状态图。

【解】
问题1:题干中“设计类”意为在设计阶段的3种类(见OOA最开头)。
(1)实体类:映射需求中的每个实体,保存需要存储在永久存储体中的信息,例如,用户、商品等。
(2)控制类:用于控制用例工作的,用于对一个或几个用例所特有的控制行为进行建模。例如,结算、备货等。
(3)边界类:用于封装在用例内、外流动的信息或数据流。例如,浏览器、购物车等。
问题2:
(1) 活动图描述的是对象活动的顺序关系所遵循的规则,它着重表现系统的行为,而非处理过程;而流程图着重描述处理过程。
(2) 流程图一般都限于顺序进程,而活动图则可以支持并发进程。
(3) 活动图是面向对象的,而流程图是面向过程的。
问题3:
(a)取消;(b)待结算;(c)大于30分钟;(d)订单生效;(c)用户签收。
4.3.1.5 构件图与包图
构件图与包图均属静态图。
构件图(Component Diagram)是类图的变体,描述一个封装的类及其接口、端口,以及由内嵌的构件和连接件构成的内部结构。构件图用于表示系统的静态设计实现视图。对于由小的部件构建大的系统来说,构件图相当重要。

包图(Package Diagram)包含由模型本身分解⽽成的组织单元,以及它们之间的依赖关系。通常作为面向对象的设计模型中的软件体系结构图。其基本思想是把共同工作的元素(例如多个类或构件)放到一个包中。
两者的区别:
- 构件图聚焦于某一功能,提供了供外部调用的接口,可让其所含的类互相协作,返回结果
- 包图仅将一堆元素放至一个包中,以供管理。
4.3.1.6 部署图
部署图(Deployment Diagram)属于静态图,描述对运行时的处理节点及在其中生存的构件的配置。给出了架构的静态部署视图,通常一个节点包含一个或多个部署图。(软硬件之间映射)

在项目开发完毕后使用,直观地展现服务器上的部署情况。
4.3.2 UML“4+1”视图

UML采⽤“4+1”视图来描述软件和软件开发过程(流程如图所示)
各视图详细解释如下:
- 左上——逻辑视图(Logical View):系统分析、设计人员——类与对象(关注系统功能/逻辑)
- 右上——实现视图(Implementation View):程序员——物理代码文件和组件
- 左下——进程视图(Process View):系统集成人员——线程、进程、并发(进程 ⇒ 并发)
- 右下——部署视图(Deployment View):系统和网络工程师——软件到硬件的映射
- 中心——⽤例视图(Use-case View):最终用户——需求分析模型(即“+1”,四个视图均涉及到)
4.3.3 组件对象模型(COM)
拓展
组件对象模型(Component Object Model,COM)不支持任何形式的实现继承。
COM支持两种形式的对象组装:
- 包含(Containment):一个对象拥有指向另一个对象的唯一引用。
- 外部对象只是把请求转发给内部对象,所谓转发就是调用内部对象的方法。
- 包含能重用内含于其他构件的实现,是完全透明的。
- 聚集(Aggregation):直接把内部对象接口引用传给外部对象的客户,而不是再转发请求。
- 如果包含层次较深,或者被转发的方法本身相对简单,包含会存在性能上的问题。因此COM定义聚集这种重用形式。
- 保持透明性是很重要的,因为外部对象的客户无法辨别哪个特定接口是从内部对象聚集而来的。
4.4 需求定义(形成需求规格)
需求定义(形成需求规格)即形成SRS(软件需求规范/软件需求规格说明书,Software Requirements Specification)。
两种方法:
- 严格定义法
- 所有需求都能够被预先定义
- 开发人员与用户之间能够准确而清晰地交流
- 采用图形/文字可以充分体现最终系统
- 原型法
- 并非所有的需求都能在开发前被准确的说明
- 项目参加者之间通常都存在交流上的困难
- 需要实际的、可供用户参与的系统模型
- 有合适的系统开发环境
- 反复是完全需要和值得提倡的,需求一旦确定,就应遵从严格的方法
4.5 需求验证
需求验证(Requirements Verification)在最后用户签字确认后形成需求基线(Baseline)(经过评审的SRS)。这个基线在用户和开发人员之间构筑了计划产品功能需求和非功能需求的一个约定 (Agreement),是需求开发和需求管理之间的桥梁。

4.6 需求管理
需求管理(Requirement Management)是对【需求基线】进行管理,是一个对系统需求变更、了解和控制的过程。需求管理过程与需求开发过程相互关联。
关于需求管理过程域内的原则和策略,可以参考:
- 需求管理的关键过程领域不涉及收集和分析项目需求,而是假定已收集了软件需求,或者已由更高一级的系统给定了需求。
- 开发人员在向客户以及有关部门承诺某些需求之前,应确认需求和约束条件、风险、偶然因素、假定条件等。
- 关键处理领域同样建议通过版本控制和变更控制来管理需求文档。
主要活动:变更控制、版本控制、需求跟踪、需求状态跟踪
4.6.1 变更控制
需求变更(Requirement Change)要进行控制,严格防止因失控而导致项目混乱,出现重大风险。

一般情况下,需求变更管理的流程如下(严格遵守该顺序):
- 问题分析和变更描述:识别和分析需求问题或者一份明确的变更提议,以检查它的有效性,从而产生一个更明确的需求变更提议。
- 变更分析和成本计算:由CCB(Change Control Board,项目变更控制委员会)负责审批。
- 使用可追溯性信息和系统需求的一般知识,对需求变更提议进行影响分析和评估。变更成本计算应该包括对需求文档的修改、系统修改的设计和实现的成本。一旦分析完成并且被确认,应该进行是否执行这一变更的决策。
- 变更控制委员会对项目中任何基线工作产品的变更都可以做出决定。
- 变更实现:要求需求文档和系统设计以及实现都要同时修改。如果先对系统的程序做变更,然后再修改需求文档,这几乎不可避免地会出现需求文档和程序的不一致。
需求变更控制流程的⼗⼤步骤:
- 明确问题
- 书⾯申请
- 判断变更需求类别
- 评估变更影响
- 判断变更的紧急级别
- 沟通确认
- 明确解决⽅案
- 审批管理
- 执⾏变更
- 版本控制
4.6.2 需求跟踪
需求跟踪(Requirements Traceability)将单个需求和其他系统元素之间的依赖关系和逻辑联系建立跟踪,这些元素包括各种类型的需求、业务规则、系统架构和构件、源代码、测试用例,以及帮助文件等。
需求跟踪矩阵(Requirement Traceability Matrix,RTM)常用于需求跟踪的跟进工作,从需求源头一直跟进到最终的软件产品,即通过需求跟踪来一步步落实过程。主要作用包括建立需求与设计、编程和测试之间的一致性(不含运维)。

在反向跟踪表中,每有某个用例满足某个原始需求就在对应格子打“√”。最后若某列无“√”则说明该用例多余(不对应任何用户需求),若某行无“√”则说明该需求被遗漏。正向跟踪表同理。
A 关于长文拆分
软件工程内容极多,故于2026年7月26日将后半部分内容(系统设计、软件测试、系统维护、项目管理等)拆至另一文,请通过系列博文系统进行博文导航。