软件工程核心概念精讲

软件工程核心概念:开发方法、模型、需求、建模、测试、维护及遗留系统处理。

原文标题:软件工程基本概念整理

原文作者:牧羊人的方向

冷月清谈:

本文整理了软件工程中的核心概念,涵盖软件开发方法、模型、需求工程、系统建模、测试等关键知识点。

**软件开发方法**:结构化方法强调流程和文档;原型法注重用户反馈;面向对象方法以实体、关系和属性为核心;面向服务方法则构建于类和对象之上,形成构件。

**软件开发模型**:瀑布模型线性推进;原型模型快速迭代;V模型强调测试;螺旋模型注重风险管理;统一过程兼顾迭代和增量;CMMI成熟度模型评估组织能力;敏捷方法强调适应性和以人为本。

**需求工程**:包括需求获取、分析、定义和验证,以及变更管理。

**基于构件的软件工程**:强调构件的可组装性、可部署性、文档化、独立性和标准化,并介绍了顺序、层次和叠加三种组装方式。

**软件系统建模**:UML语言通过事物、关系和图来描述系统;SysML语言则专门用于基于模型的系统工程。

**系统分析与设计**:结构化方法采用数据流图、数据字典和状态转换图;面向对象方法强调抽象、封装、继承等原则;面向服务方法以服务为核心。

**测试与评审**:涵盖黑盒/白盒测试、动态/静态测试、灰盒测试和自动化测试,以及单元测试、集成测试、系统测试、验收测试等阶段。

**系统运行与软件维护**:包括正确性维护、适应性维护、完善性维护和预防性维护。

**遗留系统处置原则**:集成、改造、淘汰和继承。

怜星夜思:

1、文章提到了很多软件开发模型,实际项目中如何选择合适的模型呢?有没有什么经验可以分享?
2、面向对象和面向服务有什么区别?它们分别适用于哪些场景?
3、如何有效地进行需求管理,避免需求变更带来的风险?

原文内容

系统架构设计中软件工程相关概念知识点整理记录。

1、软件开发方法
1.1 结构化方法
  • 生命周期划分为系统调查、系统分析、系统设计、系统实施和系统维护

  • 按照设定好的程序和步骤,使用一定的开发工具,完成规定的文档,在结构化和模块化的基础上进行信息系统的开发工作

1.2 原型法

根据用户需求,利用系统开发工具,快速建立系统模型展示给用户

1.3 面向对象方法

利用面向对象的信息进行建模,如实体、关系和属性,同时运用封装、继承、多态等机制来构造模拟实现。

1.4 面向服务方法

构建在类和对象之上,将相关对象按照业务功能进行分组,形成构件的概念。

2、软件开发模型
2.1瀑布模型

包含一系列活动,活动之间紧密关联

缺点:软件需求的完整性、正确性很难确定;严格串行化的过程模型,如果预期不一致或需求变更,带来损失;每个阶段完全解决该阶段工作,不能出现遗漏。

2.2 原型模型
  • 原型开发阶段:根据提出的定义,快速开发一个原型

  • 目标软件开发阶段:原型确认后,进一步开发实际系统

  • 抛弃型原型(需求确认后原型被弃用)和演化型原型(需求确认后不断补充和完善原型)

2.3 V模型

需求分析->验收测试与系统测试;概要设计对应集成测试,详细设计对应单元测试。

2.4 螺旋模型

软件开发分为多个阶段,每个阶段由4部分组成:目标设定、风险分析、开发和有效性验证、评审。

2.5 统一过程
2.5.1 4个阶段
  • 初始阶段:定义最终产品视图和业务模型,确定系统范围

  • 细化阶段:设定及确定系统的体系结构,制定工作计划及资源需求

  • 构造阶段:构造产品并继续演进直至提交

  • 移交阶段:产品移交给用户

2.5.2 9个核心工作流

业务建模、需求、分析与设计、实现、测试、部署、配置与变更管理、项目管理、环境

2.5.3 4+1视图
  • 逻辑视图:最终用户关心系统功能

  • 实现视图:程序员关心系统配置、装配等

  • 部署视图:系统工程师关心系统发布、安装和拓扑结构等

  • 进程视图:系统集成人员关心系统性能、可伸缩性、吞吐率等

  • 用例视图:分析和测试人员关心的是系统行为

2.5.4 迭代和增量
  • 迭代:项目分为完整的项目周期,每个迭代都致力于完成一组特定的功能或任务

  • 增量:软件开发过程中逐步增加的功能或产品组件

2.6 CMMI成熟度模型
  • Level 1初始级:随意混乱,依赖组织内的人员能力

  • Level 2已管理级:建立明确目标,实现成本、进度和质量目标

  • Level 3已定义级:定义标准流程,进行项目积累

  • Level 4量化管理级:产品质量、服务质量和过程性能的定量目标,过程性能的可预测

  • Level 5优化级:增量式与创新式的需求改进

2.7 敏捷方法
2.7.1 核心思想

适应型非预测型、以人为本非过程为本、迭代增量式开发

2.7.2 常见的敏捷方法
  • XP:交流、朴素、反馈、勇气

  • 水晶系列:提倡机动性方法,包含具有共性的核心元素

  • Scrum:侧重项目管理,迭代增量式软件开发

  • 特征驱动开发FDD:人、过程、技术

2.8 逆向工程

对一项目标产品进行逆向分析及研究,从而演绎并得出该产品的处理流程、组织结构、功能特性及技术规格等设计要素,以制作出功能相近但又不完全一样的产品

2.9 净室软件工程
2.9.1 核心理念

力图通过严格的工程化的软件过程达到开发中的零缺陷或接近零缺陷

2.9.2 技术手段
  • 统计过程控制下的增量开发

  • 基于函数的规范与设计

  • 正确性验证

  • 统计测试与软件验证

3、需求工程
3.1 需求开发
3.1.1 需求获取
  • 通过与用户交流,对现有的系统观察及任务进行分析,从而开发、捕获和修订用户的需求

  • 需求获取方法:用户面谈、专题讨论会、问卷调查、现场观察、原型化方法、头脑风暴等

3.1.2 需求分析

为需求建立概念模型,对需求的抽象描述,尽可能多的捕获现实世界的意义

3.1.3 需求定义

按照约定的规格生成需求的文档描述,用户的原始需求书作为用户和开发者之间的协约

3.1.4 需求验证

以需求规格为输入,验证需求的完整性、正确性、一致性、可测试性和可行性

3.2 需求变更管理

需求文档的追踪管理、变更控制、版本控制等 变更管理委员会CCB

4、基于构件的软件工程
4.1 特性
  • 可组装性:外部交互通过公开定义的接口进行

  • 可部署性:二进制形式,作为独立实体运行和部署

  • 文档化:用户根据文档判断构件是否满足需求

  • 独立性:无其它特殊构件下进行组装和部署

  • 标准化:符合标准化的构件模型

4.2 主要活动

  • 系统需求概览

  • 识别候选构件

  • 根据发现的构件修改需求

  • 体系结构设计

  • 构件定制与适配

  • 组装构件创建系统

4.3 构件的组装
4.3.1 顺序组装

按照顺序调用已经存在的构件,可以用两个已经存在的构件创造一个新的构件

4.3.2 层次组装

一个构件直接调用另一个构件提供的服务,被调用构件提供的接口必须与调用构件提供的接口兼容

4.3.3 叠加组装

多个构件合并形成新的构件,新构件合并了原构件的内容,从而对外提供了新的接口

5、软件系统建模
5.1 UML语言
5.1.1 UML基本构造块

1)事物

  • 结构事物:类、接口、协作、用例、主动类、构件、制品和节点

  • 行为事物:交互、状态机和活动

  • 分组事物:包package

  • 注释事物:注释部分

2)关系

  • 依赖:两个事物之间的语义关系

  • 关联:描述一组链,链是对象之间的连接

  • 泛化:特殊/一般关系,子元素共享父元素的结构和行为

  • 实现:类元之间的语义关系

5.1.2 UML图
  • 静态图(类图、对象图、构件图、部署图、制品图、包图、组合结构图)

  • 动态图(用例图、序列图、通信图、状态图、活动图、交互概览图和计时图)

5.1.3 UML5种视图(4+1视图)

用例视图、逻辑视图、进程视图、实现视图、部署视图

5.2 SyML语言
5.2.1 基本概念
  • 专门针对系统工程开发的建模语言,旨在支持基于模型的系统工程(MBSE)实践

  • SysML由图和元模型组成。图是语法,用于描述系统的各个方面;元模型是语义,定义了SysML中所有元素和关系的含义和规则

5.2.2 图表类型
  • 结构图:用于描述系统的物理和逻辑结构,包括块定义图(BDD)和内部块图(IBD)

  • 需求图:用于表示系统需求之间的关系,包括需求图(REQ)和验证图(V&V)

  • 参数图:用于定义和跟踪系统参数,包括参数图(PD)和约束块图(CBD)

  • 行为图:用于描述系统的动态行为,包括活动图(AD)、状态机图(SMD)和顺序图(SD)

6、系统分析与设计
6.1 结构化方法SASD

6.1.1 结构化分析

1)数据流图

  • 从应用系统的数据流着手以图形方式刻画和表示一个具体业务系统中的数据处理过程和数据流

  • 数据流、处理、数据存储、外部项

2)数据字典

  • 用户可以访问的记录数据库和应用程序元数据的目录

  • 数据项、数据结构、数据流、数据存储、处理过程

3)状态转换图

6.1.2 结构化设计

面向数据流设计,自顶向下、逐步求精和模块化方法。高内聚低耦合

1)高内聚

2)低耦合

6.1.3 结构化编程

自顶向下,逐步细化;清晰第一,效率第二;书写规范,缩进格式;基本结构,组合而成

6.1.4 数据库设计

E-R图:实体类型、属性和联系的方法

6.2 面向对象方法

6.2.1 面向对象分析
  • 基本原则:抽象、封装、继承、分类、聚合、关联、消息通信、粒度控制、行为分析

  • 基本步骤

    • 确定对象和类

    • 确定结构:结构指问题域的复杂性和抽象关系

    • 确定主题:主题是事物的总体概貌和总体分析模型

    • 确定属性:属性即数据元素

    • 确定方法:收到消息后进行处理的一些方法

6.2.2 面向对象设计

  • 实体类:映射需求中的每个实体

  • 控制类:用于控制用例工作的类

  • 边界类:用于封装在用例内、外流动的信息或数据流,用于系统接口与外部交互

6.2.3 面向对象开发

以对象为核心,认为程序由一系列对象组成,对象+类+继承+多态+消息

6.3 面向服务方法
6.3.1 面向服务分析
  • 以服务为核心,将应用程序的不同功能模块定义为一系列相互独立的服务,并通过标准化的接口与其他服务进行通信的方法

  • 定义业务需求:基于业务需求文档,了解系统需要实现的功能和性能要求

  • 明确已有的自动化系统:分析企业现有的自动化系统,确定哪些功能可以复用或集成

  • 对候选系统进行建模:使用服务建模技术,将业务流程分解为多个粒度相对较小的步骤,并确定候选操作。

  • 抽出流程控制逻辑:将控制逻辑独立抽象出来,以满足不断出现的新变化。

  • 构建候选服务:根据上下文对相关的服务操作进行分组,每一组构成一个潜在的服务。

  • 应用面向服务的原则修正候选服务:检查候选服务是否满足可重用性、自治等原则,并进行必要的调整。

  • 确定服务的组合:确定候选服务之间的关系,挑选流程的主要执行路径,并依次检查哪些服务被调用。

6.3.2 面向服务设计
  • 设计服务接口:确定需要支持的服务特征及使用的规范,包括服务的输入、输出、异常处理等。

  • 构建面向服务的架构:设计实体型服务、应用级服务、任务型服务和流程级服务等不同类型的服务,并确定它们之间的交互方式和接口规范。

  • 服务分层设计:将服务分为应用级服务层、业务级服务层和流程级服务层,以提高系统的模块化和可维护性。

6.3.3 面向服务开发
  • 选择开发平台和语言:根据设计好的服务接口和规范,选择合适的开发平台和编程语言进行服务实现。

  • 实现服务:按照设计文档编写服务代码,并进行单元测试和集成测试,确保服务的正确性和稳定性。

  • 发布服务:将经过测试的服务发布到具体的运行环境中,如应用服务器、云环境等。

  • 服务管理:负责运营、管理和维护服务,包括服务的监控、故障排查、性能优化等。

7、测试与评审
7.1 测试类型
7.1.1 白盒测试与黑盒测试
  • 黑盒测试:不考虑任何程序内部结构和特性的条件下,根据需求规格说明书设计测试实例。主要是对软件界面和软件功能进行测试

  • 白盒测试:借助程序内部的逻辑和相关信息,通过检测内部动作是否按照设计规格说明书的设定进行。常用的白盒测试法有控制流分析、数据流分析、路径分析、程序变异等。根据测试用例的覆盖程度,分为语句覆盖、判定覆盖、分支覆盖和路径覆盖等。

7.1.2 动态测试与静态测试
  • 静态测试:程序不运行,只依靠分析或检查源程序的语句、结构、过程来检查程序是否有错误

  • 动态测试:通过运行被测试程序,对得到的运行结果,与预期的结果进行比较分析,同时分析运行效率和健壮性能等

7.1.3 灰盒测试

介于黑盒和白盒之间,简单地靠一些象征性的现象或标志来判断其内部的运行情况

7.1.4 自动化测试

软件测试自动化,在预先设定的条件下自动运行被测程序

7.2 软件测试阶段
  • 单元测试:对该软件的模块进行测试,通过测试以发现该模块的功能不符合/不满足期望的情况和编码错误。

  • 集成测试:通常要对已经严格按照程序设计要求和标准组装起来的模块同时进行测试,明确该程序结构组装的正确性,发现和接口有关的问题。

  • 系统测试:采用黑盒测试,以此来检查该系统是否符合软件需求。主要测试内容要包括功能测试、性能测试、健壮性测试、安装或反安装测试、用户界面测试、压力测试、可靠性及安全性测试等

  • 性能测试:通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。负载测试和压力测试都属于性能测试,两者可以结合进行

  • 验收测试:软件产品投入正式交付前的测试工作,满足用户需求或者与用户签订的合同的各项要求

8、系统运行与软件维护

软件维护的类型:正确性维护、适应性维护、完善性维护、预防性维护

9、遗留系统处置原则

集成(高水平、低价值)、改造(高水平、高价值)、淘汰(低水平、低价值)、继承(低水平、高价值)

10、知识点总结

打个比方,面向对象就像搭积木,每个积木都有自己的形状和功能;面向服务就像组装电脑,每个部件都有标准接口,可以互相组合。所以面向对象更注重内部结构,面向服务更注重外部交互。

其实面向对象和面向服务并不是非此即彼的关系,它们可以结合使用。比如,在微服务架构中,每个微服务内部可以使用面向对象的方法进行设计,而微服务之间则使用面向服务的方法进行交互。

我之前经历过一个项目,因为需求变更频繁,导致项目延期,最后还烂尾了。所以需求管理真的很重要,宁愿前期多花点时间沟通,也不要后期天天救火。

面向对象更关注的是对象的属性和行为,而面向服务更关注的是服务的接口和交互。面向对象适合构建复杂的业务逻辑,而面向服务更适合构建分布式系统和微服务架构。

个人感觉敏捷开发现在很流行,但是并不是所有项目都适合。敏捷强调快速迭代和沟通,如果团队成员沟通不畅,或者项目周期很紧,反而会适得其反。所以选择模型要结合团队实际情况。

选择模型要看项目的具体情况。比如,项目需求明确、稳定,就可以用瀑布模型;需求不明确,需要快速迭代,就适合原型模型或敏捷方法。关键是根据项目特点选择最合适的模型,而不是一味追求新潮。

我之前做过一个嵌入式项目,因为硬件限制比较多,所以选择了V模型,方便提前进行测试,避免后期返工。我觉得选择模型要考虑项目的技术栈、团队成员的经验以及项目的风险因素。

需求管理的关键在于沟通。在项目初期就要与用户充分沟通,明确需求,并形成文档。在项目进行过程中,也要及时与用户沟通,处理需求变更,避免后期返工。