软件设计师——软件工程学习笔记

软件工程

一、软件工程基础知识

1. 软件的生存周期


(1)可行性分析与项目开发计划 。这个阶段主要确定软件的开发目标及其可行性。参与该阶段的人员有用户、项目负责人、系统分析师。产生的文档有 可行性分析报告、项目开发计划
(2)需求分析 。该阶段的任务不是具体的解决问题,而是要确定软件系统要做什么,确定软件系统的功能、性能、数据和界面等要求,从而确定系统的逻辑模型。参与该阶段的人员有用户、项目负责人、系统分析师。产生的文档主要是 软件需求说明书
(3)概要设计 。该阶段开发人员把确定的各项功能需求转换成需要的体系结构。概要设计就是设计软件的结构,明确软件由哪些模块组成,这些模块层次结构是怎样的,调用关系是怎样的,每个模块的功能是什么。参与该阶段的人员有系统分析师、软件设计师。产生的文档主要是 概要设计说明书
(4)详细设计 。该阶段的主要任务是对每个模块的功能进一步详细、具体的描述。参与该阶段的人员有软件设计师、程序员。产生的文档主要是 详细设计文档
(5)编码 。把每个模块的控制结构转换成计算机可接受的程序代码,即写成某种特定程序设计语言表示的 源程序 清单。
(6)测试 。测试是保证软件质量的重要手段。参加测试的人员通常是另一部门(或单位)的软件设计师或系统分析师。产生的文档主要是 软件测试计划、测试用例、测试报告
(7)维护。软件维护是软件生存周期中时间最长的阶段。软件已交付且正式投入使用后,便进入维护阶段。对软件进行修改的原因包括:①运行中发现隐含的错误而需要修改;②为了适应变化的(或变化后的)工作环境而修改;③需要对软件功能进行扩充、增强而进行的修改;④为将来软件维护活动做预先准备。

2. 软件过程

1.能力成熟度模型(CMM)

能力等级 特点 关键过程区域(KPAs)
初始级 过程不可预测、缺乏控制,依赖个人能力。
可重复级 基本项目管理能力建立,可跟踪成本、进度和功能。 需求管理、项目计划、项目跟踪与监督、配置管理、质量保证、子合同管理。
已定义级 过程标准化、文档化,组织级一致性增强。 同行评审、组间协调、软件产品工程、集成软件管理、培训大纲、组织过程定义、组织过程集点
定量管理级 过程可量化控制,质量与性能可预测。 定量过程管理、软件质量管理。
优化级 持续改进,缺陷预防与技术创新。 过程变更管理、技术变更管理、缺陷预防。

2.能力成熟度模型集成(CMMI)

CMMI提供了两种表示方法:阶段式模型和连续式模型。

(1)阶段式模型。结构类似于CMM,它关注组织的成熟度。CMMI-SE/SW/IPPD 1.1版本中有五个成熟度等级。

(2)连续式模型。关注每个过程域的能力,一个组织对不同的过程域可以达到不同的过程域能力等级(简称CL)。CMMI中包括六个过程域能力等级。

二、软件开发模型

1. 瀑布模型与V模型

瀑布模型

瀑布模型将软件生命周期中的各个活动规定为依据线性顺序连接的若干阶段的模型,包括需求分析、设计、编码、测试、运行与维护。如同瀑布流水逐级下落,如图所示。

以文档作为驱动、适合于软件需求很明确的软件项目,或者二次开发(需求稳定)

缺点:必须完整、正确和清晰地表达需要

V模型

瀑布模型的一个变体是V模型

V模型特点是增加了很多轮测试,并且这些测试贯穿于软件开发的各个阶段,不像其他模型都是软件开发完再测试,很大程度上保证了项目的准确性。V模型开发和测试级别对应如下图:

2. 演化模型(原型模型和螺旋模型)

演化模型是迭代的过程模型,使得软件开发人员能够逐步开发出更完整的软件版本。演化模型特别适用于对软件需求缺乏准确认识的情况

原型

与瀑布模型相反,原型 针对的就是需求不明确的情况,首先快速构造一个功能模型,演示给用户看,并按用户要求及时修改,中间再通过不断的演示与用户沟通,最终设计出项目,就不会出现与用户要求不符合的情况,采用的是迭代的思想 。不适合超大项目开发。

原型模型又根据使用目的的不同,分为探索型原型、实验型原型和演化型原型。
探索型原型 用于快速验证需求或概念的可行性,通常出现在项目早期阶段。这类原型聚焦于核心功能或用户痛点的模拟,忽略细节实现,帮助团队明确方向。
实验型原型 针对特定技术或设计假设进行验证,例如性能测试、算法可行性或新材料应用。通过可控实验收集数据,为决策提供依据。
演化型原型以迭代方式逐步完善,最终形成正式产品。每个版本在用户反馈和技术优化的基础上持续改进,常见于敏捷开发或MVP策略。

螺旋模型

螺旋模型将瀑布模型和演化模型结合起来,增加了风险分析特别适用于庞大、复杂并且具有高风险的系统。

需要开发人员具有相当丰富的风险评估经验和专门知识。

3. 增量模型

增量模型:首先开发核心模块功能 ,而后与用户确认,之后再开发次核心模块的功能,即每次开发一部分功能,并与用户需求确认,最终完成项目开发,优先级最高的服务最先交付,但由于并不是从系统整体角度规划各个模块,因此不利于模块划分。难点在于如何将客户需求划分为多个增量。与原型不用的是增量模型的每一次增量版本都可作为独立可操作的作品,而原型的构造一般是为了演示。

4. 喷泉模型

喷泉模型是以用户需求为动力、以对象为驱动的模型 。适用于面向对象的开发方法,克服了瀑布模型不支持软件重用和多项开发活动集成的局限性。喷泉模型使开发过程具有迭代性和无间隙性

缺点:需要大量的开发人员,要求严格管理文档。

5.统一过程(UP)模型

统一过程(UP)模型是一种"用例和风险驱动,以架构为中心,迭代并增量"的开发过程,由UML方法和工具支持。

统一过程的典型代表是RUP,RUP是UP的商业扩展,完全兼容UP,比UP更完整、更详细。

6.敏捷方法

敏捷方法的总体目标是通过"尽可能早地、持续地对有价值的软件进行交付"使客户满意。适用于:适合小项目小团队,"小步快跑"的思想。

敏捷方法的核心思想主要有以下三点:

①敏捷方法是"适应性"而非"预设性"的。

②敏捷方法是以人为本,而不是以过程为本。

③迭代增量式的开发过程。敏捷方法以原型开发思想为基础,采用迭代增量式开发,发行版本小型化。RUP相比,敏捷方法的周期可能更短。敏捷方法在几周或者几个月的时间内完成相对较小的功能,强调的是能尽早将尽量小的可用的功能交付使用,并在整个项目周期中持续改善和增强,并且更加强调团队中的高度写作。

**敏捷软件开发宣言:**相对于过程和工具,更强调个人和交互;相对于严格的文档,更重视可工作的软件;相对于合同谈判,更注重与客户的合作;相对于遵循计划,更专注于对变化的响应。

常用的方法:极限编程(XP)、水晶法(Crystal)、并列争球法(Scrum)、自适应软件开发(ASD)、敏捷统一过程(AUP)。

极限编程(XP)

因为知道计划永远赶不上变化,XP 无需开发人员在软件开始初期做出很多的文档。XP提倡 测试先行,为了将以后出现bug的几率降到最低。

三、软件开发方法

四、需求分析

一个好的需求应该具有无二义性、完整性、一致性、可测试性、确定性、可跟踪性、正确性、必要性等特性。

需求分析阶段的产物:软件需求规格说明书(SRS)

1. 结构化的需求分析

结构化特点: 自顶向下,逐步分解。
面向数据三大模型: 功能模型(数据流图)、行为模型(状态转换图)、数据模型(E-R图)以及数据字典

2. 需求分类

3. 需求分析工具

数据流图(DFD)

DFD的基本图形元素:外部实体、加工、数据存储、数据流。

层次结构:顶层图、0层图、底层图、父图、子图。
DFD的审查

(1)一致性:父图与子图平衡、数据守恒、具备数据存储、输出不能与输入同名。

(2)完整性:奇迹(无入有出)、黑洞(有入无出)、灰洞(无法出)。

数据字典(DD)

数据字典有以下4类条目:数据流、数据项、数据存储和基本加工 。(源点和终点不再系统之内,不在字典中说明)

逻辑描述方法

常用的加工逻辑描述方法有结构化语言、判定表和判定树3种。

  • 结构化语言采用接近自然语言的格式,但通过限制词汇和句式确保逻辑清晰。通常分为顺序、选择(IF-THEN-ELSE)和循环(WHILE-DO)三种结构,适合描述具有明确步骤或分支的业务规则。
  • 判定表通过表格形式列举所有条件组合及对应动作,适用于条件复杂且存在多分支的场景。表格分为条件桩(条件列表)、动作桩(动作列表)和规则(条件与动作的映射)。
  • 判定树以树形结构展示条件与动作的层级关系,直观呈现逻辑分支路径。节点表示条件,分支表示条件取值,叶子节点表示动作,适合可视化复杂决策过程。

五、系统设计

进入设计阶段,要把软件"做什么"的逻辑模型转换成 "怎么做" 的物理模型。

**系统设计的主要内容包括:**新系统总体结构设计、代码设计、输出设计、输入设计、处理过程设计、数据存储设计、用户界面设计和安全控制设计等。
常用的设计方法有 :面向数据流的结构化设计方法(SD)、面向对象的分析方法(OOD)。
系统设计基本原理

  • 抽象化;
  • 自顶而下,逐步求精;
  • 信息隐蔽;
  • 模块独立(高内聚,低耦合)。

系统设计包括两个基本的步骤:概要设计、详细设计。

1.概要设计

概要设计基本任务:设计软件系统总体结构、数据结构及数据库设计、编写概要设计文档(概要设计说明书、数据库设计说明书、用户手册及修订测试计划)、评审

2.详细设计

详细设计的基本任务:模块内详细算法设计、模块内数据结构设计、数据库的物理设计、其他设计(代码、输入/输出格式、用户界面)、编写详细设计说明书、评审。

3. 模块设计

  • 保持模块的大小适中;
  • 尽可能减少调用的深度;
  • 多扇入,少扇出;
  • 单入口,单出口;
  • 模块的作用域应该在模块之内;
  • 功能应该是可预测的。

模块的设计要求独立性高,就必须 高内聚,低耦合

(1). 内聚是指一个模块内部功能之间的相关性。

内聚类型 描述 示例
偶然内聚(偶然内聚) 模块内元素无逻辑关联,仅因巧合被分组 将打印日志、验证输入等无关功能放入同一模块
逻辑内聚 通过参数控制执行不同但逻辑相似的操作 一个"数据处理"模块根据参数选择排序或搜索
时间内聚(瞬时内聚) 元素在相同时间段执行(如初始化/关闭模块) 系统启动时同时加载配置、建立数据库连接
过程内聚 按特定过程顺序执行相关操作 用户注册流程:验证输入→保存数据→发送确认邮件
通信内聚 操作相同数据集但无严格执行顺序 报表生成模块:读取数据→计算统计量→格式化输出
顺序内聚 前一个操作的输出是后一个操作的输入 流水线处理:图像解码→滤镜处理→压缩
功能内聚 所有元素协同完成单一明确功能 加密模块仅实现AES算法

(2). 耦合是指多个模块之间的联系

耦合类型 描述 典型场景
非直接耦合 模块之间不直接交互,而是通过中间媒介传递信息 如消息队列、事件总线、共享数据库等
数据耦合 模块间通过参数传递基本数据类型,依赖度最低 函数调用时传递整数、字符串等简单数据
标记耦合 模块间通过传递数据结构(如记录、对象),但只使用其中部分字段 传递结构体但仅读取特定成员变量
控制耦合 一个模块通过控制信号(如标志位)直接影响另一个模块的执行逻辑 通过布尔参数控制函数内部分支选择
外部耦合 模块依赖共同的外部环境(如全局变量、共享文件) 多个模块读写同一配置文件或数据库表
公共耦合 多个模块共享同一全局数据结构,任一模块修改会影响其他模块 多个类方法直接操作同一静态变量
内容耦合 一个模块直接访问另一个模块的内部数据;一个模块不通过正常入口转到另一个模块的内部;两个模块有一部分程序代码重叠;一个块有多个入口 绕过接口直接访问另一模块的私有成员

4.人机界面设计

人机界面设计的三大原则:置于用户控制之下、减少用户的记忆负担、保持界面的一致性

置于用户的控制之下

  1. 以不强迫用户进入不必要的或不希望的动作的方式来定义交互方式提供灵活的交互;
  2. 允许用户交互可以被中断和取消;
  3. 当技能级别增加时可以使交互流水化并允许定制交互;使用户隔离内部技术细节;
  4. 设计应允许用户和出现在屏幕上的对象直接交互。

减少用户的记忆负担

  1. 减少对短期记忆的要求; 建立有意义的缺省;
  2. 定义直觉性的捷径;
  3. 界面的视觉布局应该基于真实世界的隐喻;
  4. 以不断进展的方式揭示信息。

保持界面的一致性

  • 允许用户将当前任务放入有意义的语境
  • 在应用系列内保持一致性
  • 如过去的交互模型已建立起了用户期望,除非有迫不得已的理由,不要去改变它。

5.架构设计

架构设计的一个核心问题是能否达到架构级的软件复用。

架构风格反映了领域中众多系统所共有的结构和语义特性,并指导如何将各个构件有效地组织成一个完整的系统。

架构风格定义了用于描述系统的术语表和一组指导构建系统的规则。5大基本架构风格:

(1) 数据流风格

批处理序列 : 构件为一系列固定顺序的计算单元,构件之间只通过数据传递交互。每个处理步骤是一个独立的程序,每一步必须在其前一步结束后才能开始,数据必须是完整的,以整体的方式传递,
管道-过滤器:每个构件都有一组输入和输出,构件读取输入的数据流,经过内部处理,产生输出数据流。前一个构件的输出作为后一个构件的输入,前后数据流关联。过滤器就是构件,连接件就是管道。Unix命令行工具是经典案例。


(2) 调用/返回风格

主程序/子程序 :基于分层调用,主程序协调子程序完成功能。C语言中的main()函数调用库函数是典型例子。
面向对象 :通过对象封装数据和行为,利用继承和多态实现复用。Java或C++中的类与对象交互是核心体现。
层次结构

  • MVC(Model-View-Controller):分离数据(Model)、显示(View)和控制逻辑(Controller),常见于Web框架(如Django)。
  • C/S(Client-Server):客户端请求服务,服务器响应,如HTTP协议。
  • B/S(Browser-Server):基于Web的C/S变体,浏览器作为通用客户端。

(3) 独立构件风格

进程通信 :构件通过消息传递(如RPC、消息队列)交互,微服务架构是典型应用。
事件驱动系统:构件通过事件隐式触发(如发布-订阅模式)。GUI框架(如Node.js的事件循环)依赖此风格。


(4) 虚拟机风格

解释器 :通过解释执行中间代码(如Python解释器处理字节码)。
基于规则的系统:规则引擎(如Drools)按条件-动作规则执行,适用于专家系统。


(5) 仓库风格

数据库系统 :以数据为中心,通过事务和查询语言(如SQL)管理数据。
超文本系统 :非线性的信息链接(如Web页面通过超链接关联)。
黑板系统:多个构件通过共享的"黑板"协作解决问题,常见于AI领域(如语音识别系统)。


六、软件测试

1. 测试基础

测试应遵循的基本原则:

  • 应尽早并不断的进行测试;
  • 测试工作应该避免由元开发软件的人或小组承担;
  • 在设计测试方案时,不仅要确定输入数据,而且要根据系统功能确定预期的输出结果
  • 既包含有效、合理的测试用例,也包含不合理、失效的用例;
  • 检验程序是否做了该做的事,且是否做了不该做的事;
  • 严格按照测试计划进行;
  • 妥善保存测试计划和测试用例:
  • 测试用例可以重复使用或追加测试
  • 修改后应进行回归测试
  • 尚未发现的错误数量与该程序已发现错误数成正比

软件测试分为静态测试和动态测试。
(1)静态测试: 被测程序不在机器上运行,采用人工检测和计算机辅助静态分析的手段对程序进行测试,包括人工检测、计算机辅助静态分析。

桌前检查:程序员检查自己编写的程序,在程序编译后,单元测试前。

代码审查:由若干个程序员和测试人员组成评审小组,通过召开程序评审会来进行审查。

代码走查:也是采用开会来对代码进行审查,但并非简单的检查代码,而是由测试人员提供测试用例,让程序员扮演计算机的角色,手动运行测试用例,检查代码逻辑。

(2)动态测试: 通过运行程序发现错误,一般采用黑盒测试和白盒测试。

1)**黑盒测试:**也称功能测试,在不考虑软件内部结构和特性的情况下,测试软件的外部特性。

2)**白盒测试:**也称结构测试,根据程序的内部结构和逻辑来设计测试用例,对程序的路径和过程进行测试,检查是否满足设计的需要。

3)灰盒测试法:即既有黑盒,也有白盒。

2. 黑盒测试

黑盒测试用例: 将程序看做一个黑盒子,只知道输入输出,不知道内部代码,由此设计出测试用例。

分为下面几类:
等价类划分: 把所有的数据按照某种特性进行归类,而后在每类的数据里选取一个即可。

等价类测试用例的设计原则: 设计一个新的测试用例,使其尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步,直到所有的有效等价类都被覆盖为止;设计一个新的测试用例,使其仅覆盖一个尚未被覆盖的无效等价类,重复这一步,直到所有的无效等价类都被覆盖为止。

边界值划分: 将每类的边界值作为测试用例,边界值一般为范围的两端值以及在此范围之外的与此范围间隔最小的两个值,如年龄范围为 0-150,边界值为0,150,-1,151四个。

错误推测:没有固定的方法,凭经验而言,来推测有可能产生问题的地方,作为测试用例进行测试。

因果图:由一个结果来反推原因的方法,具体结果具体分析,没有固定方法。

3. 白盒测试

测试类型 定义 特点
语句覆盖 确保程序的每条语句至少执行一次。 简单易实现,但无法检测逻辑错误或未执行的代码分支。
判定覆盖(分支覆盖) 确保每个条件语句的真假分支均被测试。 比语句覆盖更严格,能发现更多逻辑问题,但可能遗漏复杂条件组合。
条件覆盖 确保每个条件的真假值均被独立测试。 覆盖更细粒度,但可能忽略条件间的依赖关系。
条件组合覆盖 每个判定中的各种可能值的组合都至少出现一次。 同时满足判定覆盖、条件覆盖、判定/条件覆盖。
路径覆盖 测试所有可能的执行路径(包括循环和嵌套分支)。 覆盖最全面,但实现复杂且成本高,适合关键代码段。
循环覆盖 专门测试循环结构的边界条件(如零次、一次、多次迭代)。 针对循环结构设计,能发现边界值错误。

4. 测试阶段


(1)单元测试 :也称为模块测试,测试的对象是可独立编译或汇编的程序模块、软件构件或OO软件中的类(统称为模块),测试依据是软件详细设计说明书
(2)集成测试 :目的是检查模块之间,以及模块和已集成的软件之间的接口关系,并验证已集成的软件是否符合设计要求。测试依据是软件概要设计文档 。(自顶向下、自底向上、三明治)
(3)确认测试:主要用于验证软件的功能、性能和其他特性是否与用户需求一致。根据用户的参与程度,通常包括以下类型:

  • 内部确认测试:主要由软件开发组织内部按照 SRS进行测试。
  • Alpha 测试:用户在开发环境下进行测试。
  • Beta测试:用户在实际使用环境下进行测试,通过改测试后,产品才能交付用户。
  • 验收测试:针对 SRS,在交付前以用户为主进行的测试。其测试对象为完整的、集成的计算机系统。验收测试的目的是,在真实的用户工作环境下,检验软件系统是否满足开发技术合同或SRS。验收测试的结论是用户确定是否接收该软件的主要依据。除应满足一般测试的准入条件外,在进行验收测试之前,应确认被测软件系统已通过系统测试。

(4)系统测试 :测试对象是完整的、集成的计算机系统;测试的目的是在真实系统工作环境下,验证完成的软件配置项能否和系统正确连接,并满足系统/子系统设计文档和软件开发合同规定的要求。测试依据是用户需求或开发合同

主要内容包括功能测试、健壮性测试、性能测试、用户界面测试、安全性测试、安装与反安装测试等,其中,最重要的工作是进行功能测试与性能测试。功能测试主要采用黑盒测试方法;性能测试主要指标有响应时间、吞吐量、并发用户数和资源利用率等。
(5)配置项测试 :测试对象是软件配置项,测试目的是检验软件配置项与SRS的一致性。测试的依据是 SRS。在此之间,应确认被测软件配置项已通过单元测试和集成测试。
(6)回归测试:测试目的是测试软件变更之后,变更部分的正确性和对变更需求的符合性,以及软件原有的、正确的功能、性能和其他规定的要求的不损害性。

5. McCabe复杂度计算


计算有向图G的环路复杂度公式为:V(G)=m-n+20

有向图中有向边数为m,节点数为n。

对一个程序流程图,每一个分支边(连线)就是一条有向边,每一条语句(语句框)就是一个顶点。

相关推荐
GEO_JYB3 小时前
BERT家族进化史:从BERT到LLaMA,每一次飞跃都源于对“学习”的更深理解
学习·bert·llama
CC数分3 小时前
组长跟我说,她招人看重的是数据分析能力
学习·数据挖掘·数据分析·大学生·考证
网络安全大学堂4 小时前
【网络安全入门基础教程】网络安全零基础学习方向及需要掌握的技能
网络·学习·安全·web安全·网络安全·黑客
汇能感知4 小时前
光谱相机在手机行业的应用
经验分享·笔记·科技
moxiaoran57536 小时前
Python学习笔记--使用Django修改和删除数据
笔记·python·学习
@ZzHhXx6 小时前
嵌入式学习---(单片机)
单片机·嵌入式硬件·学习
chillxiaohan6 小时前
Docker学习记录
学习·docker·容器
m0_571372826 小时前
关于嵌入式学习——嵌入式硬件3
嵌入式硬件·学习
豆浩宇7 小时前
学习PaddlePaddle--环境配置-PyCharm + Conda
人工智能·深度学习·学习·目标检测·计算机视觉·pycharm·paddlepaddle