- 软件工程教程
- 软件工程首页
- 软件工程概述
- 软件开发生命周期
- 软件项目管理
- 软件需求
- 软件设计基础
- 分析与设计工具
- 软件设计策略
- 软件用户界面设计
- 软件设计复杂性
- 软件实现
- 软件测试概述
- 软件维护
- CASE工具概述
- 软件 - 考试题及答案
- 软件工程 - 考试题及答案
软件工程 - 快速指南
软件工程概述
让我们首先了解软件工程的含义。这个术语由两个词组成:软件和工程。
软件不仅仅是程序代码。程序是可执行的代码,用于某种计算目的。软件被认为是可执行编程代码、相关库和文档的集合。为特定需求而编写的软件称为软件产品。
另一方面,工程是关于使用明确定义的科学原理和方法开发产品。
软件工程是与使用明确定义的科学原理、方法和程序开发软件产品相关的工程分支。软件工程的结果是高效且可靠的软件产品。
定义
IEEE将软件工程定义为:
(1) 以系统化、规范化、可量化的方式进行软件开发、运行和维护的应用;也就是说,将工程应用于软件。
(2) 对上述陈述中所述方法的研究。
德国计算机科学家Fritz Bauer将软件工程定义为:
软件工程是在实际机器上经济有效地获得可靠且高效工作的软件的建立和使用健全的工程原理。
软件演进
使用软件工程原理和方法开发软件产品的过程称为软件演进。这包括软件的初始开发及其维护和更新,直到开发出满足预期需求的所需软件产品。
演进始于需求收集过程。之后,开发人员创建目标软件的原型,并在软件产品开发的早期阶段将其展示给用户以获取他们的反馈。用户提出更改,在此基础上,连续的更新和维护也会不断变化。这个过程会改变原始软件,直到完成所需的软件。
即使用户已经获得了所需的软件,不断发展的技术和不断变化的需求也迫使软件产品做出相应的改变。从头开始重新创建软件并逐一满足需求是不可行的。唯一可行且经济的解决方案是更新现有软件,使其与最新需求相匹配。
软件演进定律
Lehman提出了软件演进定律。他将软件分为三类:
- S型(静态型) - 这是严格按照定义的规范和解决方案工作的软件。解决方案和实现方法在编码之前都已立即理解。S型软件最不易更改,因此这是最简单的一种。例如,用于数学计算的计算器程序。
- P型(实用型) - 这是具有程序集合的软件。这由程序可以执行的确切操作来定义。在此软件中,可以描述规范,但解决方案并非立即可见。例如,游戏软件。
- E型(嵌入型) - 此软件作为现实世界环境的需求紧密配合。此软件具有高度的演化性,因为现实世界情况中的法律、税收等方面存在各种变化。例如,在线交易软件。
E型软件演进
Lehman提出了E型软件演进的八条定律:
- 持续变化 - E型软件系统必须持续适应现实世界的变化,否则它将逐渐变得越来越无用。
- 复杂性增加 - 随着E型软件系统的演进,除非进行维护或减少其复杂性,否则其复杂性往往会增加。
- 熟悉性保持 - 必须不惜一切代价保留对软件的熟悉程度或对其开发方式、为何以这种特定方式开发等的了解,以便在系统中实施更改。
- 持续增长 - 对于旨在解决某些业务问题的E型系统,其实施更改的规模会根据业务生活方式的变化而增长。
- 质量下降 - 除非严格维护并适应不断变化的操作环境,否则E型软件系统的质量会下降。
- 反馈系统 - E型软件系统构成多环、多级反馈系统,必须将其视为这样的系统才能成功修改或改进。
- 自调节 - E型系统演进过程是自调节的,产品和过程测量的分布接近正态分布。
- 组织稳定性 - 在演进的E型系统中,平均有效全局活动率在产品的整个生命周期中是不变的。
软件范式
软件范式是指在设计软件时采取的方法和步骤。今天提出了许多方法并正在使用中,但我们需要了解这些范式在软件工程中的位置。这些可以组合成不同的类别,尽管它们每个都包含在彼此之中。
编程范式是软件设计范式的子集,而软件设计范式又是软件开发范式的子集。
软件开发范式
这种范式被称为软件工程范式,其中应用了与软件开发相关的全部工程概念。它包括各种研究和需求收集,这有助于构建软件产品。它包括:
- 需求收集
- 软件设计
- 编程
软件设计范式
此范式是软件开发的一部分,包括:
- 设计
- 维护
- 编程
编程范式
此范式与软件开发的编程方面密切相关。这包括:
- 编码
- 测试
- 集成
软件工程的必要性
软件工程的必要性源于用户需求和软件运行环境变化速度加快。
- 大型软件 - 建造一堵墙比建造一所房子或建筑物更容易,同样,随着软件规模的扩大,工程必须介入以使其具有科学的过程。
- 可扩展性 - 如果软件过程不是基于科学和工程概念,那么重新创建新软件比扩展现有软件更容易。
- 成本 - 正如硬件行业已经展示其技能并且大规模制造降低了计算机和电子硬件的价格一样。但如果未采用适当的流程,软件成本仍然很高。
- 动态特性 - 软件不断发展和适应的特性在很大程度上取决于用户工作的环境。如果软件的特性总是在变化,则需要对现有软件进行新的增强。这就是软件工程发挥良好作用的地方。
- 质量管理 - 更好的软件开发流程可提供更好、更高质量的软件产品。
优秀软件的特性
软件产品可以通过其提供的功能和易用性来判断。此软件必须在以下方面满足要求:
- 操作性
- 过渡性
- 维护
设计精良的软件应具有以下特性:
操作性
这说明软件在操作中的工作情况。它可以根据以下方面进行衡量:
- 预算
- 可用性
- 效率
- 正确性
- 功能性
- 可靠性
- 安全性
- 安全性
过渡性
当软件从一个平台迁移到另一个平台时,这个方面很重要。
- 可移植性
- 互操作性
- 可重用性
- 适应性
维护
这个方面简要介绍了软件在不断变化的环境中保持自身能力的情况。
- 模块化
- 可维护性
- 灵活性
- 可扩展性
简而言之,软件工程是计算机科学的一个分支,它使用明确定义的工程概念来生产高效、持久、可扩展、符合预算和按时交付的软件产品。
软件开发生命周期
软件开发生命周期(简称SDLC)是软件工程中一个明确定义的、结构化的阶段序列,用于开发预期的软件产品。
SDLC活动
SDLC提供了一系列步骤,以便高效地设计和开发软件产品。SDLC框架包括以下步骤:
沟通
这是第一步,用户在此发起对所需软件产品的请求。他联系服务提供商并试图协商条款。他以书面形式向服务提供组织提交他的请求。
需求收集
从这一步开始,软件开发团队开始执行项目。团队与来自问题领域的各种利益相关者进行讨论,并尝试尽可能多地了解他们的需求。需求经过考虑并分为用户需求、系统需求和功能需求。使用许多实践来收集需求,如下所示:
- 研究现有或过时的系统和软件;
- 对用户和开发人员进行访谈;
- 参考数据库;或
- 收集问卷答案。
可行性研究
在需求收集之后,团队会制定一个软件过程的粗略计划。在此步骤中,团队会分析是否可以制作软件来满足用户的全部需求,以及软件是否可能不再有用。它会确定该项目在财务上、实际上和技术上是否可行。有很多算法可以帮助开发人员得出软件项目的可行性结论。
系统分析
在此步骤中,开发人员确定其计划的路线图,并尝试提出最适合项目的软件模型。系统分析包括:了解软件产品的局限性;预先了解系统相关问题或现有系统中需要进行的更改;识别和解决项目对组织和人员的影响等。项目团队分析项目的范围,并相应地规划进度和资源。
软件设计
下一步是将所有需求和分析知识整理出来,并设计软件产品。用户提供的输入和在需求收集阶段收集的信息是此步骤的输入。此步骤的输出以两种设计形式出现:逻辑设计和物理设计。工程师会生成元数据和数据字典、逻辑图、数据流图,在某些情况下还会生成伪代码。
编码
此步骤也称为编程阶段。软件设计的实现从使用合适的编程语言编写程序代码和高效地开发无错误的可执行程序开始。
测试
据估计,整个软件开发过程的 50% 应该用于测试。错误可能会从严重级别到软件本身被移除,都会破坏软件。软件测试由开发人员在编码过程中进行,并由测试专家在代码的各个级别(例如模块测试、程序测试、产品测试、内部测试以及在用户端测试产品)进行彻底的测试。尽早发现错误并加以纠正,是获得可靠软件的关键。
集成
软件可能需要与库、数据库和其他程序集成。SDLC 的此阶段涉及将软件与外部实体集成。
实施
这意味着将软件安装在用户机器上。有时,软件需要在用户端进行安装后配置。软件会针对可移植性和适应性进行测试,并在实施过程中解决与集成相关的问题。
运行和维护
此阶段确认软件运行效率更高且错误更少。如有需要,会对用户进行培训,或提供有关如何操作软件以及如何保持软件运行的文档。通过根据用户端环境或技术的更改及时更新代码来维护软件。此阶段可能会面临隐藏错误和现实世界中未识别问题的挑战。
处置
随着时间的推移,软件的性能可能会下降。它可能完全过时,或者可能需要大量的升级。因此,迫切需要消除系统的大部分内容。此阶段包括存档数据和所需的软件组件、关闭系统、规划处置活动以及在适当的系统结束时间终止系统。
软件开发范式
软件开发范例帮助开发人员选择开发软件的策略。软件开发范例具有自己的一套工具、方法和程序,这些工具、方法和程序表达清晰,并定义了软件开发生命周期。一些软件开发范例或流程模型定义如下:
瀑布模型
瀑布模型是最简单的软件开发范例模型。它指出 SDLC 的所有阶段将以线性方式一个接一个地运行。也就是说,只有完成第一个阶段后,才会启动第二个阶段,依此类推。
此模型假设所有事情都按照上一阶段的计划完美地执行和发生,并且不需要考虑下一阶段可能出现的过去问题。如果上一步骤留下了一些问题,则此模型无法顺利运行。模型的顺序性质不允许我们返回并撤消或重做我们的操作。
如果开发人员过去已经设计和开发过类似的软件,并且了解其所有领域,则此模型最适合。
迭代模型
此模型以迭代方式引导软件开发过程。它以循环方式预测开发过程,在 SDLC 过程的每个周期后重复每个步骤。
软件首先在非常小的规模上开发,并且会遵循所有考虑在内的步骤。然后,在每次迭代中,都会设计、编码、测试和添加到软件中更多的功能和模块。每个周期都会产生一个软件,它本身就是完整的,并且比前一个软件具有更多功能和能力。
在每次迭代之后,管理团队可以进行风险管理工作并为下一次迭代做准备。因为一个周期包含整个软件过程的一小部分,所以更容易管理开发过程,但它会消耗更多资源。
螺旋模型
螺旋模型是迭代模型和 SDLC 模型之一的组合。可以将其视为选择一个 SDLC 模型并将其与循环过程(迭代模型)组合。
此模型考虑风险,而大多数其他模型往往忽略了这一点。该模型从确定一次迭代开始时软件的目标和约束开始。下一阶段是软件的原型设计。这包括风险分析。然后使用标准 SDLC 模型构建软件。在第四阶段,准备下一次迭代的计划。
V 模型
瀑布模型的主要缺点是,我们只有在上一个阶段完成后才能进入下一个阶段,如果在后期阶段发现某些错误,则没有机会返回。V 模型提供了一种以相反方式在每个阶段测试软件的方法。
在每个阶段,都会创建测试计划和测试用例,以根据该阶段的要求验证和确认产品。例如,在需求收集阶段,测试团队会根据需求准备所有测试用例。稍后,当产品开发完毕并准备进行测试时,此阶段的测试用例会根据此阶段的要求验证软件的有效性。
这使得验证和确认能够并行进行。此模型也称为验证和确认模型。
大爆炸模型
此模型是形式上最简单的模型。它需要很少的计划,大量的编程和大量的资金。该模型的概念围绕着宇宙大爆炸。正如科学家所说,大爆炸之后,许多星系、行星和恒星都像一个事件一样进化。同样,如果我们将大量的编程和资金放在一起,我们可能会获得最好的软件产品。
对于此模型,只需要很少的规划。它不遵循任何流程,或者有时客户不确定需求和未来的需求。因此,输入需求是任意的。
此模型不适用于大型软件项目,但对于学习和实验来说是一个不错的选择。
要深入了解 SDLC 及其各种模型,点击此处。
软件项目管理
从事软件开发的 IT 公司的职位模式可以分为两部分:
- 软件创建
- 软件项目管理
项目是一个明确定义的任务,它是一系列为了实现目标而执行的操作的集合(例如,软件开发和交付)。项目可以概括为:
- 每个项目可能都有一个独特且不同的目标。
- 项目不是例行活动或日常运营。
- 项目有开始时间和结束时间。
- 项目在实现其目标时结束,因此它是组织生命周期中的一个临时阶段。
- 项目需要充足的资源,包括时间、人力、资金、材料和知识库。
软件项目
软件项目是软件开发的完整过程,从需求收集到测试和维护,根据执行方法,在规定的时间内完成,以实现预期的软件产品。
软件项目管理的必要性
软件被称为无形产品。软件开发是世界商业中一种全新的潮流,在构建软件产品方面经验很少。大多数软件产品都是定制的,以适应客户的需求。最重要的是,底层技术变化和发展如此频繁和迅速,以至于一个产品的经验可能无法应用于另一个产品。所有这些业务和环境限制都会给软件开发带来风险,因此高效地管理软件项目至关重要。
上图显示了软件项目的三个约束。对于软件组织来说,在客户预算限制内保持成本,并根据计划交付项目,交付高质量产品至关重要。有许多内部和外部因素可能会影响这个三约束三角形。任何三个因素都可能严重影响其他两个因素。
因此,软件项目管理对于结合用户需求以及预算和时间限制至关重要。
软件项目经理
软件项目经理是一个承担执行软件项目责任的人。软件项目经理完全了解软件将经历的 SDLC 的所有阶段。项目经理可能永远不会直接参与最终产品的生产,但他会控制和管理生产中涉及的活动。
项目经理密切监控开发过程,制定和执行各种计划,安排必要的和足够的资源,保持所有团队成员之间的沟通,以解决成本、预算、资源、时间、质量和客户满意度的问题。
让我们看看项目经理承担的一些责任:
人员管理
- 担任项目领导
- 与利益相关者沟通
- 人力资源管理
- 建立报告层次结构等。
项目管理
- 定义和设置项目范围
- 管理项目管理活动
- 监控进度和绩效
- 每个阶段的风险分析
- 采取必要的步骤来避免或解决问题
- 担任项目发言人
软件管理活动
软件项目管理包含许多活动,包括项目规划、确定软件产品的范围、估算各种方面的成本、安排任务和事件以及资源管理。项目管理活动可能包括:
- 项目规划
- 范围管理
- 项目估算
项目规划
软件项目规划是在软件实际生产开始之前执行的任务。它用于软件生产,但不涉及任何与软件生产有任何直接联系的具体活动;相反,它是一组多个流程,这些流程促进了软件生产。项目规划可能包括以下内容:
范围管理
它定义了项目的范围;这包括所有活动,需要完成这些过程才能制作可交付的软件产品。范围管理至关重要,因为它通过明确定义项目中将执行什么和不执行什么来创建项目的边界。这使得项目包含有限且可量化的任务,这些任务可以轻松地记录下来,进而避免成本和时间超支。
在项目范围管理期间,有必要:
- 定义范围
- 确定其验证和控制
- 将项目划分为各个较小的部分,以便于管理。
- 验证范围
- 通过纳入范围变更来控制范围
项目估算
为了有效管理,准确估算各种指标是必须的。通过正确的估算,管理者可以更高效、更有效地管理和控制项目。
项目估算可能包括以下内容:
- 软件规模估算
软件规模可以根据代码行数(KLOC,千行代码)估算,也可以通过计算软件的功能点来估算。代码行数取决于编码规范,功能点则根据用户或软件需求而变化。
- 工作量估算
管理者根据人员需求和生产软件所需的工时来估算工作量。进行工作量估算需要知道软件规模。这可以通过管理者的经验、组织的历史数据获得,或者可以使用一些标准公式将软件规模转换为工作量。
- 时间估算
一旦估算出规模和工作量,就可以估算出生产软件所需的时间。根据需求规格说明和软件各个组件的相互依赖性,将所需的工作量细分为子类别。软件任务通过工作分解结构 (WBS) 分解成更小的任务、活动或事件。这些任务按天或按日历月进行安排。
完成所有任务所需时间的总和(以小时或天为单位)就是完成项目所需的总时间。
- 成本估算
这可能是所有估算中最困难的,因为它依赖于比前面任何一项都更多的因素。为了估算项目成本,需要考虑:
- 软件规模
- 软件质量
- 硬件
- 附加软件或工具、许可证等
- 具备特定任务技能的熟练人员
- 差旅费用
- 沟通
- 培训和支持
项目估算技术
我们讨论了项目估算中涉及的各种参数,例如规模、工作量、时间和成本。
项目经理可以使用两种广泛认可的技术来估算上述因素:
分解技术
这种技术将软件视为各种组成部分的产物。
主要有两种模型:
- 代码行数 根据软件产品中的代码行数进行估算。
- 功能点 根据软件产品中的功能点数量进行估算。
经验估算技术
这种技术使用经验得出的公式进行估算。这些公式基于代码行数或功能点。
- Putnam 模型
该模型由 Lawrence H. Putnam 建立,基于 Norden 的频率分布(瑞利曲线)。Putnam 模型将所需的时间和工作量与软件规模关联起来。
- COCOMO
COCOMO 代表 COnstructive COst MOdel,由 Barry W. Boehm 开发。它将软件产品分为三类:有机型、半独立型和嵌入型。
项目进度安排
项目进度安排是指对所有活动进行规划,指定顺序并在每个活动分配的时间段内完成。项目经理倾向于定义各种任务和项目里程碑,并考虑到各种因素进行安排。他们会关注进度表中关键路径上的任务,这些任务需要以特定方式(由于任务的相互依赖性)并在分配的时间内严格完成。关键路径之外的任务不太可能影响项目的整体进度。
为了安排项目进度,需要:
- 将项目任务分解成更小、更易于管理的形式
- 找出各种任务并将其关联起来
- 估算每个任务所需的时间范围
- 将时间划分为工作单元
- 为每个任务分配足够数量的工作单元
- 计算项目从开始到结束所需的总时间
资源管理
开发软件产品所使用的所有元素都可以视为该项目的资源。这可能包括人力资源、生产工具和软件库。
资源的数量有限,作为资产池存在于组织中。资源短缺会阻碍项目开发,并可能导致项目落后于进度。分配额外的资源最终会增加开发成本。因此,必须对项目进行充分的资源估算和分配。
资源管理包括:
- 通过创建项目团队并为每个团队成员分配职责来定义适当的项目组织
- 确定特定阶段所需的资源及其可用性
- 通过在需要时生成资源请求并在不再需要时取消分配资源来管理资源。
项目风险管理
风险管理涉及所有与识别、分析和为项目中可预测和不可预测的风险做出规避措施的活动。风险可能包括:
- 经验丰富的员工离开项目,新员工加入。
- 组织管理的变化。
- 需求变更或需求理解错误。
- 对所需时间和资源的低估。
- 技术变革、环境变化、商业竞争。
风险管理流程
风险管理流程涉及以下活动:
- 识别 - 记录项目中可能发生的所有风险。
- 分类 - 根据其对项目可能造成的潜在影响,将已知风险分为高、中、低风险强度。
- 管理 - 分析风险在各个阶段发生的概率。制定避免或应对风险的计划。尝试尽量减少其负面影响。
- 监控 - 密切监控潜在风险及其早期征兆。还要监控为减轻或避免风险而采取的措施的效果。
项目执行与监控
在此阶段,项目计划中描述的任务将按照其进度执行。
执行需要监控,以检查一切是否按计划进行。监控是观察以检查风险的可能性并采取措施解决风险或报告各种任务的状态。
这些措施包括:
- 活动监控 - 可以每天监控在某个任务中安排的所有活动。当任务中的所有活动都完成后,该任务即被视为完成。
- 状态报告 - 报告包含在给定时间段内(通常是一周)完成的活动和任务的状态。状态可以标记为已完成、待处理或进行中等等。
- 里程碑清单 - 每个项目都细分为多个阶段,在这些阶段中会根据 SDLC 的阶段执行主要任务(里程碑)。此里程碑清单每隔几周准备一次,并报告里程碑的状态。
项目沟通管理
有效的沟通在项目的成功中起着至关重要的作用。它弥合了客户和组织之间的差距,弥合了团队成员以及项目中的其他利益相关者(例如硬件供应商)之间的差距。
沟通可以是口头的或书面的。沟通管理流程可能包括以下步骤:
- 计划 - 此步骤包括识别项目中的所有利益相关者以及他们之间的沟通方式。它还考虑是否需要任何额外的沟通设施。
- 分享 - 在确定计划的各个方面后,经理会专注于在正确的时间向正确的人分享正确的信息。这使每个参与项目的人都能够及时了解项目的进展及其状态。
- 反馈 - 项目经理使用各种措施和反馈机制,并创建状态和绩效报告。这种机制确保来自各个利益相关者的意见作为反馈传达给项目经理。
- 收尾 - 在每个主要事件结束、SDLC 阶段结束或项目本身结束时,将正式宣布行政收尾,以便通过发送电子邮件、分发文档的纸质副本或其他有效的沟通方式向每个利益相关者进行更新。
收尾后,团队将进入下一阶段或项目。
配置管理
配置管理是一个跟踪和控制软件变化的过程,这些变化涉及产品的需求、设计、功能和开发。
IEEE 将其定义为“识别和定义系统中的项目,控制这些项目在其整个生命周期中的变化,记录和报告项目和变更请求的状态,以及验证项目的完整性和正确性”。
通常,一旦 SRS 定稿,用户就很少需要更改需求。如果发生更改,只有在获得高级管理层的批准后才能解决这些更改,因为存在成本和时间超支的可能性。
基线
如果某个 SDLC 阶段已建立基线,则该阶段被认为已完成,即基线是定义阶段完整性的衡量标准。当与某个阶段相关的所有活动都完成并记录在案时,该阶段即已建立基线。如果不是最后一个阶段,其输出将用于下一个阶段。
配置管理是组织管理的一个分支,负责在某个阶段建立基线后发生的任何变化(流程、需求、技术、策略等)。CM 会检查软件中所做的任何更改。
变更控制
变更控制是配置管理的功能,它确保对软件系统所做的所有更改都是一致的,并符合组织的规章制度。
产品配置的更改将经历以下步骤:
识别 - 变更请求来自内部或外部来源。当正式识别变更请求时,会对其进行适当的记录。
验证 - 检查变更请求的有效性并确认其处理程序。
分析 - 从进度、成本和所需工作量的角度分析变更请求的影响。分析预期的变更对系统的整体影响。
控制 - 如果预期的更改会影响系统中的太多实体,或者它是不可避免的,则必须在将更改合并到系统中之前获得高级管理层的批准。决定更改是否值得纳入。如果不可行,则正式拒绝变更请求。
执行 - 如果上一阶段决定执行变更请求,则此阶段将采取适当的操作来执行更改,如有必要,将进行彻底的修订。
关闭请求 - 验证更改是否已正确实施并与系统的其余部分合并。软件中新纳入的更改将被妥善记录,并正式关闭请求。
项目管理工具
即使项目按照既定方法开发,项目规模越大,风险和不确定性也会成倍增加。
有一些工具可以帮助有效地进行项目管理。以下是一些描述:
甘特图
甘特图由亨利·甘特(1917年)设计。它根据时间段表示项目进度。它是一个水平条形图,条形代表活动以及项目活动的时间安排。
PERT图
PERT(计划评审技术)图是一种将项目描绘成网络图的工具。它能够以并行和连续的方式图形化地表示项目的关键事件。依次发生的事件显示了后续事件对先前事件的依赖性。
事件显示为编号的节点。它们通过带标签的箭头连接,描绘了项目中任务的顺序。
资源柱状图
这是一个图形工具,包含条形图或图表,表示项目事件(或阶段)随时间推移所需的资源数量(通常是熟练员工)。资源柱状图是有效的人员计划和协调工具。
关键路径分析
此工具有助于识别项目中相互依赖的任务。它还有助于找出成功完成项目的最佳路径或关键路径。与PERT图一样,每个事件都被分配一个特定的时间范围。此工具显示事件的依赖性,假设一个事件只有在先前事件完成之后才能继续进行。
事件按其最早可能的开始时间排列。开始节点和结束节点之间的路径是关键路径,无法进一步缩短,并且所有事件都需要按相同的顺序执行。
软件需求
软件需求是对目标系统特性和功能的描述。需求传达了用户对软件产品的期望。从客户的角度来看,需求可能是显而易见的或隐藏的,已知的或未知的,预期的或未预期的。
需求工程
从客户处收集软件需求、分析和记录这些需求的过程称为需求工程。
需求工程的目标是开发和维护复杂且具有描述性的“系统需求规格说明”文档。
需求工程流程
这是一个四步过程,包括:
- 可行性研究
- 需求收集
- 软件需求规格说明
- 软件需求验证
让我们简要了解一下这个过程:
可行性研究
当客户联系组织以开发所需产品时,他们会对软件必须执行的所有功能以及软件的预期特性有一个大致的概念。
参考这些信息,分析人员会详细研究所需系统及其功能是否可行。
这项可行性研究侧重于组织的目标。这项研究分析了软件产品在实施方面、对组织的贡献、成本约束以及根据组织的价值观和目标是否能够实际实现。它探讨了项目的技术方面和产品,例如可用性、可维护性、生产力和集成能力。
此阶段的输出应为一份可行性研究报告,其中应包含关于项目是否应该进行的充分评论和管理建议。
需求收集
如果可行性报告对进行项目持积极态度,则下一阶段将从收集用户的需求开始。分析人员和工程师与客户和最终用户沟通,了解他们对软件应该提供什么以及他们希望软件包含哪些功能的想法。
软件需求规格说明
SRS是由系统分析师在从各个利益相关者收集需求后创建的文档。
SRS定义了预期的软件将如何与硬件、外部接口、运行速度、系统响应时间、软件在各种平台上的可移植性、可维护性、崩溃后的恢复速度、安全、质量、限制等进行交互。
从客户那里收到的需求是用自然语言编写的。系统分析师有责任用技术语言记录需求,以便软件开发团队能够理解和使用这些需求。
SRS应该具备以下特性:
- 用户需求是用自然语言表达的。
- 技术需求是用组织内部使用的结构化语言表达的。
- 设计描述应使用伪代码编写。
- 表单和GUI屏幕截图的格式。
- DFD等的条件和数学符号。
软件需求验证
在开发需求规格说明之后,将验证此文档中提到的需求。用户可能会要求非法的、不切实际的解决方案,或者专家可能会错误地解释需求。如果不能从一开始就解决这个问题,这将导致成本大幅增加。可以根据以下条件检查需求:
- 如果它们可以实际实现
- 如果它们有效并且符合软件的功能和领域
- 如果存在任何歧义
- 如果它们是完整的
- 如果它们可以被证明
需求获取过程
可以使用以下图表来描述需求获取过程
- 需求收集 - 开发人员与客户和最终用户讨论,了解他们对软件的期望。
- 组织需求 - 开发人员根据重要性、紧迫性和便利性对需求进行优先级排序和安排。
协商与讨论 - 如果需求不明确或各个利益相关者的需求存在冲突,则应与利益相关者进行协商和讨论。然后可以对需求进行优先级排序并进行合理的妥协。
需求来自各个利益相关者。为了消除歧义和冲突,需要讨论其清晰度和正确性。不切实际的需求应进行合理的妥协。
- 文档编制 - 所有正式和非正式、功能性和非功能性需求都将被记录下来,并提供给下一阶段处理。
需求获取技术
需求获取是通过与客户、最终用户、系统用户以及其他在软件系统开发中拥有利益的人员沟通,找出预期软件系统需求的过程。
有多种方法可以发现需求
访谈
访谈是收集需求的有力手段。组织可以进行几种类型的访谈,例如:
- 结构化(封闭式)访谈,其中预先确定了要收集的每一条信息,它们遵循模式和讨论的内容。
- 非结构化(开放式)访谈,其中预先没有确定要收集的信息,更灵活且偏差更小。
- 口头访谈
- 书面访谈
- 一对一访谈,在两人之间进行。
- 小组访谈,在参与者之间进行。由于涉及众多人员,它们有助于发现任何遗漏的需求。
调查
组织可以通过询问各个利益相关者对即将推出的系统的期望和需求来进行调查。
问卷调查
将包含预定义的一组客观问题和相应选项的文档交给所有利益相关者回答,然后收集和整理这些答案。
这项技术的缺点是,如果问卷中没有提到某个问题的选项,则该问题可能会被忽略。
任务分析
工程师和开发人员团队可以分析需要新系统进行的操作。如果客户已经有一些软件来执行某些操作,则对其进行研究并收集拟议系统的需求。
领域分析
每个软件都属于某个领域类别。该领域的专家可以极大地帮助分析一般和特定需求。
头脑风暴
在各个利益相关者之间进行非正式辩论,并记录所有输入内容以供进一步的需求分析。
原型设计
原型设计是在不添加详细功能的情况下构建用户界面,以便用户解释预期软件产品的特性。它有助于更好地了解需求。如果客户终端没有安装软件供开发人员参考,并且客户不了解自己的需求,则开发人员会根据最初提到的需求创建原型。原型将显示给客户,并记录反馈。客户反馈将作为需求收集的输入。
观察
专家团队访问客户的组织或工作场所。他们观察现有已安装系统的实际工作情况。他们观察客户的工作流程以及如何处理执行问题。团队本身会得出一些结论,这些结论有助于形成对软件的预期需求。
软件需求特性
收集软件需求是整个软件开发项目的基础。因此,它们必须清晰、正确且定义明确。
完整的软件需求规格说明必须:
- 清晰
- 正确
- 一致
- 连贯
- 易于理解
- 可修改
- 可验证
- 已排序
- 明确
- 可追溯
- 可靠的来源
软件需求
我们应该尝试了解在需求获取阶段可能会出现什么样的需求,以及软件系统需要什么样的需求。
广义上讲,软件需求应分为两类:
功能需求
与软件功能相关的需求属于此类。
它们定义软件系统内部和软件系统的功能。
例如:
- 为用户提供搜索选项,以便从各种发票中进行搜索。
- 用户应该能够将任何报告通过邮件发送给管理层。
- 用户可以被分成组,并且可以为组分配单独的权限。
- 应遵守业务规则和管理功能。
- 软件开发过程中保持向下兼容性。
非功能性需求
与软件功能方面无关的需求属于此类。它们是软件的隐含或预期特性,用户对此进行假设。
非功能性需求包括:
- 安全性
- 日志记录
- 存储
- 配置
- 性能
- 成本
- 互操作性
- 灵活性
- 灾难恢复
- 可访问性
需求按逻辑分类为:
- 必须具备:没有它们,软件就不能算作可运行的。
- 应该具备:增强软件的功能。
- 可以具备:即使没有这些需求,软件也能正常运行。
- 愿望清单:这些需求与软件的任何目标都不匹配。
在软件开发过程中,必须实现“必须具备”的需求,“应该具备”的需求需要与利益相关者协商和取舍,而“可以具备”和“愿望清单”中的需求可以保留到软件更新时再考虑。
用户界面需求
UI是任何软件、硬件或混合系统的的重要组成部分。如果软件:
- 易于操作
- 响应迅速
- 有效处理操作错误
- 提供简单且一致的用户界面
用户是否接受软件很大程度上取决于用户如何使用软件。UI是用户感知系统的唯一途径。一个性能良好的软件系统也必须配备具有吸引力、清晰、一致和响应迅速的用户界面。否则,软件系统功能将无法以方便的方式使用。如果一个系统能够提供高效使用的方法,则该系统被认为是良好的。以下是用户界面需求的简要说明:
- 内容呈现
- 轻松导航
- 简洁的界面
- 响应式
- 一致的UI元素
- 反馈机制
- 默认设置
- 有目的的布局
- 策略性地使用颜色和纹理。
- 提供帮助信息
- 以用户为中心的方法
- 基于组的视图设置。
软件系统分析师
IT组织中的系统分析师是一个分析拟议系统需求并确保需求被正确且完整地构思和记录的人员。分析师的角色始于SDLC的软件分析阶段。分析师有责任确保开发的软件满足客户的需求。
系统分析师的职责包括:
- 分析和理解目标软件的需求
- 理解项目如何促进组织目标的实现
- 识别需求来源
- 需求验证
- 制定和实施需求管理计划
- 记录业务、技术、流程和产品需求
- 与客户协调以确定需求优先级并消除歧义
- 与客户和其他利益相关者最终确定验收标准
软件度量和衡量
软件度量可以理解为量化和象征软件的各种属性和方面的一个过程。
软件度量为软件过程和软件产品的各个方面提供度量。
软件度量是软件工程的基本要求。它们不仅有助于控制软件开发过程,而且还有助于保持最终产品的卓越质量。
软件工程师汤姆·德马科 (Tom DeMarco) 认为:“你无法控制你无法衡量的东西。” 这句话清楚地说明了软件度量的重要性。
让我们来看一些软件度量:
规模度量 - LOC(代码行数),通常以交付的源代码行数(千行)计算,表示为 KLOC。
功能点计数是衡量软件提供的功能的指标。功能点计数定义了软件功能方面的规模。
- 复杂度度量 - McCabe 的循环复杂度量化了程序中独立路径数量的上限,这被认为是程序或其模块的复杂度。它使用控制流图通过图论概念表示。
质量度量 - 缺陷、缺陷的类型和原因、后果、严重程度和影响定义了产品的质量。
在开发过程中发现的缺陷数量和产品安装或交付给客户后客户报告的缺陷数量,决定了产品的质量。
- 过程度量 - 在SDLC的各个阶段,所使用的方法和工具、公司标准以及开发的性能都是软件过程度量。
- 资源度量 - 所用的努力、时间和各种资源代表资源测量的指标。
软件设计基础
软件设计是一个将用户需求转换为某种合适形式的过程,这有助于程序员进行软件编码和实现。
为了评估用户需求,会创建一个 SRS(软件需求规格说明)文档,而对于编码和实现,则需要使用软件术语进行更具体和详细的需求。此过程的输出可以直接用于编程语言中的实现。
软件设计是 SDLC(软件设计生命周期)的第一步,它将重点从问题域转移到解决方案域。它试图指定如何满足 SRS 中提到的需求。
软件设计级别
软件设计产生三个级别的结果:
- 体系结构设计 - 体系结构设计是系统的最高抽象版本。它将软件识别为一个由许多相互交互的组件组成的系统。在这个级别,设计人员可以了解拟议的解决方案域。
- 高层设计 - 高层设计将体系结构设计中的“单个实体-多个组件”概念分解为子系统和模块的较少抽象视图,并描述它们之间的相互作用。高层设计侧重于如何以模块的形式实现系统及其所有组件。它识别每个子系统的模块化结构及其相互之间的关系和交互。
- 详细设计 - 详细设计处理在之前的两个设计中被视为系统及其子系统的实现部分。它对模块及其实现更详细。它定义每个模块的逻辑结构及其与其他模块通信的接口。
模块化
模块化是一种将软件系统划分为多个离散且独立的模块的技术,这些模块有望能够独立地执行任务。这些模块可以作为整个软件的基本构造。设计人员倾向于设计模块,以便可以单独且独立地执行和/或编译它们。
模块化设计无意中遵循了“分而治之”的解决问题策略的规则,这是因为模块化软件设计还附带许多其他好处。
模块化的优点:
- 较小的组件更容易维护
- 程序可以根据功能方面进行划分
- 可以在程序中引入所需的抽象级别
- 具有高内聚性的组件可以再次重用
- 可以实现并发执行
- 从安全角度来看是理想的
并发性
过去,所有软件都旨在顺序执行。顺序执行意味着编码指令将一个接一个地执行,这意味着任何给定时间只有一个程序部分被激活。例如,一个软件有多个模块,那么在任何执行时间,只能找到一个模块处于活动状态。
在软件设计中,并发性是通过将软件拆分为多个独立的执行单元(如模块)并并行执行它们来实现的。换句话说,并发性为软件提供了并行执行多个代码部分的能力。
程序员和设计师有必要识别哪些模块可以进行并行执行。
示例
文字处理器中的拼写检查功能是一个软件模块,它与文字处理器本身一起运行。
耦合和内聚
当软件程序模块化时,其任务将根据某些特性划分为几个模块。众所周知,模块是一组指令,为了完成某些任务而组合在一起。它们虽然被认为是单个实体,但可能会相互引用以一起工作。有一些衡量标准可以用来衡量模块的设计质量及其相互之间的交互。这些衡量标准称为耦合和内聚。
内聚
内聚是一种衡量模块元素内部依赖程度的指标。内聚越高,程序设计就越好。
共有七种内聚类型:
- 偶然内聚 - 这是无计划的和随机的内聚,可能是为了模块化而将程序分解成较小模块的结果。因为它没有计划,所以可能会让程序员感到困惑,并且通常不被接受。
- 逻辑内聚 - 当逻辑分类的元素组合到一个模块中时,这称为逻辑内聚。
- 时间内聚 - 当模块的元素被组织起来,以便在相似的点处理时,这称为时间内聚。
- 过程内聚 - 当模块的元素组合在一起,按顺序执行以执行任务时,这称为过程内聚。
- 通信内聚 - 当模块的元素组合在一起,按顺序执行并在相同的数据(信息)上工作时,这称为通信内聚。
- 顺序内聚 - 当模块的元素组合在一起,因为一个元素的输出作为另一个元素的输入,依此类推时,这称为顺序内聚。
- 功能内聚 - 这被认为是最高程度的内聚,并且它是非常理想的。功能内聚中模块的元素组合在一起,因为它们都对单个明确定义的功能做出了贡献。它也可以重复使用。
耦合
耦合是一种衡量程序模块之间相互依赖程度的指标。它说明了模块以什么级别相互干扰和交互。耦合越低,程序越好。
共有五种耦合级别:
- 内容耦合 - 当一个模块可以直接访问、修改或引用另一个模块的内容时,这称为内容级耦合。
- 公共耦合 - 当多个模块对某些全局数据具有读写访问权限时,这称为公共或全局耦合。
- 控制耦合 - 如果一个模块决定另一个模块的功能或更改其执行流程,则这两个模块称为控制耦合。
- 标记耦合 - 当多个模块共享公共数据结构并在其不同部分工作时,这称为标记耦合。
- 数据耦合 - 数据耦合是指两个模块通过传递数据(作为参数)来相互交互。如果一个模块传递数据结构作为参数,那么接收模块应该使用其所有组件。
理想情况下,无耦合被认为是最好的。
设计验证
软件设计过程的输出是设计文档、伪代码、详细逻辑图、流程图以及所有功能性或非功能性需求的详细描述。
下一个阶段,即软件的实现,取决于上述所有输出。
因此,在进入下一个阶段之前,有必要验证输出。越早发现错误越好,否则可能直到产品测试时才被发现。如果设计阶段的输出采用形式化表示形式,则应使用其相关的验证工具;否则,可以使用彻底的设计评审进行验证。
通过结构化验证方法,评审人员可以发现可能因忽略某些条件而造成的缺陷。良好的设计评审对于良好的软件设计、准确性和质量至关重要。
软件分析与设计工具
软件分析和设计包括所有有助于将需求规范转换为实现的活动。需求规范指定软件的所有功能性和非功能性期望。这些需求规范以人类可读和理解的文档形式出现,计算机对此无能为力。
软件分析和设计是中间阶段,它有助于将人类可读的需求转换为实际代码。
让我们看看软件设计师使用的一些分析和设计工具
数据流图
数据流图是信息系统中数据流动的图形表示。它能够描绘传入数据流、传出数据流和存储数据。DFD 没有提及数据如何在系统中流动。
DFD 和流程图之间存在显著区别。流程图描述程序模块中的控制流。DFD 描述系统中不同层次的数据流。DFD 不包含任何控制或分支元素。
DFD 的类型
数据流图可以是逻辑的或物理的。
- 逻辑 DFD - 此类型的 DFD 重点关注系统过程和系统中的数据流。例如,在银行软件系统中,数据如何在不同实体之间移动。
- 物理 DFD - 此类型的 DFD 显示数据流在系统中的实际实现方式。它更具体,更接近于实现。
DFD 组件
DFD 可以使用以下组件集表示数据源、目标、存储和流 -
- 实体 - 实体是信息数据的源和目标。实体用矩形及其各自的名称表示。
- 过程 - 对数据采取的活动和操作用圆形或圆角矩形表示。
- 数据存储 - 数据存储有两个变体 - 它可以表示为两侧都没有的矩形,也可以表示为只有一侧缺失的开放式矩形。
- 数据流 - 数据移动用尖箭头表示。数据移动从箭头的底部(作为其源)指向箭头的头部(作为目标)。
DFD 的层次
- 0 层 - 最高抽象级别的 DFD 称为 0 层 DFD,它将整个信息系统描绘成一个图,隐藏所有底层细节。0 层 DFD 也称为上下文层 DFD。
- 1 层 - 0 层 DFD 被分解成更具体的 1 层 DFD。1 层 DFD 描绘系统中的基本模块以及各个模块之间的数据流。1 层 DFD 还提到了基本流程和信息来源。
2 层 - 在此级别,DFD 显示数据如何在 1 层中提到的模块内部流动。
更高层次的 DFD 可以转换为更具体的更低层次的 DFD,并具有更深入的理解,直到达到所需的规范级别。
结构图
结构图是从数据流图派生的图表。它比 DFD 更详细地表示系统。它将整个系统分解为最低功能模块,比 DFD 更详细地描述每个系统模块的功能和子功能。
结构图表示模块的层次结构。每一层执行一项特定任务。
以下是结构图中使用的符号 -
- 模块 - 它表示过程、子程序或任务。控制模块分支到多个子模块。库模块是可重用的,可以从任何模块调用。
- 条件 - 它用模块底部的菱形表示。它表示控制模块可以根据某些条件选择任何子程序。
- 跳转 - 指向模块内部的箭头表示控制将跳转到子模块的中间。
- 循环 - 曲线箭头表示模块中的循环。循环覆盖的所有子模块都重复执行模块。
- 数据流 - 末端带有空心圆的定向箭头表示数据流。
- 控制流 - 末端带有实心圆的定向箭头表示控制流。
HIPO 图
HIPO(层次输入过程输出)图是分析系统并提供文档化手段的两种组织方法的组合。HIPO 模型由 IBM 于 1970 年开发。
HIPO 图表示软件系统中模块的层次结构。分析师使用 HIPO 图来获得系统功能的高级视图。它以层次方式将功能分解为子功能。它描述了系统执行的功能。
HIPO 图非常适合文档化目的。它们的图形表示使设计人员和管理人员更容易获得系统结构的图解。
与描绘模块中控制流和数据流的 IPO(输入过程输出)图相反,HIPO 不提供有关数据流或控制流的任何信息。
示例
HIPO 图的两个部分,层次表示和 IPO 图表,都用于软件程序的结构设计以及同一程序的文档化。
结构化英语
大多数程序员都没有意识到软件的大图景,因此他们只依赖于管理人员告诉他们做什么。高级软件管理人员有责任向程序员提供准确的信息,以开发准确且快速的代码。
使用图表或图的其他方法有时会被不同的人解释得不同。
因此,软件的分析师和设计师提出了诸如结构化英语之类的工具。它只不过是对需要编码的内容以及如何编码的描述。结构化英语帮助程序员编写无错误的代码。
使用图表或图的其他方法有时会被不同的人解释得不同。在这里,结构化英语和伪代码都试图弥合这种理解差距。
结构化英语使用结构化编程范例中的普通英语单词。它不是最终的代码,而是一种对需要编码的内容以及如何编码的描述。以下是结构化编程的一些标记。
IF-THEN-ELSE, DO-WHILE-UNTIL
分析师使用存储在数据字典中的相同变量和数据名称,这使得编写和理解代码更加简单。
示例
我们以在线购物环境中的客户身份验证为例。可以使用结构化英语编写此客户身份验证过程,如下所示:
Enter Customer_Name SEEK Customer_Name in Customer_Name_DB file IF Customer_Name found THEN Call procedure USER_PASSWORD_AUTHENTICATE() ELSE PRINT error message Call procedure NEW_CUSTOMER_REQUEST() ENDIF
用结构化英语编写的代码更像是日常口语英语。它不能直接作为软件代码实现。结构化英语独立于编程语言。
伪代码
伪代码更接近于编程语言。它可以被认为是增强的编程语言,充满了注释和描述。
伪代码避免变量声明,但它们使用某些实际编程语言的结构编写,例如 C、Fortran、Pascal 等。
伪代码比结构化英语包含更多编程细节。它提供了一种执行任务的方法,就像计算机正在执行代码一样。
示例
打印斐波那契数列直到 n 个数的程序。
void function Fibonacci Get value of n; Set value of a to 1; Set value of b to 1; Initialize I to 0 for (i=0; i< n; i++) { if a greater than b { Increase b by a; Print b; } else if b greater than a { increase a by b; print a; } }
决策表
决策表以结构化的表格格式表示条件以及为解决这些条件而应采取的相应操作。
它是一个强大的工具,可以调试和防止错误。它有助于将类似的信息分组到一个表中,然后通过组合表来提供简单方便的决策。
创建决策表
要创建决策表,开发人员必须遵循以下四个基本步骤
- 确定所有需要解决的可能条件
- 确定所有已识别条件的操作
- 创建尽可能多的规则
- 为每条规则定义操作
决策表应由最终用户验证,并且稍后可以通过消除重复规则和操作来简化。
示例
让我们以我们互联网连接的日常问题的简单示例为例。我们首先确定启动互联网时可能出现的所有问题及其各自可能的解决方案。
我们将所有可能的问题列在“条件”列下,并将可能的解决方案列在“操作”列下。
条件/操作 | 规则 | ||||||||
---|---|---|---|---|---|---|---|---|---|
条件 | 显示已连接 | N | N | N | N | Y | Y | Y | Y |
Ping 可用 | N | N | Y | Y | N | N | Y | Y | |
打开网站 | Y | N | Y | N | Y | N | Y | N | |
操作 | 检查网络电缆 | X | |||||||
检查互联网路由器 | X | X | X | X | |||||
重新启动 Web 浏览器 | X | ||||||||
联系服务提供商 | X | X | X | X | X | X | |||
不采取任何操作 |
实体关系模型
实体关系模型是一种数据库模型,基于现实世界实体及其之间关系的概念。我们可以将现实世界场景映射到 ER 数据库模型。ER 模型创建一组具有其属性的实体、一组约束以及它们之间的关系。
ER 模型最适合用于数据库的概念设计。ER 模型可以表示如下
实体 - ER 模型中的实体是现实世界中的存在,它具有一些称为属性的属性。每个属性都由其对应的值集定义,称为域。
例如,考虑一个学校数据库。这里,学生是一个实体。学生具有各种属性,例如姓名、ID、年龄和班级等。
关系 - 实体之间的逻辑关联称为关系。关系以各种方式映射到实体。映射基数定义两个实体之间的关联数。
映射基数
- 一对一
- 一对多
- 多对一
- 多对多
数据字典
数据字典是关于数据的集中式信息集合。它存储数据的含义和来源、它与其他数据的关联、使用的数据格式等。数据字典对所有名称都具有严格的定义,以方便用户和软件设计师。
数据字典通常被称为元数据(关于数据的数据)存储库。它与软件程序的数据流图 (DFD) 模型一起创建,并且在 DFD 发生更改或更新时,也应相应更新。
数据字典的需求
在软件设计和实现过程中,数据是通过数据字典来引用的。数据字典消除了任何歧义的可能性。它有助于使程序员和设计师在程序的各个部分使用相同的对象引用时保持工作同步。
数据字典提供了一种在一个地方记录完整数据库系统的方法。可以使用数据字典对 DFD 进行验证。
内容
数据字典应包含以下方面的信息:
- 数据流
- 数据结构
- 数据元素
- 数据存储
- 数据处理
数据流通过前面学习过的数据流图 (DFD) 来描述,并以所述的代数形式表示。
= | 组成部分 |
---|---|
{} | 重复 |
() | 可选 |
+ | 和 |
[ / ] | 或 |
示例
地址 = 门牌号 + (街道/区域)+ 城市 + 省份
课程ID = 课程编号 + 课程名称 + 课程级别 + 课程成绩
数据元素
数据元素由数据和控制项、内部或外部数据存储等的名称和描述组成,包含以下详细信息:
- 主名称
- 次要名称(别名)
- 用例(如何以及在哪里使用)
- 内容描述(符号等)
- 补充信息(预设值、约束等)
数据存储
它存储数据进入系统和离开系统的信息。数据存储可能包括:
- 文件
- 软件内部。
- 软件外部,但在同一台机器上。
- 软件和系统外部,位于不同的机器上。
- 表
- 命名约定
- 索引属性
数据处理
数据处理有两种类型:
- 逻辑:用户看到的
- 物理:软件看到的
软件设计策略
软件设计是一个将软件需求概念化为软件实现的过程。软件设计将用户需求作为挑战,并试图找到最佳解决方案。在软件概念化的过程中,会制定一个计划来找到实现预期解决方案的最佳设计。
软件设计有多种变体。让我们简要地学习它们。
结构化设计
结构化设计是将问题概念化为解决方案的几个组织良好的元素。它主要关注解决方案设计。结构化设计的优点是,它能够更好地理解如何解决问题。结构化设计还可以使设计人员更准确地专注于问题。
结构化设计主要基于“分而治之”的策略,其中一个问题被分解成几个较小的问题,并且每个小问题都被单独解决,直到整个问题被解决。
小问题的解决是通过解决方案模块来实现的。结构化设计强调这些模块必须组织良好,以实现精确的解决方案。
这些模块按层次排列。它们相互通信。良好的结构化设计始终遵循一些模块间通信规则,即:
内聚性 - 将所有功能相关的元素分组。
耦合性 - 不同模块之间的通信。
良好的结构化设计具有高内聚性和低耦合性。
面向函数的设计
在面向函数的设计中,系统由许多称为函数的较小的子系统组成。这些函数能够在系统中执行重要任务。系统被认为是所有函数的顶层视图。
面向函数的设计继承了结构化设计的一些属性,其中使用了分而治之的方法。
这种设计机制将整个系统划分为较小的函数,这通过隐藏信息及其操作来提供抽象方法。这些功能模块可以通过传递信息和使用全局可用的信息来相互共享信息。
函数的另一个特点是,当程序调用函数时,函数会改变程序的状态,这有时是其他模块无法接受的。面向函数的设计适用于系统状态无关紧要且程序/函数基于输入而不是状态的情况。
设计过程
- 整个系统被视为数据如何通过数据流图在系统中流动。
- DFD 描述了函数如何改变数据和整个系统状态。
- 整个系统根据其在系统中的操作逻辑地分解成较小的单元,称为函数。
- 然后详细描述每个函数。
面向对象的设计
面向对象的设计围绕实体及其特性而不是软件系统中涉及的函数展开。这种设计策略侧重于实体及其特性。软件解决方案的整个概念围绕参与的实体展开。
让我们看看面向对象设计的重要概念:
- 对象 - 解决方案设计中涉及的所有实体都称为对象。例如,人、银行、公司和客户都被视为对象。每个实体都有一些与其相关的属性,并有一些方法对属性进行操作。
类 - 类是对对象的概括性描述。对象是类的实例。类定义了对象可以具有的所有属性以及定义对象功能的方法。
在解决方案设计中,属性存储为变量,功能通过方法或过程定义。
- 封装 - 在 OOD 中,将属性(数据变量)和方法(对数据进行的操作)捆绑在一起称为封装。封装不仅将对象的 important 信息捆绑在一起,还限制了外部世界对数据和方法的访问。这称为信息隐藏。
- 继承 - OOD 允许相似的类以层次结构方式堆叠,其中较低的或子类可以从其直接的超类导入、实现和重用允许的变量和方法。OOD 的此属性称为继承。这使得定义特定类和从特定类创建通用类更容易。
- 多态性 - OOD 语言提供了一种机制,其中执行类似任务但参数不同的方法可以分配相同的名称。这称为多态性,它允许单个接口为不同类型执行任务。根据函数调用的方式,代码的相应部分将被执行。
设计过程
软件设计过程可以被视为一系列明确定义的步骤。尽管它根据设计方法(面向函数或面向对象)而有所不同,但它可能涉及以下步骤:
- 根据需求或先前使用的系统和/或系统序列图创建解决方案设计。
- 识别对象并根据属性特征的相似性将其分组到类中。
- 定义类层次结构及其之间的关系。
- 定义应用程序框架。
软件设计方法
以下是两种通用的软件设计方法:
自顶向下设计
我们知道一个系统是由多个子系统组成的,它包含许多组件。此外,这些子系统和组件可能有它们自己的子系统和组件集,并在系统中创建层次结构。
自顶向下设计将整个软件系统作为一个实体,然后根据某些特性将其分解为多个子系统或组件。然后将每个子系统或组件视为一个系统,并进一步分解。此过程持续运行,直到达到自顶向下层次结构中的最低系统级别。
自顶向下设计从系统的通用模型开始,并不断定义其更具体的方面。当所有组件组合在一起时,整个系统就形成了。
当软件解决方案需要从头设计并且具体细节未知时,自顶向下设计更合适。
自底向上设计
自底向上设计模型从最具体和最基本的组件开始。它通过使用基本或较低级别的组件来构建更高级别的组件。它不断创建更高级别的组件,直到所需的系统没有发展为单个组件。随着每个更高级别,抽象量都会增加。
当需要从某些现有系统创建系统时,自底向上策略更合适,其中基本原语可以在较新的系统中使用。
自顶向下和自底向上方法单独使用都不实用。相反,使用这两种方法的良好组合。
软件用户界面设计
用户界面是前端应用程序视图,用户与其交互以使用软件。用户可以通过用户界面操作和控制软件以及硬件。如今,用户界面几乎存在于任何使用数字技术的地方,从计算机、移动电话、汽车、音乐播放器、飞机、船舶等。
用户界面是软件的一部分,其设计方式旨在向用户提供对软件的洞察力。UI 为人机交互提供了基本平台。
UI 可以是图形化的、基于文本的、基于音频视频的,这取决于底层的硬件和软件组合。UI 可以是硬件或软件,也可以是两者的组合。
如果其用户界面:
- 吸引人
- 易于使用
- 响应时间短
- 易于理解
- 所有界面屏幕上保持一致
UI 主要分为两类:
- 命令行界面
- 图形用户界面
命令行界面 (CLI)
在视频显示器出现之前,CLI 一直是与计算机交互的重要工具。CLI 是许多技术用户和程序员的首选。CLI 是软件可以为用户提供的最小界面。
CLI 提供一个命令提示符,用户在此处键入命令并将其馈送到系统。用户需要记住命令的语法及其用法。早期的 CLI 没有被编程为有效地处理用户错误。
命令是文本形式的指令集的引用,系统预期执行这些指令。宏、脚本等方法使用户易于操作。
与 GUI 相比,CLI 使用的计算机资源较少。
CLI 元素
基于文本的命令行界面可以包含以下元素:
命令提示符 - 它是一个基于文本的通知器,主要显示用户正在工作的上下文。它由软件系统生成。
光标 - 它是一条细小的水平线或一条与行高相同的垂直条,用于表示打字时字符的位置。光标通常处于闪烁状态。当用户编写或删除内容时,它会移动。
命令 - 命令是一个可执行的指令。它可以有一个或多个参数。命令执行后的输出将直接显示在屏幕上。输出产生后,命令提示符将显示在下一行。
图形用户界面
图形用户界面 (GUI) 为用户提供了与系统交互的图形化方式。GUI 可以是硬件和软件的组合。用户通过 GUI 来理解软件。
通常,GUI 比 CLI 更消耗资源。随着技术的进步,程序员和设计师创建了更复杂、更高效、更准确、更快速的 GUI 设计。
GUI 元素
GUI 提供了一组组件来与软件或硬件交互。
每个图形组件都提供了一种与系统交互的方式。GUI 系统具有以下元素:
窗口 - 显示应用程序内容的区域。如果窗口代表文件结构,则窗口中的内容可以以图标或列表的形式显示。用户在资源管理器窗口中浏览文件系统更容易。窗口可以最小化、调整大小或最大化到屏幕大小。它们可以移动到屏幕上的任何位置。窗口可以包含同一应用程序的另一个窗口,称为子窗口。
标签 - 如果应用程序允许执行其多个实例,则它们会在屏幕上显示为单独的窗口。选项卡式文档界面 允许在同一窗口中打开多个文档。此界面还有助于查看应用程序中的首选项面板。所有现代网络浏览器都使用此功能。
菜单 - 菜单是一组标准命令的数组,它们组合在一起并放置在应用程序窗口中可见的位置(通常是顶部)。可以对菜单进行编程,使其在鼠标点击时显示或隐藏。
图标 - 图标是一张小图片,代表相关的应用程序。单击或双击这些图标时,将打开应用程序窗口。图标以小图片的形式显示系统上安装的应用程序和程序。
光标 - 在 GUI 中,鼠标、触摸板、数位笔等交互式设备表示为光标。屏幕光标几乎实时地遵循硬件的指令。在 GUI 系统中,光标也称为指针。它们用于选择菜单、窗口和其他应用程序功能。
特定于应用程序的 GUI 组件
应用程序的 GUI 包含列出的一个或多个 GUI 元素。
应用程序窗口 - 大多数应用程序窗口使用操作系统提供的结构,但许多应用程序使用自己创建的自定义窗口来包含应用程序的内容。
对话框 - 这是一个子窗口,包含给用户的提示信息以及需要采取的操作请求。例如:应用程序会生成一个对话框,以获取用户删除文件的确认。
文本框 - 为用户提供了一个区域来键入和输入基于文本的数据。
按钮 - 它们模拟现实生活中的按钮,用于向软件提交输入。
单选按钮 - 显示可供选择的选项。所有提供的选项中只能选择一个。
复选框 - 功能类似于列表框。选择一个选项后,该框将被标记为已选中。可以选中由复选框表示的多个选项。
列表框 - 提供可供选择的项目列表。可以选中多个项目。
其他令人印象深刻的 GUI 组件包括:
- 滑块
- 组合框
- 数据网格
- 下拉列表
用户界面设计活动
设计用户界面会执行许多活动。GUI 设计和实现的过程类似于 SDLC(软件开发生命周期)。瀑布模型、迭代模型或螺旋模型都可以用于 GUI 实现。
用于 GUI 设计和开发的模型应满足这些 GUI 特定的步骤。
GUI 需求收集 - 设计师可能希望列出 GUI 的所有功能和非功能需求。这可以从用户及其现有的软件解决方案中获得。
用户分析 - 设计师会研究谁将使用该软件 GUI。目标受众很重要,因为设计细节会根据用户的知识和能力水平而改变。如果用户是技术达人,则可以采用高级和复杂的 GUI。对于新手用户,会包含更多关于软件使用方法的信息。
任务分析 - 设计师必须分析软件解决方案要完成的任务。在 GUI 中,如何完成并不重要。任务可以以分层的方式表示,将一个主要任务进一步细分为较小的子任务。任务为 GUI 展示提供目标。子任务之间信息流决定了软件中 GUI 内容的流程。
GUI 设计与实现 - 设计师在获得关于需求、任务和用户环境的信息后,设计 GUI 并将其实现到代码中,并将 GUI 与后台的工作或虚拟软件嵌入在一起。然后由开发人员对其进行自测。
测试 - GUI 测试可以通过多种方式进行。组织可以进行内部检查,直接让用户参与,以及发布测试版等。测试可能包括可用性、兼容性、用户验收等。
GUI 实现工具
有几种工具可用,设计师可以使用这些工具只需单击鼠标即可创建整个 GUI。某些工具可以嵌入到软件环境(IDE)中。
GUI 实现工具提供强大的 GUI 控件数组。为了进行软件定制,设计师可以相应地更改代码。
根据不同的用途和平台,GUI 工具分为不同的部分。
示例
移动 GUI、计算机 GUI、触摸屏 GUI 等。以下是一些构建 GUI 的实用工具列表:
- FLUID
- AppInventor(Android)
- LucidChart
- Wavemaker
- Visual Studio
用户界面黄金法则
以下规则被认为是 GUI 设计的黄金法则,由 Shneiderman 和 Plaisant 在他们的著作《Designing the User Interface》(用户界面设计)中描述。
力求一致性 - 在类似的情况下,应需要一致的操作顺序。提示、菜单和帮助屏幕中应使用相同的术语。整个过程中应使用一致的命令。
允许频繁用户使用快捷键 - 用户减少交互次数的愿望会随着使用频率的增加而增加。缩写、功能键、隐藏命令和宏工具对专家用户非常有帮助。
提供信息反馈 - 对于每个操作员操作,都应该有一些系统反馈。对于频繁和次要的操作,响应必须适中,而对于不频繁和主要的操作,响应必须更充分。
设计对话框以产生闭合感 - 操作序列应组织成具有开始、中间和结束的组。在完成一组操作后提供的信息反馈,让操作员获得成就感、解脱感,并发出信号,让他们从脑海中放弃应急计划和选项,这表明前进的道路清晰,可以准备下一组操作。
提供简单的错误处理 - 尽可能设计系统,以防止用户犯严重错误。如果发生错误,系统应该能够检测到它,并提供简单易懂的错误处理机制。
允许轻松撤消操作 - 此功能可以减轻焦虑,因为用户知道可以撤消错误。轻松撤消操作鼓励探索不熟悉的选项。可逆转的单元可以是单个操作、数据条目或一组完整的操作。
支持内部控制中心 - 经验丰富的操作员强烈希望感觉到他们掌控着系统,并且系统响应他们的操作。设计系统,使用户成为操作的发起者,而不是响应者。
减少短期记忆负荷 - 人类在短期记忆中信息处理的局限性要求显示保持简单,多个页面显示合并,窗口移动频率降低,并分配足够的培训时间来学习代码、助记符和操作序列。
软件设计复杂性
复杂性是指事件或事物处于具有多个相互关联的链接和高度复杂结构的状态。在软件编程中,随着软件设计的实现,元素的数量及其相互连接的数量逐渐变得巨大,这使得一次难以理解。
如果不使用复杂性指标和度量,软件设计复杂性就难以评估。让我们看看三个重要的软件复杂性度量。
Halstead 复杂性度量
1977 年,Maurice Howard Halstead 先生引入了用于测量软件复杂性的指标。Halstead 指标取决于程序的实际实现及其度量,这些度量是静态地直接从源代码中的运算符和操作数计算出来的。它允许评估 C/C++/Java 源代码的测试时间、词汇量、大小、难度、错误和工作量。
根据 Halstead 的说法,“计算机程序是算法的实现,被认为是令牌的集合,这些令牌可以分为运算符或操作数”。Halstead 指标将程序视为运算符及其相关操作数的序列。
他定义了各种指标来检查模块的复杂性。
参数 | 含义 |
---|---|
n1 | 唯一运算符的数量 |
n2 | 唯一操作数的数量 |
N1 | 运算符的总出现次数 |
N2 | 操作数的总出现次数 |
当我们在度量查看器中选择源文件以查看其复杂性详细信息时,将在度量报告中看到以下结果
度量 | 含义 | 数学表示 |
---|---|---|
n | 词汇量 | n1 + n2 |
N | 大小 | N1 + N2 |
V | 体积 | 长度 * Log2(词汇量) |
D | 难度 | (n1/2) * (N1/n2) |
E | 工作量 | 难度 * 体积 |
B | 错误数 | 体积 / 3000 |
T | 测试时间 | 时间 = 工作量 / S,其中 S = 18 秒。 |
圈复杂度度量
每个程序都包含需要执行以执行某些任务的语句以及其他决定哪些语句需要执行的决策语句。这些决策结构改变了程序的流程。
如果我们比较两个大小相同的程序,那么具有更多决策语句的程序将更复杂,因为程序控制会频繁跳转。
McCabe 在 1976 年提出了圈复杂度度量来量化给定软件的复杂性。这是一个基于程序决策结构(例如 if-else、do-while、repeat-until、switch-case 和 goto 语句)的图形驱动模型。
创建流程控制图的过程
- 将程序分解成更小的块,由决策结构分隔。
- 创建表示每个块的节点。
- 按如下方式连接节点
如果控制可以从块 i 分支到块 j
绘制一条弧
从出口节点到入口节点
绘制一条弧。
为了计算程序模块的圈复杂度,我们使用以下公式 -
V(G) = e – n + 2 Where e is total number of edges n is total number of nodes
上述模块的圈复杂度是
e = 10 n = 8 Cyclomatic Complexity = 10 - 8 + 2 = 4
根据 P. Jorgensen 的说法,模块的圈复杂度不应超过 10。
功能点
它被广泛用于衡量软件的大小。功能点关注系统提供的功能。系统的特性和功能用于衡量软件复杂性。
功能点计数基于五个参数,分别命名为外部输入、外部输出、逻辑内部文件、外部接口文件和外部查询。为了考虑软件的复杂性,每个参数进一步分为简单、平均和复杂。
让我们看看功能点的参数
外部输入
来自外部的每个唯一输入都被视为外部输入。输入的唯一性是衡量的,因为没有两个输入应该具有相同的格式。这些输入可以是数据或控制参数。
简单 - 如果输入计数低且影响较少的内部文件
复杂 - 如果输入计数高且影响较多的内部文件
平均 - 简单和复杂之间。
外部输出
系统提供的所有输出类型都计入此类别。如果输出格式和/或处理是唯一的,则输出被认为是唯一的。
简单 - 如果输出计数低
复杂 - 如果输出计数高
平均 - 简单和复杂之间。
逻辑内部文件
每个软件系统都维护内部文件以维护其功能信息并正常运行。这些文件保存系统的逻辑数据。这些逻辑数据可能包含功能数据和控制数据。
简单 - 如果记录类型数量少
复杂 - 如果记录类型数量多
平均 - 简单和复杂之间。
外部接口文件
软件系统可能需要与其它的外部软件共享其文件,或者它可能需要将文件传递给某个函数进行处理或作为参数。
简单 - 如果共享文件中记录类型的数量少
复杂 - 如果共享文件中记录类型的数量多
平均 - 简单和复杂之间。
外部查询
查询是输入和输出的组合,用户发送一些数据作为输入进行查询,系统则以处理后的查询输出响应用户。查询的复杂性高于外部输入和外部输出。如果查询的输入和输出在格式和数据方面是唯一的,则该查询被认为是唯一的。
简单 - 如果查询需要较少的处理并产生少量输出数据
复杂 - 如果查询需要大量的处理并产生大量的输出数据
平均 - 简单和复杂之间。
系统中的每个参数都会根据其类别和复杂性赋予权重。下表列出了赋予每个参数的权重
参数 | 简单 | 平均 | 复杂 |
---|---|---|---|
输入 | 3 | 4 | 6 |
输出 | 4 | 5 | 7 |
查询 | 3 | 4 | 6 |
文件 | 7 | 10 | 15 |
接口 | 5 | 7 | 10 |
上表得出原始功能点。这些功能点会根据环境复杂性进行调整。系统使用十四个不同的特性来描述
- 数据通信
- 分布式处理
- 性能目标
- 操作配置负载
- 事务速率
- 在线数据输入
- 最终用户效率
- 在线更新
- 复杂的处理逻辑
- 可重用性
- 安装简易性
- 操作简易性
- 多个站点
- 希望方便更改
这些特性因素的等级从 0 到 5,如下所示
- 无影响
- 偶然的
- 适中的
- 平均
- 重要的
- 必要的
所有等级相加为 N。N 的值范围为 0 到 70(14 种特性 x 5 种等级)。它用于使用以下公式计算复杂性调整因子 (CAF)
CAF = 0.65 + 0.01N
然后,
Delivered Function Points (FP)= CAF x Raw FP
此 FP 可用于各种度量,例如
成本 = 美元/FP
质量 = 错误数/FP
生产力 = FP/人月
软件实现
在本章中,我们将学习软件实现中的编程方法、文档和挑战。
结构化编程
在编码过程中,代码行不断增加,从而导致软件大小增加。逐渐地,记住程序流程变得几乎不可能。如果一个人忘记了软件及其底层程序、文件、过程是如何构建的,那么共享、调试和修改程序就会变得非常困难。解决这个问题的方法是结构化编程。它鼓励开发人员使用子程序和循环,而不是在代码中使用简单的跳转,从而使代码更清晰并提高其效率。结构化编程还有助于程序员减少编码时间并正确组织代码。
结构化编程规定了程序的编码方式。结构化编程使用三个主要概念
自顶向下分析 - 软件总是被用来执行一些合理的工作。在软件术语中,这项合理的工作被称为问题。因此,了解如何解决问题非常重要。在自顶向下分析中,问题被分解成许多小的部分,每个部分都有一定的意义。每个问题都被单独解决,并清楚地说明了解决问题的方法。
模块化编程 - 在编程中,代码被分解成更小的指令组。这些组被称为模块、子程序或子例程。模块化编程基于对自顶向下分析的理解。它不鼓励使用程序中的“goto”语句进行跳转,这通常会使程序流程难以追踪。在结构化编程中禁止跳转并鼓励模块化格式。
结构化编码 - 参考自顶向下分析,结构化编码按照其执行顺序将模块进一步细分为更小的代码单元。结构化编程使用控制结构来控制程序的流程,而结构化编码使用控制结构以可定义的模式组织其指令。
函数式编程
函数式编程是一种编程语言风格,它使用数学函数的概念。数学中的函数在接收到相同的参数时应该总是产生相同的结果。在过程式语言中,程序的流程通过过程运行,即程序的控制被转移到被调用的过程。当控制流从一个过程转移到另一个过程时,程序会改变其状态。
在过程式编程中,过程在使用相同参数调用时可能产生不同的结果,因为程序本身在调用时可能处于不同的状态。这是过程式编程的一个特性也是一个缺点,其中过程执行的顺序或时间变得很重要。
函数式编程提供了一种将计算作为数学函数的方法,无论程序状态如何,它都会产生结果。这使得预测程序的行为成为可能。
函数式编程使用以下概念
一等函数和高阶函数 - 这些函数能够接受另一个函数作为参数,或者将其他函数作为结果返回。
纯函数 - 这些函数不包括破坏性更新,也就是说,它们不影响任何 I/O 或内存,如果它们没有被使用,则可以很容易地删除它们而不会影响程序的其余部分。
递归 - 递归是一种编程技术,其中一个函数调用自身并在其中重复程序代码,直到满足某个预定义的条件。递归是在函数式编程中创建循环的方式。
严格求值 - 这是一种对作为参数传递给函数的表达式进行求值的方法。函数式编程有两种求值方法,严格(急切)或非严格(惰性)。严格求值总是在调用函数之前对表达式进行求值。非严格求值不会对表达式求值,除非需要。
λ演算 - 大多数函数式编程语言使用 λ 演算作为其类型系统。λ 表达式在出现时通过对其进行求值来执行。
Common Lisp、Scala、Haskell、Erlang 和 F# 是一些函数式编程语言的示例。
编程风格
编程风格是一套所有程序员遵循的编写代码的规则。当多个程序员在一个软件项目上工作时,他们经常需要使用其他开发人员编写的程序代码。如果所有开发人员不遵循某些标准编程风格来编写程序,这将变得繁琐,有时甚至是不可能的。
适当的编程风格包括使用与预期任务相关的函数和变量名称、使用放置良好的缩进、为方便读者编写代码注释以及代码的整体演示。这使得程序代码易于被所有人阅读和理解,从而使调试和错误解决更容易。此外,正确的编码风格有助于简化文档和更新。
编码规范
编码风格的做法因组织、操作系统和编码语言本身而异。
以下编码元素可以在组织的编码规范中定义
命名约定 - 本节定义如何命名函数、变量、常量和全局变量。
缩进 - 这通常是行首留出的空格,通常是 2-8 个空格或单个制表符。
空格 - 通常省略行尾空格。
运算符 - 定义编写数学、赋值和逻辑运算符的规则。例如,赋值运算符“=”应该在其前后留有空格,例如“x = 2”。
控制结构 - 编写 if-then-else、case-switch、while-until 和 for 控制流语句的规则,包括单独使用和嵌套使用。
行长和换行 - 定义一行中应该有多少个字符,通常一行是 80 个字符长。换行定义了如果一行太长应该如何换行。
函数 - 这定义了如何声明和调用函数,包括带参数和不带参数的函数。
变量 - 这提到了如何声明和定义不同数据类型的变量。
注释 - 这是重要的编码组件之一,因为代码中包含的注释描述了代码的实际作用以及所有其他相关的描述。本节还有助于为其他开发人员创建帮助文档。
软件文档
软件文档是软件流程的重要组成部分。一份编写良好的文档提供了必要的软件流程信息库,是一个极好的工具和信息资源。软件文档还提供有关如何使用产品的信息。
一份维护良好的文档应包含以下文档
需求文档 - 这份文档是软件设计人员、开发人员和测试团队执行各自任务的关键工具。这份文档包含目标软件的所有功能性、非功能性和行为描述。
这份文档的来源可以是先前存储的软件数据、客户端已运行的软件、客户端访谈、问卷调查和研究。通常情况下,它以电子表格或文字处理文档的形式存储在高端软件管理团队中。
这份文档是待开发软件的基础,主要用于验证和确认阶段。大多数测试用例都是直接根据需求文档构建的。
软件设计文档 - 这些文档包含构建软件所需的所有必要信息,包括:(a) 高级软件架构,(b) 软件设计细节,(c) 数据流图,(d) 数据库设计
这些文档是开发人员实现软件的资源库。虽然这些文档没有提供任何关于如何编写程序的细节,但它们提供了编码和实现所需的所有必要信息。
技术文档 - 这些文档由开发人员和实际编码人员维护。这些文档作为一个整体,代表了关于代码的信息。在编写代码时,程序员还会说明代码的目标、编写者、需要使用的位置、代码的功能和实现方式、代码使用的其他资源等。
技术文档增强了不同程序员之间对同一代码的理解。它增强了代码的可重用性。它使调试更容易且可追溯。
有各种各样的自动化工具可用,有些工具与编程语言本身一起提供。例如,Java 提供了 JavaDoc 工具来生成代码的技术文档。
用户文档 - 这份文档与上述所有文档都不同。所有之前的文档都是为了提供关于软件及其开发流程的信息而维护的。但用户文档解释了软件产品应该如何工作以及如何使用它来获得所需的结果。
这些文档可能包括软件安装过程、操作指南、用户指南、卸载方法以及获取更多信息的特殊参考,例如许可证更新等。
软件实现挑战
开发团队在实现软件时会面临一些挑战。其中一些如下所示
代码重用 - 当今编程语言的编程接口非常复杂,并配备了大量的库函数。但为了降低最终产品的成本,组织管理层更倾向于重用为其他软件创建的代码。程序员在兼容性检查和决定重用多少代码方面面临着巨大的问题。
版本管理 - 每当向客户发布新软件时,开发人员都必须维护版本和配置相关的文档。这些文档需要高度准确并按时提供。
目标主机 - 组织正在开发的软件程序需要为客户端的宿主机器设计。但有时,不可能设计出一个在目标机器上运行的软件。
软件测试概述
软件测试是对软件进行评估,以验证其是否满足从用户和系统规范中收集的需求。测试是在软件开发生命周期的阶段级别或程序代码的模块级别进行的。软件测试包括验证和确认。
软件确认
确认是检查软件是否满足用户需求的过程。它在 SDLC 结束时进行。如果软件符合其制作的要求,则认为它是有效的。
- 确认确保正在开发的产品符合用户需求。
- 确认回答了这样一个问题——“我们开发的产品是否满足用户对该软件的所有需求?”
- 确认强调用户需求。
软件验证
验证是确认软件是否满足业务需求,以及是否按照正确的规范和方法开发的过程。
- 验证确保正在开发的产品符合设计规范。
- 验证回答了这样一个问题——“我们是否按照所有设计规范严格地开发此产品?”
- 验证侧重于设计和系统规范。
测试的目标是 -
错误 - 这些是开发人员实际犯下的编码错误。此外,软件的输出与预期输出之间的差异也被认为是错误。
缺陷 - 当存在错误时,就会发生缺陷。缺陷,也称为 bug,是错误的结果,可能导致系统故障。
故障 - 故障是指系统无法执行所需任务。当系统中存在缺陷时,就会发生故障。
手动测试与自动化测试
测试既可以手动进行,也可以使用自动化测试工具进行
手动测试 - 这种测试是在不借助自动化测试工具的情况下进行的。软件测试人员为代码的不同部分和级别准备测试用例,执行测试并将结果报告给经理。
手动测试既费时又费资源。测试人员需要确认是否使用了正确的测试用例。大部分测试都涉及手动测试。
自动化测试 这种测试是借助自动化测试工具进行的测试过程。使用自动化测试工具可以克服手动测试的局限性。
一项测试需要检查是否可以在 Internet Explorer 中打开网页。这可以通过手动测试轻松完成。但是,要检查 Web 服务器是否能够承受 100 万用户的负载,手动测试是无法实现的。
有一些软件和硬件工具可以帮助测试人员进行负载测试、压力测试和回归测试。
测试方法
测试可以基于两种方法进行:
- 功能测试
- 实现测试
当在不考虑实际实现的情况下测试功能时,这被称为黑盒测试。另一方面被称为白盒测试,它不仅测试功能,还分析实现方式。
穷举测试是理想的完美测试方法。测试输入和输出值范围内的每一个可能的取值。如果取值范围很大,在现实场景中不可能测试每个取值。
黑盒测试
它用于测试程序的功能。它也称为“行为”测试。在这种情况下,测试人员有一组输入值和相应的预期结果。提供输入后,如果输出与预期结果匹配,则程序测试“通过”,否则出现问题。
在这种测试方法中,代码的设计和结构对测试人员是未知的,测试工程师和最终用户对软件进行此测试。
黑盒测试技术
等价类 - 输入被划分为相似的类。如果一个类的元素通过了测试,则假定该类的所有元素都通过了测试。
边界值 - 输入被划分为较高和较低端的值。如果这些值通过了测试,则假定介于两者之间的所有值也可能通过。
因果图 - 在前面两种方法中,一次只测试一个输入值。因果图是一种测试技术,它以系统的方式测试输入值的组合。
配对测试 - 软件的行为取决于多个参数。在配对测试中,对多个参数的不同值进行配对测试。
基于状态的测试 - 系统在提供输入时会更改状态。这些系统根据其状态和输入进行测试。
白盒测试
它用于测试程序及其实现,以提高代码效率或结构。它也称为“结构”测试。
在这种测试方法中,代码的设计和结构对测试人员是已知的。代码的程序员对代码进行此测试。
以下是一些白盒测试技术
控制流测试 - 控制流测试的目的是设置覆盖所有语句和分支条件的测试用例。分支条件被测试为真和假,以便可以覆盖所有语句。
数据流测试 - 这种测试技术强调覆盖程序中包含的所有数据变量。它测试变量的声明和定义位置以及使用或更改的位置。
测试级别
测试本身可以在 SDLC 的各个级别定义。测试过程与软件开发并行运行。在进入下一阶段之前,需要对一个阶段进行测试、验证和确认。
单独进行测试只是为了确保软件中没有隐藏的错误或问题。软件在各个级别进行测试 -
单元测试
在编码过程中,程序员会对程序的单元进行一些测试,以了解它是否没有错误。测试是在白盒测试方法下进行的。单元测试帮助开发人员确定程序的各个单元是否按要求工作并且没有错误。
集成测试
即使软件的单元单独工作良好,也需要找出如果将这些单元集成在一起是否也能正常工作,例如参数传递和数据更新等。
系统测试
软件被编译成产品,然后作为一个整体进行测试。这可以通过以下一项或多项测试来完成
功能测试 - 根据需求测试软件的所有功能。
性能测试 - 此测试证明软件的效率。它测试软件执行所需任务的效率和平均时间。性能测试是通过负载测试和压力测试来完成的,其中软件在各种环境条件下承受高用户和数据负载。
安全性和可移植性 - 当软件旨在在各种平台上运行并被多人访问时,会进行这些测试。
验收测试
当软件准备交付给客户时,它必须经过最后的测试阶段,在该阶段中,它将针对用户交互和响应进行测试。这很重要,因为即使软件满足所有用户需求,如果用户不喜欢其外观或工作方式,也可能会被拒绝。
α测试 - 开发团队本身通过在工作环境中使用系统来执行 α 测试。他们试图找出用户对软件中某些操作的反应以及系统应如何响应输入。
β测试 - 在软件内部测试后,将其交给用户,仅出于测试目的在其生产环境中使用。这还不是交付的产品。开发人员期望用户在此阶段会发现一些微小的错误,而这些错误之前被忽略了。
回归测试
每当软件产品使用新代码、功能或功能进行更新时,都会对其进行彻底测试,以检测添加的代码是否产生任何负面影响。这称为回归测试。
测试文档
测试文档在不同阶段准备 -
测试前
测试从生成测试用例开始。需要参考以下文档 -
SRS 文档 - 功能需求文档
测试策略文档 - 描述在发布产品之前应进行多长时间的测试。
测试策略文档 - 本文档详细说明了测试团队、责任矩阵以及测试经理和测试工程师的权利/责任。
可追溯性矩阵文档 - 这是SDLC文档,与需求收集过程相关。随着新需求的到来,它们将添加到此矩阵中。这些矩阵帮助测试人员了解需求的来源。它们可以向前和向后追溯。
测试期间
测试开始和进行期间可能需要以下文档
测试用例文档 - 此文档包含需要执行的测试列表。它包括单元测试计划、集成测试计划、系统测试计划和验收测试计划。
测试描述 - 此文档详细描述了所有测试用例和执行它们的程序。
测试用例报告 - 此文档包含测试结果的测试用例报告。
测试日志 - 此文档包含每个测试用例报告的测试日志。
测试后
测试后可能会生成以下文档
测试总结 - 此测试总结是对所有测试报告和日志的综合分析。它总结并得出软件是否准备好发布的结论。如果软件准备好发布,则在版本控制系统下发布。
测试与质量控制、质量保证和审计
我们需要理解软件测试不同于软件质量保证、软件质量控制和软件审计。
软件质量保证 - 这些是软件开发过程监控手段,通过它可以确保所有措施都按照组织的标准执行。进行此监控是为了确保遵循适当的软件开发方法。
软件质量控制 - 这是一个维护软件产品质量的系统。它可能包括软件产品的功能和非功能方面,这增强了组织的商誉。该系统确保客户获得满足其需求的优质产品,并且产品被认证为“适合使用”。
软件审计 - 这是对组织用于开发软件的程序的审查。一个独立于开发团队的审计团队检查软件过程、程序、需求和SDLC的其他方面。软件审计的目的是检查软件及其开发过程是否都符合标准、规则和法规。
软件维护概述
软件维护现在已被广泛接受为SDLC的一部分。它代表软件产品交付后进行的所有修改和更新。需要进行修改的原因有很多,其中一些简要介绍如下
市场环境 - 随着时间的推移而变化的政策,例如税收和新引入的约束,例如如何维护簿记,可能会触发修改的需求。
客户需求 - 随着时间的推移,客户可能会要求软件提供新的功能。
主机修改 - 如果目标主机的任何硬件和/或平台(例如操作系统)发生变化,则需要更改软件以保持适应性。
组织变化 - 如果客户方面有任何业务层面的变化,例如组织规模缩减、收购另一家公司、组织涉足新业务,则可能需要修改原始软件。
维护类型
在软件生命周期中,维护类型可能会根据其性质而有所不同。它可能只是某些用户发现的错误的例行维护任务,也可能根据维护规模或性质本身就是一个大型事件。以下是根据其特征的一些维护类型
纠正性维护 - 这包括为了纠正或修复问题而进行的修改和更新,这些问题要么由用户发现,要么由用户错误报告得出结论。
适应性维护 - 这包括应用的修改和更新,以使软件产品保持最新状态,并适应不断变化的技术和商业环境。
完善性维护 - 这包括为了使软件在较长时间内保持可用而进行的修改和更新。它包括新功能、改进软件的新用户需求以及提高其可靠性和性能。
预防性维护 - 这包括进行修改和更新以防止软件的未来问题。其目的是解决目前并不重要但将来可能导致严重问题的问题。
维护成本
报告表明,维护成本很高。一项关于估计软件维护成本的研究发现,维护成本高达整个软件过程周期的67%。
平均而言,软件维护成本超过所有SDLC阶段的50%。有各种因素导致维护成本居高不下,例如
影响维护成本的现实因素
- 任何软件的标准使用寿命被认为最多为10到15年。
- 旨在在内存和存储容量较小的慢速机器上运行的较旧软件无法在现代硬件上的新兴增强型软件面前保持竞争力。
- 随着技术的进步,维护旧软件的成本变得很高。
- 大多数维护工程师都是新手,并使用反复试验的方法来纠正问题。
- 通常,所做的更改很容易损害软件的原始结构,从而使任何后续更改都变得困难。
- 更改通常没有记录,这可能会在将来导致更多冲突。
影响维护成本的软件端因素
- 软件程序的结构
- 编程语言
- 对外部环境的依赖
- 员工的可靠性和可用性
维护活动
IEEE为顺序维护过程活动提供了一个框架。它可以以迭代方式使用,并且可以扩展,以便可以包含自定义项目和过程。
这些活动与以下每个阶段相辅相成
识别与追踪 - 它涉及与识别修改或维护需求相关的活动。它由用户生成,系统本身也可能通过日志或错误消息报告。在这里,维护类型也被分类。
分析 - 分析修改对系统的影响,包括安全隐患。如果可能的影响严重,则寻找替代方案。然后将一组所需的修改具体化为需求规范。分析修改/维护的成本并得出估计。
设计 - 根据上一阶段设定的需求规范,设计需要替换或修改的新模块。创建测试用例以进行验证。
实现 - 在设计步骤中创建的结构化设计的帮助下对新模块进行编码。每个程序员都应该并行进行单元测试。
系统测试 - 在新创建的模块之间进行集成测试。还在新模块和系统之间进行集成测试。最后,按照回归测试程序对整个系统进行测试。
验收测试 - 在内部测试系统后,在用户的帮助下对其进行验收测试。如果在此状态下,用户抱怨某些问题,则会解决这些问题或记录下来以便在下次迭代中解决。
交付 - 验收测试后,系统将通过小型更新包或系统的全新安装部署到整个组织。软件交付后,最终测试将在客户端进行。
如果需要,除了用户手册的纸质副本外,还将提供培训设施。
维护管理 - 配置管理是系统维护的重要组成部分。它借助版本控制工具来控制版本、半版本或补丁管理。
软件再工程
当我们需要更新软件以使其保持在当前市场水平,而又不影响其功能时,这称为软件再工程。这是一个彻底的过程,其中软件的设计被更改并且程序被重写。
遗留软件无法与市场上最新的技术保持同步。随着硬件的过时,软件的更新变得令人头疼。即使软件随着时间的推移而老化,其功能也不会消失。
例如,Unix 最初是用汇编语言开发的。当 C 语言出现时,Unix 被用 C 语言重新设计,因为用汇编语言工作很困难。
除此之外,有时程序员会注意到软件的某些部分比其他部分需要更多的维护,并且它们也需要再工程。
再工程过程
- 决定要再工程什么。是整个软件还是一部分?
- 执行反向工程,以获得现有软件的规范。
- 如有必要,重构程序。例如,将面向函数的程序更改为面向对象的程序。
- 根据需要重构数据。
- 应用正向工程概念以获得再工程的软件。
软件再工程中使用了一些重要的术语
反向工程
这是一个通过彻底分析、理解现有系统来实现系统规范的过程。这个过程可以看作是反向SDLC模型,即我们试图通过分析较低的抽象级别来获得较高的抽象级别。
现有系统是先前实现的设计,我们对其一无所知。然后,设计人员通过查看代码并尝试获取设计来进行反向工程。有了设计,他们试图得出规范。因此,从代码反向到系统规范。
程序重构
这是一个重构和重建现有软件的过程。它完全是关于重新排列源代码,无论是在相同的编程语言中还是从一种编程语言到另一种编程语言。重构可以包括源代码重构和数据重构,或者两者兼而有之。
重构不会影响软件的功能,但会提高可靠性和可维护性。可以更改或更新经常导致错误的程序组件。
可以通过重构来消除软件对过时硬件平台的依赖性。
正向工程
正向工程是从现有规范中获取所需软件的过程,这些规范是通过反向工程获得的。它假设过去已经完成了一些软件工程工作。
前向工程与软件工程过程相同,只有一点不同——它总是在逆向工程之后进行。
组件可重用性
组件是软件程序代码的一部分,它在系统中执行独立的任务。它可以是一个小模块或子系统本身。
示例
网络上使用的登录过程可以被认为是组件,软件中的打印系统可以被视为软件的一个组件。
组件具有较高的功能内聚性和较低的耦合率,即它们独立工作,可以执行任务而无需依赖其他模块。
在面向对象编程中,对象的设计非常具体地针对它们关注的问题,并且很少有机会在其他软件中使用。
在模块化编程中,模块的编码是为了执行特定任务,这些任务可以在许多其他软件程序中使用。
有一个全新的垂直领域,它基于软件组件的重用,被称为基于组件的软件工程 (CBSE)。
重用可以在不同的层次上进行
应用级 - 将整个应用程序用作新软件的子系统。
组件级 - 使用应用程序的子系统。
模块级 - 重用功能模块。
软件组件提供接口,可用于建立不同组件之间的通信。
重用过程
可以采用两种方法:保持需求相同并调整组件,或者保持组件相同并修改需求。
需求规范 - 使用现有系统、用户输入或两者兼而有之,指定软件产品必须符合的功能和非功能需求。
设计 - 这也是标准 SDLC 过程步骤,其中需求以软件术语定义。创建整个系统及其子系统的基本架构。
指定组件 - 通过研究软件设计,设计人员将整个系统细分为更小的组件或子系统。一个完整的软件设计变成了一个庞大的组件集合共同工作。
搜索合适的组件 - 设计人员参考软件组件库,根据功能和预期的软件需求搜索匹配的组件。
集成组件 - 将所有匹配的组件打包在一起,以将其塑造成完整的软件。
软件案例工具概述
CASE 代表Computer Aided Software Engineering(计算机辅助软件工程)。这意味着在各种自动化软件工具的帮助下开发和维护软件项目。
CASE 工具
CASE 工具是一组软件应用程序,用于自动化 SDLC 活动。软件项目经理、分析师和工程师使用 CASE 工具来开发软件系统。
有许多 CASE 工具可用于简化软件开发生命周期的各个阶段,例如分析工具、设计工具、项目管理工具、数据库管理工具、文档工具等等。
使用 CASE 工具可以加快项目开发以产生预期结果,并有助于在继续进行软件开发的下一阶段之前发现缺陷。
CASE 工具的组成部分
根据在特定 SDLC 阶段的使用,CASE 工具大致可以分为以下几部分
中央存储库 - CASE 工具需要一个中央存储库,它可以作为常见、集成和一致信息的来源。中央存储库是一个中央存储位置,存储产品规范、需求文档、相关报告和图表以及其他关于管理的有用信息。中央存储库也用作数据字典。
上层 CASE 工具 - 上层 CASE 工具用于 SDLC 的规划、分析和设计阶段。
下层 CASE 工具 - 下层 CASE 工具用于实现、测试和维护。
集成 CASE 工具 - 集成 CASE 工具有助于 SDLC 的所有阶段,从需求收集到测试和文档。
如果 CASE 工具具有相似的功能、流程活动和与其他工具集成的能力,则可以将其组合在一起。
CASE 工具的范围
CASE 工具的范围贯穿整个 SDLC。
CASE 工具类型
现在我们简要介绍各种 CASE 工具
图表工具
这些工具用于以图形形式表示系统组件、数据和各种软件组件之间的控制流以及系统结构。例如,用于创建最先进流程图的流程图制作工具。
流程建模工具
流程建模是一种创建软件流程模型的方法,该模型用于开发软件。流程建模工具帮助管理人员选择流程模型或根据软件产品的需求对其进行修改。例如,EPF Composer。
项目管理工具
这些工具用于项目规划、成本和工作量估算、项目调度和资源规划。管理人员必须严格遵守软件项目管理中提到的每个步骤来执行项目。项目管理工具有助于在整个组织中实时存储和共享项目信息。例如,Creative Pro Office、Trac Project、Basecamp。
文档工具
软件项目中的文档工作始于软件过程之前,贯穿 SDLC 的所有阶段,并在项目完成后完成。
文档工具为技术用户和最终用户生成文档。技术用户主要是开发团队的内部专业人员,他们参考系统手册、参考手册、培训手册、安装手册等。最终用户文档描述系统的功能和使用方法,例如用户手册。例如,用于文档编制的 Doxygen、DrExplain、Adobe RoboHelp。
分析工具
这些工具有助于收集需求,自动检查图表中是否存在任何不一致、不准确之处、数据冗余或错误遗漏。例如,用于需求分析的 Accept 360、Accompa、CaseComplete,用于全面分析的 Visible Analyst。
设计工具
这些工具帮助软件设计师设计软件的模块结构,可以使用细化技术将其进一步分解成更小的模块。这些工具提供了每个模块的详细信息以及模块之间的互连。例如,Animated Software Design。
配置管理工具
软件的一个实例在一个版本下发布。配置管理工具处理:
- 版本和修订管理
- 基线配置管理
- 变更控制管理
CASE 工具通过自动跟踪、版本管理和发布管理来帮助实现这一点。例如,Fossil、Git、Accu REV。
变更控制工具
这些工具被认为是配置管理工具的一部分。它们处理在软件确定基线后或软件首次发布后对软件所做的更改。CASE 工具自动化变更跟踪、文件管理、代码管理等等。它还有助于执行组织的变更策略。
编程工具
这些工具包括编程环境,如 IDE(集成开发环境)、内置模块库和仿真工具。这些工具为构建软件产品提供了全面的帮助,并包括仿真和测试功能。例如,用于在 C 中搜索代码的 Cscope、Eclipse。
原型工具
软件原型是预期软件产品的模拟版本。原型提供了产品的初始外观和感觉,并模拟了实际产品的某些方面。
原型设计 CASE 工具基本上带有图形库。它们可以创建独立于硬件的用户界面和设计。这些工具帮助我们根据现有信息构建快速原型。此外,它们还提供软件原型的模拟。例如,Serena prototype composer、Mockup Builder。
Web 开发工具
这些工具有助于设计网页以及所有相关元素,如表单、文本、脚本、图形等等。Web 工具还提供正在开发的内容的实时预览,以及完成后它会是什么样子。例如,Fontello、Adobe Edge Inspect、Foundation 3、Brackets。
质量保证工具
软件组织中的质量保证是对开发软件产品的工程过程和方法的监控,以确保符合组织标准的质量。QA 工具包括配置和变更控制工具以及软件测试工具。例如,SoapTest、AppsWatch、JMeter。
维护工具
软件维护包括在软件产品交付后对其进行修改。自动日志记录和错误报告技术、自动错误工单生成和根本原因分析是一些 CASE 工具,这些工具可以帮助软件组织进行 SDLC 的维护阶段。例如,用于缺陷跟踪的 Bugzilla、HP Quality Center。