《软件工程》复习题✏️
《软件工程》复习题
第一章 软件工程学概述
选择题
-
下列说法中正确的是()
A. 20世纪50年代提出了软件工程的概念
B. 20世纪60年代提出了软件工程的概念
C. 20世纪70年代出现了客户机/服务器技术
D. 20世纪80年代软件工程学科达到成熟
答案: B
-
产生软件危机的主要原因是()
A. 软件工具落后
B. 软件生产能力不足
C. 实施严格的版本控制
D. 软件本身的特点及开发方法不满足
答案: D
-
软件工程的三要素是()
A. 技术、方法和工具
B. 方法、对象和类
C. 方法、工具和过程
D. 过程、模型和方法
答案: C
-
在下列选项中,( )不属于软件工程学科所要研究的基本内容
A. 软件工程材料
B. 软件工程方法
C. 软件工程原理
D. 软件工程过程
答案: A
判断题
-
软件就是程序,编写软件就是编写程序。
答案: 错误
-
软件危机的主要表现是软件需求增加,软件价格上升。
答案: 错误
-
软件工程学科出现的主要原因是软件危机出现。
答案: 正确
-
软件工程工具的作用是为了延长软件产品的寿命。
答案: 错误
填空题
- 软件危机是指人们在
开发和维护过程中遇到的一系列问题。 - 忽略软件开发前期的
需求分析是造成软件危机的一大原因。 - 开发出来的软件产品不能满足用户的需求,即产品的功能或特性与
用户的需求并不符合。 - 软件工程分为工具层、方法层、过程层,以及
质量焦点层。 - 软件工程第一次提出是在
1968年NATO(北约)科学委员会举办的学术会议上。
主观题
-
为什么说软件工程的发展可以在一定程度上解决软件危机的各种弊端?
思考提示: 软件危机的主要表现是什么?软件工程如何通过系统化方法、过程管理、标准化、工具支持、质量保证等方式来解决这些问题?(例如:通过需求分析解决不符需求;通过项目管理解决超期超预算;通过质量保证解决质量低劣;通过规范化解决难以维护等)
-
请简述软件工程的基本原则。
思考提示: 至少列举并简要解释4-5条核心原则。(例如:分阶段生命周期管理、阶段评审、产品控制/配置管理、采用现代技术、结果可审查、注重质量等)
-
请简述软件工程的目标。
思考提示: 软件工程主要想达到什么目的?从质量、成本、时间、用户需求满足、可维护性、生产效率等方面去阐述。
-
通常有哪几种软件开发方法?
思考提示: 主要分为哪两大类?各包含哪些具体模型/框架?(例如:传统方法-瀑布、V模型、螺旋;敏捷方法-Scrum、看板、XP等),并简单提及各自特点。
第二章 软件过程
选择题
-
增量模型本质上是一种()
A. 线性顺序模型
B. 整体开发模型
C. 非整体开发模型
D. 螺旋模型
答案: A
-
软件过程是()
A. 特定的开发模型
B. 一种软件求解的计算逻辑
C. 软件开发活动的集合
D. 软件生命周期模型
答案: C
-
软件生命周期模型不包括()
A. 瀑布模型
B. 用例模型
C. 增量模型
D. 螺旋模型
答案: B
-
包含风险分析的软件过程模型是()
A. 螺旋模型
B. 瀑布模型
C. 增量模型
D. 喷泉模型
答案: A
-
软件工程中描述生命周期的瀑布模型一般包括需求分析、设计、编码、()、维护等几个阶段。
A. 产品发布
B. 版本更新
C. 可行性分析
D. 测试
答案: D
-
螺旋模型综合了()的优点,并增加了风险分析。
A. 增量模型和喷泉模型
B. 瀑布模型和快速原型模型
C. 瀑布模型和喷泉模型
D. 快速原型模型和喷泉模型
答案: B
判断题
-
瀑布模型的最大优点是将软件开发的各个阶段划分得十分清晰。
答案: 正确
-
螺旋模型在瀑布模型和增量模型的基础上增加了风险分析。
答案: 错误 (注:螺旋模型结合的是瀑布模型和快速原型模型,并增加了风险分析)
-
软件工程过程应该以软件设计为中心,关键是编写程序。
答案: 错误 (注:软件工程是全面的过程,包括需求、设计、编码、测试、维护等,不仅仅是设计和编码)
-
极限编程属于增量模型。
答案: 错误 (注:极限编程属于敏捷开发方法,虽然敏捷方法也包含增量特性,但极限编程更侧重于一套特定的实践和原则,不能简单归为增量模型)
填空题
- 螺旋模型是
瀑布模型和快速原型模型的结合。 - 基于组件的开发模型充分体现了
构件重用的思想。 - 统一软件开发过程模型是基于
迭代和增量思想的软件开发模型。 - 喷泉模型是典型的
面向对象模型,具有较好的可移植性。 - 采用RUP,可以从初始开始不断
迭代和精化,可以多次执行各个工作流程。
主观题
-
请对比瀑布模型、快速原型模型、增量模型和螺旋模型。
参考答案:
- 瀑布模型:
- 优点: 阶段清晰,易于理解和管理;适用于需求明确、稳定的项目;文档化程度高,便于团队协作和维护。
- 缺点: 缺乏灵活性,难以适应需求变更;风险发现晚,修改成本高;用户参与度低,可能导致产品不符合用户期望。
- 快速原型模型:
- 优点: 用户参与度高,能及时获取反馈;早期发现并纠正错误;降低开发风险,提高用户满意度。
- 缺点: 可能导致项目范围蔓延;原型可能被误认为是最终产品;管理难度大,需要用户积极配合。
- 增量模型:
- 优点: 早期交付核心功能,用户可提前使用;降低开发风险,每个增量可控;能够适应需求变更。
- 缺点: 需要仔细规划增量划分;每个增量都需经历完整开发过程;可能导致系统架构不稳定。
- 螺旋模型:
- 优点: 强调风险管理,适用于高风险项目;结合了瀑布模型的系统性和原型模型的迭代性;用户参与度高,可及时反馈。
- 缺点: 复杂性高,对项目管理要求严格;风险分析能力要求高;不适用于小型项目或低风险项目。
- 瀑布模型:
-
敏捷过程的核心价值观有哪些?
参考答案:
敏捷过程的核心价值观体现在《敏捷软件开发宣言》中,它提出了四个核心价值观:
- 个体和互动 高于 流程和工具:强调人与人之间的沟通、协作和互动的重要性,认为这比严格遵循预设的流程和工具更能有效地推动项目进展。
- 工作的软件 高于 详尽的文档:优先关注交付能够实际运行并带来价值的软件,而不是花费大量时间编写详尽但可能不及时更新的文档。
- 客户合作 高于 合同谈判:强调与客户持续、紧密的合作,以便及时理解并响应他们的需求变化,而不是僵化地遵循合同中最初约定的内容。
- 响应变化 高于 遵循计划:认识到软件开发中需求变化是常态,并鼓励团队拥抱变化,快速适应,而不是死板地遵循预先制定的计划。
-
什么是软件过程?它与软件工程方法学有何关系?
参考答案:
-
软件过程(Software Process): 指为了开发和维护软件产品而执行的一系列活动、方法、实践和转换的总称。它描述了软件从概念形成到最终交付和维护的整个生命周期中,各个阶段的工作内容、顺序、参与角色、所需的技术和工具,以及如何管理和控制这些活动。简单来说,软件过程就是如何开发软件的路线图和执行框架。
-
与软件工程方法学的关系:
软件工程方法学是关于“如何进行软件开发”的理论、原则、技术和工具的总称。两者是指导与被指导、框架与内容的关系:
- 软件过程是框架,方法学是具体内容: 软件过程定义了“做什么”和“何时做”。方法学提供了在每个阶段“如何做”的具体技术和实践。
- 方法学支撑过程的实施: 一个有效的软件过程需要依赖合适的软件工程方法学来支撑。
- 目标一致,侧重点不同: 两者最终目标都是提高软件质量、降低成本。软件过程侧重于宏观的组织和管理,方法学侧重于微观的技术和实践。
-
-
假设要为一家生产和销售长筒靴的公司开发一款软件…为这个软件选择软件过程模型时应使用什么准则?
参考答案:
为这种复杂供应链管理软件选择软件过程模型时,应考虑以下准则:
- 需求明确性和稳定性: 业务流程复杂,初期需求可能不完全明确,应倾向于迭代或增量模型。
- 风险程度: 系统风险较高,应优先选择包含风险分析机制的模型(如螺旋模型)。
- 用户参与度: 需要用户持续参与,鼓励用户参与的模型(如快速原型、增量、敏捷)更适用。
- 项目规模和复杂性: 系统规模大、复杂度高,需要既有宏观规划又能逐步细化的模型。
- 时间压力和交付周期: 如果需要早期交付部分功能,增量模型或敏捷方法是更合适的选择。
- 团队经验和能力: 选择团队熟悉并能驾驭的模型。
建议模型: 考虑到项目的复杂性、风险和可能的迭代需求,螺旋模型、增量模型(或其组合)以及敏捷方法(如Scrum)都是较好的选择。
-
假设(1)中…软件开发公司决定把它重新开发成一个通用软件包…为本题中的软件选择软件过程模型时,使用的准则与(1)中使用的准则有哪些不同?
参考答案:
将定制软件开发成通用软件包,选择过程模型时,新增或更侧重以下准则:
- 通用性和可配置性/可定制性: 需强调通用设计、模块化开发和参数化配置。
- 可移植性和跨平台兼容性: 需早期并持续关注跨平台设计和兼容性测试。
- 产品化和市场导向: 过程模型需更紧密结合产品管理和市场需求分析。
- 易用性和用户体验 (UX): 用户体验设计(UX Design)*和*用户界面(UI)设计变得尤为关键。
- 维护和技术支持: 过程模型应重视高质量代码、完善文档、自动化测试及版本管理。
- 安全性、健壮性和可伸缩性: 作为通用产品,这些要求更高。
- 法规遵从性(如果适用): 过程模型应包含合规性审查。
总结: 核心关注点从“满足特定业务需求”转向了“满足市场需求、提供高可配置、高可移植、易用且可维护的产品”。
第三章 可行性研究
选择题
-
可行性研究也称为()
A. 技术可行性研究
B. 操作可行性研究
C. 经济可行性研究
D. 项目论证
答案: D
-
()研究往往是系统开发过程中难度最大的工作,也是可行性研究的关键。
A. 技术可行性
B. 操作可行性
C. 经济可行性
D. 风险可行性
答案: A
-
研究软硬件资源的有效性是进行()研究的一方面。
A. 技术可行性
B. 经济可行性
C. 社会可行性
D. 操作可行性
答案: A
-
软件开发计划是软件工程中的一种()性文档。
A. 技术
B. 管理
C. 检索
D. 文献
答案: B
判断题
-
软件开发计划是软件工程中的一种技术性文档。
答案: 错误
-
可行性研究过程也称为项目论证过程。
答案: 正确
-
投资回收期越长,获得利润就越快,项目就越值得开发。
答案: 错误
-
代码行技术是成本估算技术的一种。
答案: 正确
填空题
- 可行性研究的结论有3种:
可行、不可行、需要重新评估。 - 经济可行性研究主要研究开发和运行需要的
成本和得到的效益。 - 计划可行性研究主要是估计项目完成所需要的
时间并评估项目预留的时间是否足够。 - 可行性研究主要包括战略可行性、操作可行性、计划可行性、技术可行性、市场可行性、经济可行性、
法律可行性、社会可行性。 技术可行性研究是系统开发过程中难度最大的工作,也是可行性研究的关键。- 技术可行性研究主要关注待开发的系统的
功能、性能和限制条件。 - 成本效益分析的第一步是估算开发成本、运行费用和新系统带来的
效益。 - 任务分解技术最常用的方法是按
功能划分任务。
第四章 需求分析
选择题
-
在需求分析之前有必要进行()工作。
A. 程序设计
B. 可行性研究
C. E-R分析
D. 行为建模
答案: B
-
需求分析是一个(),它应该贯穿于系统的整个生命周期中,而不是仅仅属于软件生命周期早期的一项工作。
A. 概念
B. 工具
C. 方法
D. 过程
答案: D
-
软件需求规格说明书的内容不应该包括()
A. 对重要功能的描述
B. 对算法的详细过程描述
C. 对数据的要求
D. 软件的性能
答案: B
-
软件需求分析阶段的工作可以分为以下5个方面:对问题的识别、分析、综合、编写需求分析文档以及()。
A. 总结
B. 阶段性报告
C. 需求分析评审
D. 以上答案都不正确
答案: C
-
进行需求分析可使用多种工具,但()是不适用的。
A. 数据流图
B. PAD
C. 状态转换图
D. 数据字典
答案: B
-
结构化分析方法的基本思想是()
A. 自底向上、逐步分解
B. 自顶向下、逐步分解
C. 自底向上、逐步抽象
D. 自顶向下、逐步抽象
答案: B
-
在E-R图中,包含以下基本要素()
A. 数据、对象、实体
B. 控制、关系、对象
C. 实体、关系、控制
D. 实体、属性、关系
答案: D
判断题
-
用于需求分析的软件工具,应该能够保证需求的正确性,即验证需求的一致性、完整性、现实性和有效性。
答案: 正确
-
需求分析是开发方的工作,用户的参与度不大。
答案: 错误
-
需求规格说明书在软件开发中具有重要的作用,它也可以作为软件可行性研究的依据。
答案: 错误
-
需求分析的主要目的是制订软件开发的具体方案。
答案: 错误
-
需求规格说明书描述了系统每个功能的具体实现。
答案: 错误
-
非功能性需求是从各个角度对系统的约束和限制,反映了应用对软件系统质量和特性的额外要求。
答案: 正确
-
需求分析阶段的成果主要是需求规格说明书,但该成果与软件设计、编码、测试以及维护关系不大。
答案: 错误
-
分层的DFD可以用于可行性研究阶段,描述系统的物理结构。
答案: 错误
-
信息建模方法是从数据的角度来建立信息模型的,最常用的描述信息模型的方法是E-R图。
答案: 正确
-
在需求分析阶段主要采用图形工具来描述的原因是图形的信息量大,便于描述规模大的软件系统。
答案: 错误
-
设计数据流图时只需考虑系统必须完成的基本逻辑功能,完全不需考虑怎样具体地实现这些功能。
答案: 正确
填空题
- 需求分析的步骤为
需求获取、分析建模、需求描述和需求评审。 - 需求可以分为两大类:
功能需求和非功能需求。 - 需求管理是一种用于
需求变更、记录、组织和跟踪系统需求变更的系统化方法。 - 功能分解方法将一个系统看成由若干功能
子功能组成。 - 面向对象的分析方法的关键是识别问题域内的
对象。 - 数据流图主要分为
逻辑数据流图和物理数据流图两种表示方法。 - 状态转换图是一种描述系统对内部或外部事件响应的
动态模型。 - 结构化分析方法通常强调
逐层抽象、逐层分解的方法。 - 分析模型应该包括功能模型、
信息模型和行为模型。 1层数据流图是对0层数据流图的细化。
主观题
-
如何理解结构化需求分析方法的基本思想?
参考答案:
结构化需求分析方法的基本思想是“自顶向下、逐步分解、抽象分层”。它将复杂的系统问题分解成更小的、更易于管理的部分,通过图形工具(如数据流图、实体-关系图、状态转换图)来描述系统的功能、数据和行为。这种方法强调对系统逻辑功能的描述,而不是具体的实现细节。它通过层层分解,从宏观到微观,逐步细化系统功能和数据,使复杂问题变得简单易懂,便于分析和理解。
-
请简述数据流图的作用。
参考答案:
数据流图(DFD)是结构化分析方法中描述系统功能的一种图形工具,其作用主要有:
- 描述系统功能: 直观地描绘了系统的数据如何在不同处理之间流动和转换。
- 理解系统边界: 通过外部实体,清晰地界定系统的输入和输出。
- 分解系统: 通过分层DFD将复杂系统逐步分解为更小、更易理解的子系统和功能。
- 沟通工具: 作为开发人员与用户之间沟通的桥梁,帮助双方更好地理解系统需求。
- 为后续设计提供基础: 数据流图是后续系统设计的重要依据。
-
请简述数据字典的作用。
参考答案:
数据字典是数据流图的补充工具,其作用主要有:
- 提供精确定义: 为数据流图中的每一个组成部分提供精确、无歧义的定义。
- 保证一致性: 确保整个系统设计中对数据项的定义保持一致。
- 减少冗余: 避免数据定义上的重复。
- 作为参考依据: 为系统设计、编码和测试提供详细的数据信息。
- 方便管理和维护: 有助于开发人员更好地理解和管理系统的数据。
-
请简述E-R图的作用。
参考答案:
E-R图(实体-关系图)是描述信息模型的一种图形工具,其作用主要有:
- 描述数据结构: 清晰地表示系统中的实体(数据对象)及其属性。
- 表示数据关系: 明确地描绘实体之间存在的各种关系(如一对一、一对多、多对多)。
- 概念建模: 帮助分析人员从概念层面理解和组织系统的数据。
- 为数据库设计提供基础: E-R图是关系数据库设计的重要依据。
- 沟通工具: 便于开发人员与用户沟通和确认数据需求。
-
请简述状态图的作用。
参考答案:
状态图(或状态转换图)是一种行为模型,其作用主要有:
- 描述系统行为: 详细描绘系统或对象在外部事件刺激下的动态行为和响应。
- 展现状态流转: 清晰地展示系统可能处于的所有状态以及状态转换的条件。
- 捕获事件响应: 明确系统对各种输入事件的反应。
- 帮助理解复杂逻辑: 对于具有复杂状态转换的系统,状态图能够提供直观的视图。
- 指导系统设计: 为设计系统中的事件处理机制和控制逻辑提供依据。
-
某图书管理系统有以下功能…用结构化分析方法画出系统0层数据流图。
参考答案:
0层数据流图(上下文图):图书管理系统
代码段
graph TD subgraph 外部实体 读者用户["读者用户"] 管理员["管理员"] end subgraph 系统 图书管理系统("图书管理系统") end 读者用户 -- "借书请求, 还书请求, 查询请求" --> 图书管理系统 图书管理系统 -- "借书结果, 还书结果, 查询结果, 罚款通知" --> 读者用户 管理员 -- "查询请求, 统计报告请求" --> 图书管理系统 图书管理系统 -- "查询结果, 统计报告" --> 管理员
第五章 软件设计
选择题
-
面向数据流的软件设计方法可将( )映射成软件结构。
A. 控制结构
B. 模块
C. 数据流
D. 事务流
答案: C
解析: 面向数据流的设计方法(如结构化设计)核心就是将数据流图(DFD)映射为程序结构图。
-
模块的独立性是由内聚性和耦合性来度量的,其中内聚性表示的是()
A. 模块间的联系程度
B. 信息隐藏程度
C. 模块的功能强度
D. 接口的复杂程度
答案: C
解析: 内聚性是指模块内部各个元素之间联系的紧密程度,表示模块内部功能上的强度。
-
Jackson方法根据()来导出程序结构。
A. 数据流图
B. 数据间的控制结构
C. 数据结构
D. IPO图
答案: C
解析: Jackson方法是一种面向数据结构的设计方法,它强调程序结构与问题的数据结构相对应。
-
为了提高模块的独立性,模块之间最好是()
A. 公共耦合
B. 控制耦合
C. 数据耦合
D. 特征耦合
答案: C
解析: 数据耦合是最低的耦合类型,表示模块之间仅通过参数传递数据,相互依赖性最低,最有利于提高模块独立性。
-
在面向数据流的软件设计方法中,一般将数据流分为()
A. 数据流和控制流
B. 变换流和控制流
C. 事务流和控制流
D. 变换流和事务流
答案: D
解析: 面向数据流设计主要处理两种类型的数据流图:变换流和事务流。
-
总体设计(概要设计)不包括( )
A. 体系结构设计
B. 接口设计
C. 数据设计
D. 数据结构设计
答案: D
解析: 总体设计(概要设计)包括体系结构设计、接口设计和数据设计(应用级数据设计)。数据结构设计(程序级具体数据结构)更偏向详细设计范畴。
-
一个模块把一个数值作为参数传递给另一个模块,这两个模块之间的耦合是()
A. 公共耦合
B. 数据耦合
C. 控制耦合
D. 内容耦合
答案: B
解析: 仅通过参数传递数据是数据耦合的典型特征,这是最理想的耦合类型。
-
划分模块时,一个模块的( )
A. 作用范围应在其作用范围内
B. 控制范围应在其作用范围内
C. 作用范围和控制范围互不包含
D. 作用范围和控制范围不受任何限制
答案: B
解析: 正确的设计原则是“模块的作用域(scope of effect)应该在它的控制域(scope of control)之内”,以避免不必要的副作用和提高可控性。
-
详细设计的任务是定义每个模块的()
A. 外部特征
B. 内部特征
C. 算法和数据格式
D. 功能和输入输出数据
答案: C
解析: 详细设计关注模块内部的具体实现细节,包括算法选择和数据格式的定义。
-
下面不是结构化方法的基本原理的是()
A. 自底向上功能分解
B. 数据抽象
C. 功能抽象
D. 模块化
答案: A
解析: 结构化方法通常采用“自顶向下、逐步求精”的功能分解策略。
判断题
-
判定表的优点是容易转换为计算机实现,缺点是不能描述组合条件。
答案: 错误
解析: 判定表的核心优势恰恰是能清晰地描述各种组合条件及其对应的动作。
-
面向数据结构的设计方法一般都包括下列任务:确定数据结构特征;用顺序型、选择型和循环型3种基本形式表示数据。
答案: 正确
解析: 面向数据结构设计方法(如Jackson方法)强调根据输入输出的数据结构,使用顺序、选择、循环三种基本结构来构建程序。
-
模块独立性要求高耦合、低内聚。
答案: 错误
解析: 模块独立性要求的是高内聚、低耦合。
-
软件设计说明书是软件概要设计的主要成果。
答案: 正确
解析: 软件概要设计(总体设计)的主要输出文档就是软件设计说明书。
-
软件设计中设计详审和设计本身一样重要,其主要作用是避免后期付出高昂的代价。
答案: 正确
解析: 设计评审是发现设计缺陷的关键环节,越早发现问题,修复成本越低。
-
划分模块可以降低软件的复杂度和工作量,所以应该将模块分得越小越好。
答案: 错误
解析: 模块划分并非越小越好。模块过小会导致模块数量过多,管理复杂,增加接口和调用开销。应追求适当粒度。
-
结构化设计方法是一种面向数据结构的设计方法,强调程序结构与问题结构相对应。
答案: 错误
解析: 结构化设计方法是一种面向数据流的设计方法。Jackson方法才是面向数据结构的设计方法。
-
所有的数据流图都可以看作变换型数据流图。
答案: 错误
解析: 数据流图分为变换型和事务型。
-
数据耦合是高耦合。
答案: 错误
解析: 数据耦合是最低的耦合类型,属于“低耦合”范畴。
-
文件一般用于长期存储,数据库一般用于临时存储。
答案: 错误
解析: 文件和数据库都可以用于长期存储。数据库通常用于结构化、需要复杂查询和事务管理的数据的长期存储。
填空题
- 模块化的基本原则是高内聚、
低耦合。 - 模块结构图之中如果两个模块之间有直线连接,表示它们之间存在
调用关系。 - 变换型DFD由
输入部分、变换中心、输出部分组成。 - 程序流程图的控制结构分为
顺序结构、选择结构、循环结构3种基本结构。 - 伪代码的优点是不仅可以作为
详细设计工具,还可以作为程序注释工具。 - 流程图是对过程、算法、
工作流的一种图形表示。 - 数据设计包括程序级的
数据结构设计、应用级的数据库设计两个方面。
主观题
-
请简述软件设计与需求分析的关系。
参考答案:
- 关系: 需求分析是设计的输入和依据,设计是需求的具体实现方案。
- 需求分析 (做什么): 关注于理解用户问题,定义系统的功能和约束,其成果是软件需求规格说明书。
- 软件设计 (怎么做): 关注于如何构建解决方案,根据需求规格说明书,设计出系统的架构、模块、接口和数据结构。
- 总结: 需求决定设计,设计验证需求。两者相辅相成,共同确保软件的正确性。
-
请简述软件设计的目标和任务。
参考答案:
- 目标:
- 将需求转化为可实现的软件蓝图。
- 确保软件满足用户需求并具有良好的质量属性(可维护性、可靠性等)。
- 为后续编码和测试提供清晰的指导。
- 任务:
- 体系结构设计: 确定软件的整体结构,划分模块。
- 接口设计: 定义模块之间、系统与外部的接口。
- 数据设计: 设计软件使用的数据结构,如数据库。
- 过程设计(详细设计): 为每个模块定义具体的算法和实现细节。
- 目标:
-
请简述在软件设计的过程中需要遵循的原则。
参考答案:
- 模块化: 将系统分解为独立的功能模块。
- 抽象: 隐藏不必要的实现细节,关注核心概念。
- 信息隐藏: 模块的实现细节对外部不可见,只能通过接口访问。
- 高内聚、低耦合: 模块内部功能紧密相关,模块之间依赖关系尽可能弱。
- 可重用性: 设计的模块和组件应尽可能通用。
- 可维护性: 设计应考虑未来的修改和扩展。
- 一致性: 整个设计过程中保持风格、命名等的一致性。
-
软件设计如何分类,分别有哪些活动?
参考答案:
软件设计通常分为两类:
- 总体设计 (概要设计 / Architectural Design)
- 活动: 体系结构设计、接口设计、数据设计(系统级)、非功能性需求设计。
- 详细设计 (Detailed Design)
- 活动: 模块内部过程设计(算法)、局部数据结构设计、数据流设计、错误处理设计。
- 总体设计 (概要设计 / Architectural Design)
-
什么是模块、模块化?软件设计为什么要模块化?
参考答案:
- 模块 (Module): 软件系统中具有独立功能、可独立编译和测试的程序单元。
- 模块化 (Modularization): 将复杂软件系统分解成许多个较小、相对独立的模块的过程。
- 为什么要模块化:
- 降低复杂度: 将大问题分解为小问题。
- 提高可管理性: 便于分工合作。
- 提高可维护性: 修改只影响特定模块。
- 增强可重用性: 独立模块易于复用。
- 便于测试: 可对模块进行单元测试。
- 促进并行开发: 不同团队可并行开发不同模块。
-
为什么说“高内聚、低耦合”的设计有利于提高系统的独立性?
参考答案:
- 高内聚 (High Cohesion): 确保模块内部职责单一、功能集中。这使得模块成为一个相对“自包含”的单元,内部变化不易渗透到外部。
- 低耦合 (Low Coupling): 确保模块之间的依赖关系很弱。一个模块的修改不会轻易引发其他模块的连锁反应。
- 如何提高独立性:
- 减少连锁反应: 两者结合,使得系统中一个模块的变化对其他模块的影响降到最低,避免“牵一发而动全身”。
- 提高可重用性: 功能单一且不依赖外部环境的模块,更容易被复用。
- 简化测试和维护: 独立的模块可以单独进行测试和维护,降低了理解和修改的难度。
-
请将图5-45(“查询图书”的事务中心)映射成系统结构图。
参考答案:
基于对“查询图书”事务中心的分析,可以映射出如下的系统结构图。该结构图以一个主控模块为核心,分发任务给不同的功能子模块。
- 结构描述:
- 主控制模块 作为系统入口,调用下层的功能模块。
- 登录/注册管理模块 负责用户认证,与 用户信息数据层 交互。
- 查询图书调度器 (即事务中心) 接收用户选择,调用相应的查询子模块。
- 按书名查询、按ISBN查询、按类别查询 是三个并列的查询执行模块,它们与 图书信息数据层 交互以获取数据。
- 所有查询模块都将结果传递给 显示图书信息模块 进行统一处理和格式化。
- 最终由 图书信息页面生成模块 呈现给用户。
- 系统结构图 (PlantUML):
代码段
@startuml skinparam componentStyle uml2 skinparam linetype ortho package "图书馆查询系统" { component "主控制模块" as Main component "查询图书调度器\n(事务中心)" as Dispatcher component "按书名查询" as ByName component "按ISBN查询" as ByISBN component "按类别查询" as ByCategory component "显示图书信息模块" as Display database "图书信息数据层" as BookDB Main --> Dispatcher Dispatcher --> ByName Dispatcher --> ByISBN Dispatcher --> ByCategory ByName --> BookDB : 查询 ByISBN --> BookDB : 查询 ByCategory --> BookDB : 查询 ByName --> Display : 传递结果 ByISBN --> Display : 传递结果 ByCategory --> Display : 传递结果 } @enduml - 结构描述:
《第六章》
一、单选题
-
面向对象技术中,对象是类的实例。类有3种成分: (A)、属性和方法(或操作)。
A 标识
B 继承
C 封装
D 消息
-
汽车有一个发动机,那么汽车与发动机之间的关系是(B)关系
A 组装
B 整体-部分
C 分类
D 一般-具体
-
(D)是把对象的属性与操作结合在一起,构成一个独立的对象,其内部信息对外界是隐藏的,外界只能通过有限的接口与对象发生联系。
A 多态
B 继承
C 消息
D 封装
-
关联是建立(B)之间关系的一种手段
A 操作
B 类
C 功能
D 属性
-
面向对象软件技术的许多强有力的功能和突出的优点都来源于把类组织成一个层次结构的系统。一个类的上层可以有父类,下层可以有子类。这种层次结构系统的一个重要性质是(B),一个子类可以获得其父类的全部描述(数据和操作)。
A 兼容性
B 继承性
C 多态性
D 复用性
-
所有的对象都可以成为各种对象类,每个对象类都定义了一组(D)。
A 说明
B 类型
C 过程
D 方法
-
UML是软件开发中的一个重要工具,它主要应用于(D)
A 基于螺旋模型的结构化方法
B 基于需求动态定义的原型化方法
C 基于数据的数据流开发方法
D 基于对象的面向对象的方法
-
(C)是从用户使用系统的角度来描述系统功能的图形表达方法。
A 类图
B 活动图
C 用例图
D 状态图
-
(C)描述了一组交互对象间的动态协作关系,它表示完成某项行为的对象和这些对象之间传递消息的时间顺序。
A 类图
B 活动图
C 顺序图
D 状态图
二、判断题
-
UML是一种建模语言,是一种标准的表示,是一种方法。
错误 (UML是一种建模语言,也是一种标准的表示,但它本身不是一种方法,而是支持多种方法论的工具。)
-
类图用来表示系统中类与类之间的关系,它是对系统动态结构的描述。
错误 (类图是对系统静态结构的描述,而不是动态结构的描述。)
-
在面向对象的软件开发方法中,每个类都存在其相应的对象,类是对象的实例,对象是生成类的模板。
错误 (对象是类的实例,而类是对象的模板。)
-
顺序图用于描述对象是如何交互的且将重点放在消息序列上。
正确
-
继承性是父类与子类之间共享数据结构和消息的机制,这是类之间的一种关系。
正确
-
多态性增强了软件的灵活性和复用性,允许用更为明确、易懂的方式去建立通用软件,多态性和继承性相结合使软件具有更广泛的复用性和可扩充性。
正确
-
类封装比对象封装更具体、更细致。
错误 (对象是类的实例,封装是针对对象而言的。类定义了封装的蓝图,但具体的封装是在对象层面实现的。)
-
用例之间有扩展、使用、组合等几种关系。
错误 (用例之间通常有包含 (include) 和 扩展 (extend) 两种主要关系,没有“使用”或“组合”关系。)
-
活动图显示动作及其结果,着重描述操作实现中所完成的工作,以及用例实例或类中的活动。
正确
-
UML支持面向对象的主要概念,并与具体的开发过程相关活动。
正确
-
部署图用于描述系统硬件的物理拓扑结构以及在此结构上执行的软件。
正确
三、填空题
- 对象是客观实体的抽象表示,由属性和方法两部分组成。
- 类是对具有相同属性和行为的一组对象的抽象描述。因此,它可作为一种用户自定义类型和创建对象的样板,而按照这种样板所创建的一个个具体对象就是类的实例。
- UML的静态建模机制包括用例图、类图、对象图、包图。
- 在UML中,泳道把活动图中的活动划分为若干组,并将划分的组指定给对象,这些对象必须履行该组所包括的活动。
- 顺序图是用来反映若干个对象之间动态协作关系的一种交互图。它主要反映对象之间已发送消息的先后次序和对象之间的交互过程。
- 用例图是从用户使用系统的角度来描述系统功能的图形表达方法。
- 部署图就是用于表示构成分布式系统的节点集和节点之间的联系的图示,它可以表示系统中软件和硬件的物理架构。
- 类图是面向对象设计的核心,是建立状态图、协作图和其他图的基础。
四、主观题
- 请简述面向对象的基本概念。
面向对象是一种软件开发方法,它将真实世界中的实体抽象成对象,通过对象之间的协作来构建软件系统。它主要围绕以下几个核心概念展开:
- 对象 (Object):面向对象编程的基础,是现实世界中某个实体的抽象。它包含了属性(数据或状态)和行为(方法或操作)。
- 类 (Class):对象的蓝图或模板。它定义了具有相同属性和行为的对象的通用结构。对象是类的实例。
- 封装 (Encapsulation):将对象的属性和操作这些数据的方法捆绑在一起,形成一个独立的单元。它隐藏了对象的内部实现细节,只对外提供有限的接口进行交互。
- 继承 (Inheritance):允许一个类(子类)基于另一个类(父类)的定义来创建。子类可以自动获得父类的属性和方法,并可以添加新的功能或修改现有功能。这实现了代码的重用。
- 多态 (Polymorphism):意味着允许不同类的对象对同一个消息(方法调用)做出不同的响应。它可以表现为方法重载和方法重写。多态性提高了代码的灵活性和可扩展性。
- 与面向结构化开发过程相比,为什么面向对象能更真实地反映客观世界?
面向对象方法之所以能更真实地反映客观世界,主要原因在于其核心理念和特性与我们对现实世界的认知方式更为契合:
-
直接映射现实实体: 面向对象以独立的“对象”作为基本单元,每个对象都包含自身的属性和行为,这与我们以“事物”为中心认识世界的方式一致。结构化方法则将系统分解为分离的过程和数据。
-
封装性模拟事物的内在一致性: 面向对象的封装将对象的属性和方法绑定,隐藏内部实现,只对外提供接口,这模拟了现实事物自包含、外部交互受限的特点。
-
继承性体现事物的分类与层次: 继承机制直接反映了现实世界中事物“is-a”的分类和层次结构(如“狗”是一种“动物”),提高了代码复用性并使模型更贴近现实。
-
多态性体现事物的多样行为: 多态允许不同对象对相同指令做出不同响应(如不同动物叫声不同),模拟了现实世界中行为的多样性,使系统更灵活可扩展。
-
什么是面向对象方法?面向对象方法的特点有哪些?
面向对象方法 (Object-Oriented Approach) 是一种软件开发范式,它将软件系统视为由相互协作的独立对象组成的集合。这些对象是对现实世界中实体或概念的抽象,每个对象都封装了其自身的数据(属性)和处理这些数据的方法(行为)。
面向对象方法主要有以下几个核心特点:
-
抽象 (Abstraction):忽略事物不重要的细节,只关注其关键特征和行为,通过类对现实实体进行抽象。
-
封装 (Encapsulation):将对象的属性和操作这些数据的方法捆绑在一起,形成一个独立的单元,并对外隐藏内部实现细节。提高了代码的安全性、模块化和可维护性。
-
继承 (Inheritance):允许新的类(子类)从现有类(父类)中复用其属性和方法。促进了软件的可扩展性和重用性。
-
多态 (Polymorphism):允许不同类的对象对同一个消息做出不同的响应。使得代码更加灵活和通用。
-
什么是类?类与传统的数据类型有什么关系?
类 (Class) 是一个核心概念,它是对象的蓝图或模板。它定义了具有相同属性(数据或特征)和行为(方法或操作)的多个对象的通用结构。类是抽象的定义,而对象是类的具体实例。
类与传统数据类型的关系:
-
扩展和复杂性: 传统数据类型(如
int,string)是预定义或内置的简单数据存储,而类是一种用户自定义的复杂数据类型,能组合多种数据并包含操作这些数据的方法。 -
封装数据和行为: 传统数据类型只关注数据,不含行为。类则将数据(属性)和操作这些数据的方法(行为)封装在一起,使对象既能存储数据,也知道如何处理。
-
抽象和建模能力: 传统数据类型用于基本数据存储,而类提供更强大的抽象能力,能将现实世界复杂概念映射到软件系统,构建更直观的模型。
-
创建实例: 声明传统变量直接分配内存,而定义类只是创建模板,只有实例化**对象时才分配内存。
-
与传统的软件工程方法相比,面向对象的软件工程方法有哪些优点?
与传统的结构化软件工程方法相比,面向对象软件工程方法展现出显著优势:
-
更强的可维护性 (Maintainability): 通过封装,修改对象内部实现不影响其他部分,简化了维护。
-
更高的可复用性 (Reusability): 继承机制实现代码复用,独立的对象模块也易于在不同项目中重用。
-
更好的可扩展性 (Extensibility): 继承和多态使得无需修改现有代码即可添加新功能,符合“开闭原则”。
-
更强的灵活性 (Flexibility): 多态允许统一接口处理不同类型对象,使代码更通用、灵活。
-
更真实的现实世界建模 (Realistic Modeling): 将现实实体抽象为软件对象,模型更直观自然,减少信息偏差。
-
更好的项目管理和团队协作: 系统分解为独立对象,利于并行开发、减少依赖,促进团队沟通。
-
UML的作用和优点有哪些?
UML (Unified Modeling Language) 是一种用于软件系统可视化、构造和文档化的图形化语言。
UML 的作用:
- 可视化 (Visualizing): 以图形方式直观呈现复杂的软件概念、结构和行为。
- 规约 (Specifying): 以精确、无歧义的方式定义系统的结构和行为,作为正式规约。
- 构造 (Constructing): 模型可映射到代码,CASE工具可自动生成部分代码框架。
- 文档化 (Documenting): 作为软件项目的重要文档,记录系统架构、设计决策等。
UML 的优点:
-
促进沟通与理解: 提供通用标准化图形语言,减少误解,提高团队协作。
-
降低复杂性: 将系统分解为小模型视图,帮助逐步理解复杂性。
-
提高设计质量: 绘制过程促使深入思考,发现并改进设计缺陷。
-
支持面向对象开发: 专为面向对象设计,能很好地表达其核心概念。
-
提高开发效率: 自动化代码生成和清晰设计减少返工。
-
便于系统维护和演进: 详尽文档为后期维护和扩展提供指导。
-
如何着手从自然语言描述的用户需求中画出用例图?
从自然语言用户需求中绘制用例图的步骤:
-
识别执行者 (Actors):找出与系统有交互的外部实体(人、其他系统、硬件),通常是名词短语或角色名称。
-
识别用例 (Use Cases):找出执行者希望系统完成的功能或任务,通常是动词短语,且每个用例应产生可观察到的结果。
-
描绘用例与执行者之间的关系:用直线连接执行者和他们参与的用例,表示启动或参与关系。
-
识别用例之间的关系 (可选)
:
- 包含 (Include):多个用例共享共同功能,强制性。
- 扩展 (Extend):用例在特定条件下有额外可选功能。
- 泛化 (Generalization):用例有通用行为和特定行为,抽象出父用例。
-
绘制用例图并精化:使用UML工具或手绘,用矩形框(系统边界)包围用例,执行者在外部。确保命名清晰,并与用户验证。
-
类之间的外部关系有几种类型?每种关系表达什么语义?
在面向对象建模中,类与类之间存在多种外部关系,它们描述了类实例之间如何相互关联、协作或依赖:
-
关联 (Association):
- 语义: 类之间最常见、最通用的结构化或语义连接,描述对象间通信和交互。
- 示例: “顾客”与“订单”
-
聚合 (Aggregation):
- 语义: “弱”的整体-部分 (whole-part) 关系,部分可独立于整体存在。表达“has-a”或“contains-a”语义。
- 示例: “部门”与“员工”
-
组合 (Composition):
- 语义: “强”的整体-部分 (whole-part) 关系,部分的生命周期依赖于整体。整体销毁时部分也销毁。
- 示例: “汽车”与“发动机”
-
泛化 (Generalization):
- 语义: 继承 (Inheritance) 关系,子类继承父类属性和操作,表示“is-a”关系。
- 示例: “轿车”是“汽车”的泛化
-
实现 (Realization):
- 语义: 一个类实现了 (implements) 一个或多个接口 (Interface) 定义的契约。
- 示例: “数据访问类”实现“IDataSource”接口
-
依赖 (Dependency):
- 语义: 最弱关系,一个类的改变可能影响另一个类,通常是短暂或临时的使用。
- 示例: “客户”类的方法中使用了“支付网关”类作为参数。
-
某图书借阅管理系统需求说明如下
(1)管理员应建立图书书目,以提供图书检索的便利。一条书目可有多本相同ISBN的图书,每一本图书只能对应于一个书目。
(2)图书可被读者借阅。读者在办理图书借阅时,管理员应记录借书日期,并记录约定还书日以督促读者按时归还。一个读者可借阅多本图书,一本图书每次只能被一个读者借阅。
(3)图书将由管理员办理入出库。图书入出库时,应记录图书变更状态,如存库、外借,并记变更日期。一个管理员可办理多本图书入出库,但一本图书的某次入出库办理,必须由确定的管理员经手。
试以上述说明为依据,画出该系统的用例图、类图。
37.1 用例图 (Use Case Diagram)
代码段
@startuml
left to right direction
actor 读者 as Reader
actor 管理员 as Administrator
rectangle "图书借阅管理系统" {
usecase "借阅图书" as BorrowBook
usecase "归还图书" as ReturnBook
usecase "查询图书" as SearchBook
usecase "建立图书书目" as CreateBookCatalog
usecase "办理图书入库" as BookIn
usecase "办理图书出库" as BookOut
usecase "记录图书变更状态" as RecordBookStatusChange
Administrator -- CreateBookCatalog
Administrator -- BookIn
Administrator -- BookOut
Administrator -- RecordBookStatusChange
Reader -- BorrowBook
Reader -- ReturnBook
Reader -- SearchBook
BorrowBook .> RecordBookStatusChange : <<include>>
BookIn .> RecordBookStatusChange : <<include>>
BookOut .> RecordBookStatusChange : <<include>>
}
@enduml
用例图说明:
- 执行者:
读者,管理员 - 用例:
借阅图书,归还图书,查询图书,建立图书书目,办理图书入库,办理图书出库,记录图书变更状态。 - 关系: 读者与借阅/归还/查询关联;管理员与建立书目/入出库/记录状态关联;借阅/入库/出库都包含记录图书变更状态。
37.2 类图 (Class Diagram)
代码段
@startuml
hide methods
hide members
class BookCatalog {
+ ISBN: String
+ Title: String
+ Author: String
+ Publisher: String
+ PublicationDate: Date
}
class Book {
+ BookID: String
+ ISBN: String
+ Status: String {存库, 外借, 遗失, 损坏}
+ LastChangeDate: Date
}
class Reader {
+ ReaderID: String
+ Name: String
+ ContactInfo: String
}
class Administrator {
+ AdminID: String
+ Name: String
}
class BorrowRecord {
+ RecordID: String
+ BorrowDate: Date
+ DueDate: Date
+ ReturnDate: Date
}
BookCatalog "1" -- "*" Book : 包含 >
' 一条书目可有多本相同ISBN的图书, 每一本图书只能对应于一个书目
Book "1" -- "0..1" BorrowRecord : - 每次只能被一个读者借阅 (当前借阅)
' 一本图书每次只能被一个读者借阅, 对应于一个借阅记录
Reader "1" -- "*" BorrowRecord : 借阅 >
' 一个读者可借阅多本图书
Administrator "1" -- "*" Book : 办理入出库 >
' 一个管理员可办理多本图书入出库
Book "1" -- "1" Administrator : 某次入出库办理必须由确定的管理员经手
@enduml
类图说明:
- 类:
BookCatalog(图书书目),Book(图书),Reader(读者),Administrator(管理员),BorrowRecord(借阅记录)。 - 关系:
BookCatalog(1) 包含Book(*)。Book(1) 在当前借阅中与BorrowRecord(0..1) 关联。Reader(1) 借阅BorrowRecord(*)。Administrator(1) 办理入出库Book(*)。- 某次
Book(1) 的入出库办理必须由确定的Administrator(1) 经手。
《第七章》
一、单选题
-
面向对象模型主要由以下哪些模型组成? ( A )
A 对象模型、动态模型、功能模型
B 对象模型、数据模型、功能模型
C 数据模型、动态模型、功能模型
D 对象模型、动态模型、数据模型
-
面向对象分析的首要工作是建立( D )
A 系统的动态模型
B 系统的功能模型
C 基本的E-R图
D 问题的对象模型
-
面向对象分析阶段建立的3个模型中,核心的模型是( C )模型。
A 功能
B 动态
C 对象
D 分析
-
面向对象的动态模型中,每张状态图表示( A )的动态行为。
A 某一个类
B 有关联的若干个类
C 一系列事件
D 一系列状态
-
在考察系统的一些涉及时序和改变的状况时,要用动态模型来表示。动态模型着重于系统的控制逻辑,它包括两个图:一个是事件追踪图;另一个是( B )。
A 顺序图
B 状态图
C 系统结构图
D 数据流图
-
对象模型的描述工具是( D )。
A 状态图
B 数据流图
C 结构图
D 类图
-
功能模型中所有的( D )往往形成一个层次结构,在这个层次结构中一个数据流图的过程可以由下一层数据流图进行进一步的说明。
A 事件追踪图
B 物理模型图
C 状态转换图
D 数据流图
-
在面向对象软件开发方法中,类与类之间主要有( A )结构关系。
A 继承和聚合
B 继承和方法调用
C 一般和特殊
D 聚合和消息传递
-
下面正确的说法是( C )
A 对象表示客观中存在的实物
B 类是对象的实例
C 类是具有相同属性和操作的对象的集合
D 对象也就是类
二、判断题
-
模型是对现实的简化,建模是为了更好地理解所开发的系统。
正确
-
在面向对象的需求分析方法中,建立动态模型是最主要的任务。
错误 (核心任务是建立对象模型。)
-
面向对象分析阶段建立的3个模型中,核心的模型是功能模型。
错误 (核心模型是对象模型。)
-
对象模型的描述工具是状态图。
错误 (对象模型的描述工具是类图。)
-
两个对象之间的关联关系只能有一个。
错误 (两个对象之间可以存在多个关联关系,例如一个人和一本书之间可以有“借阅”关系,也可以有“推荐”关系。)
三、填空题
-
面向对象分析的首要工作是建立问题的对象模型。
-
大型系统的对象模型通常由5个层次构成,分别是主题层、类与对象层、结构层、属性层、服务层。
-
对象模型由问题域的对象和类组成。
-
对象和类之间的关系有依赖,泛化,实现,关联,聚合和组合。
-
对象模型的描述工具是类图。
四、主观题
20. 请对比面向对象需求分析方法和结构化需求分析方法。
面向对象需求分析方法和结构化需求分析方法是两种截然不同的软件需求分析范式,它们在思维方式、关注点和建模工具上存在显著差异:
-
思维方式与关注点:
- 结构化需求分析: 采用自顶向下、逐步分解的策略。它将系统视为一系列功能的组合,核心关注点是**“做什么”**,即数据的流动和处理过程。它强调将问题分解为功能模块和数据流,数据和处理是分离的。
- 面向对象需求分析: 采用以对象为中心的思维方式。它将系统视为由相互协作的对象(封装了数据和行为的实体)组成的集合,核心关注点是**“有什么”(对象)和“能做什么”**(对象的行为)。它强调数据和操作的紧密结合,更贴近现实世界中事物的本质。
-
建模工具:
- 结构化需求分析: 主要使用**数据流图(DFD)**描述数据在系统中的流动和处理;**实体关系图(E-R图)**描述数据的静态结构及其关系;状态转换图描述实体的状态变化。
- 面向对象需求分析: 主要使用统一建模语言(UML)中的各种图表,如用例图(描述系统功能和用户交互)、类图(描述系统静态结构中的类、属性、方法及关系)、顺序图/协作图(描述对象间的动态交互)、状态图(描述单个对象的生命周期状态变化)等。
-
对变化和复用的支持:
- 结构化需求分析: 在需求变更时,由于功能和数据是分离的,一个小的变化可能导致多处修改,系统的可维护性和可扩展性较差。复用主要停留在代码级别(如函数库)。
- 面向对象需求分析: 由于封装、继承和多态等特性,系统对变化具有更强的适应性。需求的变更往往只需修改相关对象或添加新对象,对现有代码影响较小,可维护性和可扩展性更强。类和对象级别的复用是其核心优势,提高了开发效率。
-
与设计和实现的关系:
- 结构化需求分析: 分析模型(DFD、E-R)到设计模型(结构图、模块图)和实现(过程式编程语言)之间存在较大的鸿沟,转换可能不自然。
- 面向对象需求分析: 分析阶段建立的对象模型可以平滑地过渡到面向对象的设计和实现阶段,模型之间具有高度的一致性,降低了开发过程中的转换成本和错误率。
总而言之,面向对象需求分析方法以其更贴近现实世界的建模方式、对变化的良好适应性和对代码复用的支持,在处理复杂软件系统方面显示出比结构化方法更强的优势。
21. 类之间的外部关系有几种类型?每种关系表达什么语义?
在面向对象建模中,类与类之间存在多种外部关系,它们描述了类实例之间如何相互关联、协作或依赖。主要的关系类型及其语义如下:
-
关联 (Association)
- 语义: 类之间最常见、最通用的一种结构化连接或语义连接。它描述了对象之间可以进行通信和交互。关联可以是双向的或单向的。
- UML表示: 一条连接两个类的直线。
-
聚合 (Aggregation)
- 语义: 关联的一种特殊形式,表示一种“弱”的整体-部分 (whole-part) 关系。部分可以独立于整体存在,整体的生命周期不依赖于部分的生命周期。它表达的是“has-a”(拥有)或“contains-a”(包含)的语义。
- UML表示: 连接整体端的空心菱形。
-
组合 (Composition)
- 语义: 关联的一种特殊形式,表示一种“强”的整体-部分 (whole-part) 关系。部分的生命周期与整体的生命周期紧密耦合,即部分不能独立于整体存在。当整体被销毁时,部分也会随之销毁。
- UML表示: 连接整体端的实心菱形。
-
泛化 (Generalization)
- 语义: 表示类之间的一种继承 (Inheritance) 关系,通常被称为“is-a”(是)的关系。一个子类继承了父类的属性和操作,并可以添加自己的特有功能或覆盖父类的行为。它建立了类之间的层次结构。
- UML表示: 指向父类的空心三角箭头。
-
实现 (Realization)
- 语义: 表示一个类实现了 (implements) 一个或多个接口 (Interface) 定义的契约(操作)。接口定义了一组操作的签名,但不提供实现,而实现类则负责提供这些操作的具体实现。
- UML表示: 空心三角箭头加虚线指向接口。
-
依赖 (Dependency)
- 语义: 类之间最弱的一种关系,表示一个类依赖于另一个类。当一个类的改变可能会影响到另一个类时,就存在依赖关系。这种影响通常是短暂的或临时的,比如一个类的方法中使用了另一个类作为参数、局部变量或返回类型。
- UML表示: 虚线箭头指向被依赖的类。
22. 请简述面向对象分析的原则。
面向对象分析(OOA)阶段的核心目标是建立一个反映问题域的对象模型。在进行OOA时,需要遵循以下基本原则:
-
抽象原则 (Abstraction Principle):
- 含义: 关注问题域中事物的本质特征和行为,而忽略不相关的细节。通过抽象,可以创建出简洁、易于理解的模型,捕捉系统的核心概念。
- 应用: 识别关键实体(对象),定义它们的属性和行为,形成类。
-
封装原则 (Encapsulation Principle):
- 含义: 将对象的属性(数据)和操作(行为)紧密绑定在一起,形成一个独立的单元。同时,隐藏对象的内部实现细节,只对外提供有限的接口进行通信。
- 应用: 确保每个类都有清晰定义的责任,外部只能通过公共方法访问对象状态,保护数据的完整性。
-
继承原则 (Inheritance Principle):
- 含义: 允许新的类(子类)从现有类(父类)中继承属性和行为,并在其基础上进行扩展或修改。这反映了现实世界中的分类和泛化-特化关系。
- 应用: 识别类之间的“is-a”关系,建立类层次结构,促进代码重用和模型的可扩展性。
-
多态原则 (Polymorphism Principle):
- 含义: 允许不同类的对象对同一个消息(方法调用)做出不同的响应。这使得系统能够以统一的方式处理不同类型的对象。
- 应用: 设计通用接口,实现特定行为,提高系统的灵活性和通用性。
-
模块化原则 (Modularity Principle):
- 含义: 将复杂的系统分解为一系列独立、高内聚、低耦合的模块(对象或类),每个模块承担明确的职责。
- 应用: 有助于并行开发、降低复杂性、提高可维护性。
-
信息隐藏原则 (Information Hiding Principle):
- 含义: 这是封装原则的延伸,强调模块的实现细节应该对其他模块隐藏。模块只通过其接口暴露必要的信息。
- 应用: 限制了模块间的相互依赖,降低了修改对其他部分的影响。
遵循这些原则有助于建立一个健壮、灵活、易于理解和维护的面向对象分析模型。
23. 请简述面向对象分析的过程。
面向对象分析(Object-Oriented Analysis, OOA)是软件开发生命周期中的一个关键阶段,旨在深入理解问题域,并建立一个独立于具体实现技术的问题域模型。其过程通常是迭代和增量的,可以概括为以下几个主要步骤:
-
识别对象和类 (Identify Objects and Classes):
- 任务: 这是OOA的首要和核心任务。通过分析用户需求说明、领域专家访谈等,找出问题域中所有相关的名词、概念和实体,将它们抽象为潜在的对象和类。
- 方法: 关注系统要处理的“事物”以及“事物”的类别。
-
识别属性 (Identify Attributes):
- 任务: 为每个识别出的类定义其关键的属性(数据),即描述对象特征的数据项。
- 方法: 思考每个对象有哪些静态的、不变的特征。
-
识别服务/行为/操作 (Identify Services/Behaviors/Operations):
- 任务: 为每个识别出的类定义其能够执行的服务或操作(方法),即对象能够完成的功能。
- 方法: 思考每个对象能“做”什么,以及其他对象能对它“做”什么。
-
识别关系 (Identify Relationships):
- 任务: 建立类与类之间的各种关系,以反映现实世界中实体之间的连接。这包括关联(Association)、泛化(Generalization/Inheritance)、聚合(Aggregation)、组合(Composition)和依赖(Dependency)等。
- 方法: 分析类之间是“is-a”关系(泛化)、“has-a”关系(聚合/组合)还是一般的协作关系(关联),或者仅仅是临时的使用关系(依赖)。
-
构建对象模型(类图) (Build the Object Model/Class Diagram):
- 任务: 使用UML类图来可视化地表示识别出的类、它们的属性、操作以及类之间的各种关系。
- 方法: 绘制清晰的类图,并根据上述步骤进行迭代和完善。
-
构建动态模型 (Build the Dynamic Model):
- 任务: 描述系统随时间变化的行为和对象之间的交互顺序。主要使用UML状态图(描述单个对象的生命周期状态变化)和顺序图/协作图(描述对象间的消息传递和协作)。
- 方法: 分析事件、状态转换、对象间的消息流。
-
构建功能模型 (Build the Functional Model):
- 任务: 描述系统的功能以及数据在系统中的转换过程。通常使用UML用例图(从用户角度描述系统功能)和活动图(描述业务流程或操作的步骤)。
- 方法: 捕获用户的需求和业务流程。
-
迭代与精化 (Iteration and Refinement):
- 任务: OOA不是一个线性的过程。上述步骤往往是迭代进行的,随着对问题域理解的加深,需要不断地精化、修改和完善已建立的模型。
通过以上过程,OOA旨在创建一套完整、一致、无歧义且独立于实现细节的问题域模型,为后续的面向对象设计(OOD)阶段奠定坚实的基础。
24. 什么是动态模型?对象模型?功能模型?
在面向对象分析(OOA)中,通常会构建三个核心模型来从不同视角理解和描述系统:对象模型、动态模型和功能模型。
24.1 对象模型 (Object Model)
- 定义: 对象模型是面向对象分析的核心模型。它描述了系统的静态结构,即问题域中存在的对象、它们的分类(类)、这些对象的属性以及类与类之间的各种关系(如关联、继承、聚合、组合、依赖等)。
- 关注点: “什么”是系统中的重要实体,“它们有什么”特征,“它们之间有什么关系”。
- 主要描述工具: UML类图。
- 作用: 提供了系统最稳定的结构骨架,是其他两个模型的基础。它捕捉了系统的核心概念和它们之间的结构性连接。
24.2 动态模型 (Dynamic Model)
- 定义: 动态模型描述了系统的行为,特别是系统如何响应事件、对象状态如何随时间变化以及对象之间如何进行协作。它着重于系统的控制逻辑和时序关系。
- 关注点: “何时”以及“如何”发生事情,“对象如何交互”来完成某个任务,以及“对象的状态如何改变”。
- 主要描述工具: UML状态图(描述单个对象的生命周期和状态转换)和UML顺序图/协作图(描述多个对象之间消息传递的时间顺序或结构协作)。
- 作用: 展现了系统对外部事件的响应方式,揭示了系统内部对象的行为流程和相互作用。
24.3 功能模型 (Functional Model)
- 定义: 功能模型描述了系统的功能,即系统**“做什么”**以及数据如何在系统中进行转换。它侧重于系统的外部行为,从用户的角度看系统提供了哪些服务。
- 关注点: “谁”使用系统,“系统提供哪些功能”,“数据如何输入和输出”,以及“数据如何被处理”。
- 主要描述工具: UML用例图(从执行者角度描述系统提供的所有功能)和UML活动图(描述业务流程或复杂操作的步骤序列)。
- 作用: 定义了系统的边界和用户需求,是用户与开发人员沟通的重要桥梁,用于验证是否满足用户期望。
这三个模型从不同维度提供了对系统的全面视图,它们相互补充,共同构成了面向对象分析的完整体系。
《第八章》
一、主观题
1. 请简述系统设计和对象设计。
面向对象设计(Object-Oriented Design, OOD)通常分为两个主要阶段:系统设计和对象设计。
-
系统设计 (System Design):
- 概述:系统设计是面向对象设计的第一步,它着眼于系统的高层结构和架构。在这个阶段,设计者将整个系统分解为更小的、可管理的子系统 (subsystems),并决定它们之间的协作方式和通信机制。它关注的是如何将分析阶段识别出的对象和功能组织起来,形成一个整体的、可行的系统架构。
- 关注点:
- 系统分解:将系统划分为相互独立的、职责明确的子系统。
- 并发性:识别系统中的并发活动,决定如何管理并发任务和同步。
- 数据管理:设计持久化数据存储的策略,选择数据库类型或文件系统。
- 资源分配:分配进程、处理器等计算资源。
- 通信协议:定义子系统之间以及系统与外部环境之间的通信方式。
- 控制策略:确定系统内事件流和控制流的协调方式(如集中式、委托式)。
- 错误处理:规划系统如何检测、报告和从错误中恢复。
- 安全性:考虑系统的安全需求和机制。
- 产物:通常包括子系统架构图、并发模型、数据存储方案等高层设计文档。
-
对象设计 (Object Design):
- 概述:对象设计是系统设计之后的阶段,它在已确定的系统架构和子系统划分的基础上,对每个子系统内部的类和对象进行详细设计。这个阶段将分析模型中的概念性类转化为可实现的设计类,并考虑具体实现的细节、性能优化、重用性以及设计模式的应用。
- 关注点:
- 类和接口设计:为每个类定义详细的属性、操作(方法)及其可见性,并设计相关的接口。
- 算法设计:为复杂的操作设计具体的算法和数据结构。
- 关系细化:细化类之间关联的多重性、导航性,并考虑如何实现这些关系。
- 优化:针对性能、内存使用、可伸缩性等方面进行优化。
- 设计模式:应用合适的设计模式来解决常见的设计问题,提高代码质量和可维护性。
- 消息传递:确定对象间通信的具体方式和协议。
- 实现细节:考虑特定编程语言的特性和约束。
- 产物:详细的类图、对象交互图(如顺序图、协作图)、状态图、数据字典、算法描述等。
简而言之,系统设计是宏观的,关注系统的“骨架”和“协作”,而对象设计是微观的,关注每个“细胞”的具体形态和功能。两者共同构成了完整的面向对象设计过程。
2. 请比较结构化软件设计方法和面向对象软件设计方法。
结构化软件设计方法和面向对象软件设计方法是两种主流的软件设计范式,它们在设计理念、关注点、分解方式和适应性方面存在显著差异。
| 特性 | 结构化软件设计方法 | 面向对象软件设计方法 |
|---|---|---|
| 设计理念 | 功能分解、过程驱动。关注“如何做”,将系统分解为一系列功能模块。 | 对象为中心、数据驱动。关注“有什么”和“能做什么”,将系统视为对象的集合。 |
| 关注点 | 数据流、处理逻辑、功能模块。强调功能与数据的分离。 | 对象、类、封装、继承、多态、对象间协作。强调数据与操作的紧密结合。 |
| 分解方式 | 按功能(动词)分解。系统分解为功能模块,每个模块完成特定任务。 | 按对象(名词)分解。系统分解为独立的、自包含的对象。 |
| 基本单元 | 功能模块、数据。 | 类和对象。 |
| 设计工具 | 结构图(SC)、模块结构图、流程图等。 | UML类图、顺序图、状态图、组件图、部署图等。 |
| 内聚与耦合 | 强调模块的功能内聚和数据耦合(通过参数传递数据)。 | 强调对象的信息内聚和消息耦合(通过消息传递交互)。目标是高内聚、低耦合。 |
| 可维护性 | 需求变化可能导致数据流或功能逻辑的广泛修改,维护成本较高。 | 封装性使得修改局部影响小,维护成本相对较低。 |
| 可扩展性 | 增加新功能常需修改现有模块,扩展性较差。 | 继承和多态使得在不修改现有代码基础上增加新功能成为可能,扩展性好。 |
| 复用性 | 主要通过函数库进行代码复用。 | 通过类、继承、组件等实现设计和代码的广泛复用。 |
| 分析到设计 | 从数据流图到结构图,存在概念上的**“鸿沟”**,转换可能不自然。 | 从对象模型到设计模型,概念上具有一致性,转换平滑。 |
| 适用场景 | 适用于功能稳定、需求变化较少的小型系统或过程密集型系统。 | 适用于需求复杂、变化频繁、大型、可扩展的系统,尤其适合模拟现实世界。 |
总结:
面向对象设计方法更贴近人类对现实世界的认知方式,通过封装、继承和多态等特性,显著提高了软件的可维护性、可扩展性、复用性和灵活性。虽然结构化方法在特定场景仍有其价值,但在当前复杂多变的软件需求环境下,面向对象方法已成为主流。
三、单选题
-
(B)是表达系统类及其相互联系的图示,它是面向对象设计的核心,是建立状态图、协作图和其他图的基础。
A 部署图
B 类图
C 组件图
D 配置图
-
下面所列的性质中,(D)不属于面向对象设计的特性。
A 继承性
B 复用性
C 封装性
D 可视化 (可视化是UML的特性,而不是面向对象设计本身的固有特性。)
-
下列是面向对象设计方法中有关对象的叙述,其中(B)是正确的。
A 对象在内存中没有它的存储区 (对象是类的实例,在运行时会占用内存存储其属性和方法)
B 对象的属性集合是它的特征表示
C 对象的定义与程序中类型的概念相当 (对象是类的实例,类才与类型概念相当)
D 对象之间不能互相通信 (对象通过消息传递互相通信)
-
面向对象设计阶段的主要任务是系统设计和(D)
A 结构化设计
B 数据设计
C 面向对象程序设计
D 对象设计
-
面向对象设计中,基于父类创建的子类具有父类的所有特性(属性和方法),这一特点称为类的(C)
A 多态性
B 封装性
C 继承性
D 复用性
-
下列哪项不是面向对象设计的启发规则?(C)
A 设计结果应该清晰易懂
B 类等级深度应该适当
C 尽量添加设计的变动 (应尽量减少变动,保持设计稳定)
D 使用简单的协议
-
下面哪项不是系统分解的好处?(D)
A 降低设计的难度
B 有利于软件开发人员分工协作
C 有利于维护人员理解并维护系统
D 有利于增加系统依赖性 (系统分解旨在降低依赖性,提高独立性)
-
不属于任务管理子系统的是(A)。
A 人机交互所需输入 (人机交互通常属于用户接口子系统)
B 任务的定义
C 任务的通信
D 硬件分配
-
在软件系统中,由于需求的变化,一些对象的实现可能会发生变化。为了应对这种“易变对象”的变化,人们提出了(A)。
A 工厂模式 (工厂模式常用于封装对象的创建过程,以应对对象实现的易变性)
B 外观模式
C 观察者模式
D 以上都不是
四、判断题
-
在面向对象的设计中,应遵循的设计准则除了模块化、抽象、低耦合、高内聚以外,还有信息隐藏。
正确
-
面向对象分析和设计活动是一个多次反复迭代的过程。
正确
-
关系数据库可以完全支持面向对象的概念、面向对象设计中的类可以直接对应到关系数据库中的表。
错误 (关系数据库是基于关系模型的,与面向对象的对象模型存在阻抗失配问题,不能完全支持所有面向对象概念(如继承、多态的直接映射)。一个类可能对应多个表或多个表对应一个类。)
-
面向对象设计是在分析模型的基础上,运用面向对象技术生成件实即下的设计模型。
正确 (描述正确,但“件实即下”可能为错别字,应为“具体实现”。)
-
常见的任务有事件驱动型任务、时钟驱动型任务、优先任务、关键任务和协调任务等。
正确
-
设计任务管理子系统时,当系统中存在3个或3个以上的任务时,应考虑用它作为协调任务。
正确 (当任务数量较多时,引入协调任务(或称协调者)可以简化任务间的通信和管理,避免任务间直接的复杂依赖。)
-
用指针可以方便地实现单向关联。
正确 (在支持指针的语言中,通过在源类中包含指向目标类对象的指针或引用,可以方便地实现单向关联。)
-
如果某个关联包含链属性,不同关联重数的实现方法相同。
错误 (如果关联包含链属性(Link Attribute),无论关联重数如何,都需要创建一个独立的关联类来存储这些属性,并连接到参与关联的两个类。但对于不同的关联重数,关联本身的实现方式(如一对一、一对多、多对多)是不同的,例如一对多通常用集合或列表表示,多对多通常需要中间表。)
-
不可以用独立的关联对象实现双向关联。
错误 (可以使用独立的关联类来实现双向关联,特别是当关联本身具有属性时。关联类可以作为独立的类存在,管理两个或多个参与类之间的连接及其属性。)
-
增加冗余关联可以提高访问效率。
正确 (在某些情况下,为了避免复杂的导航路径或频繁的计算,可以添加冗余关联来空间换时间,提高特定查询的访问效率。但这会增加数据一致性维护的复杂性。)
-
在面向对象分析过程中,可以忽略对象模型中存在的冗余关联。
错误 (在面向对象分析过程中,不应“忽略”冗余关联。分析阶段应尽可能真实地反映问题域。虽然冗余关联可能会在设计阶段被引入用于优化,但在分析阶段应识别并记录所有语义上的关联,即使它们可能显得冗余。)
-
设计模式是从大量或成功实践中总结出来并被公认的实践和知识。
正确
五、填空题
-
数据管理子系统包括永久数据的存取,它隔离了物理的存储结构。
-
存储服务用来协调每个需永久保存的对象的存储。
-
问题域子系统也称应用子系统或业务子系统。
-
系统需求最易变动的就是加工和人机界面。
-
面向对象技术的基本特征主要为抽象性、封装性、继承性和多态性。
-
软件设计模式一般分为创建型模式、结构型模式和行为型模式。
《第九章》
一、主观题
1. 编程风格的重要性。要形成良好的编程风格可以从哪些方面做起?
编程风格的重要性
在软件工程中,良好的编程风格至关重要,它直接影响到软件的质量、团队协作效率和长期维护成本。主要体现在以下几个方面:
- 提高软件质量: 清晰、一致的代码更容易被理解和审查,从而减少引入新缺陷的可能性,并有助于快速发现和修复现有问题,最终提升软件的整体可靠性和稳定性。
- 支持团队协作开发: 统一的编程风格能够确保多位开发者编写的代码在视觉和结构上保持一致,这极大地便利了代码的交流、评审和集成,有效降低了因风格不一致而产生的沟通障碍和额外成本。
- 方便代码评审和测试: 规范化的编程风格使代码评审(Code Review)过程更高效准确,评审者能更快地理解代码逻辑。同时,清晰的代码结构也有利于单元测试等软件工程实践活动的顺利开展。
- 有助于软件生命周期管理: 软件在其整个生命周期中需要持续迭代、维护和扩展。良好的代码风格能让新加入的团队成员快速理解并接手项目,也有利于后续的维护和重构工作,从而延长软件的生命周期和价值。
形成良好编程风格的途径
在软件工程实践中,培养和形成良好的编程风格可以从以下几个方面着手:
- 遵循编码规范: 学习并严格遵守业界推荐或项目指定的编码规范(例如,Java 的 Sun/Oracle 规范、Python 的 PEP8 等)。这包括命名约定、缩进规则、括号风格、空格使用等,旨在养成统一的代码书写习惯。
- 撰写清晰注释和文档: 对类、方法、关键变量和复杂逻辑段落添加必要且有意义的注释。同时,配合撰写设计文档、接口文档等,这些都有助于提高代码的理解性。
- 合理划分模块与函数: 实践高内聚、低耦合的设计原则,确保每个函数、方法或模块职责单一、逻辑清晰、结构紧凑。这有助于提高代码的复用性和可测试性。
- 利用代码管理与格式化工具: 积极使用版本控制工具(如 Git)进行代码管理。同时,利用代码格式化工具(如 Prettier、ESLint、Black 等)自动化统一代码风格,减少人工调整的时间和不一致性。
- 参与团队合作与代码审查: 在团队项目中,积极参与代码审查。通过互相评审代码,可以互相学习、发现问题,并共同遵守团队约定的编码风格,从而提高项目整体代码质量。
- 结合软件工程实践训练: 将编程风格的培养融入到软件工程课程的各个阶段,如需求分析、设计、编码、测试等。在每个阶段都逐步建立“编写规范代码”的意识和能力。
2. 面向对象编程的概念是什么?在选择编程语言时,通常要考虑哪些因素?
面向对象编程的概念
面向对象编程 (Object-Oriented Programming, OOP) 是一种以“对象”为中心的程序设计方法。它将现实世界中的事物抽象为程序中的对象,并通过对象之间的交互来实现功能。
在 OOP 中:
- 对象是类的实例,代表现实世界中的一个具体实体,它封装了自身的属性(数据或状态)和行为(方法或操作)。
- 类是对象的蓝图或模板,定义了具有相同属性和行为的一组对象的通用结构。
面向对象编程强调以下三个核心特性:
- 封装 (Encapsulation): 将数据(属性)和操作这些数据的方法(行为)捆绑在一起,形成一个独立的单元(对象)。它隐藏对象的内部实现细节,只对外暴露必要的接口,以保护数据的完整性和安全性。
- 继承 (Inheritance): 允许一个新类(子类或派生类)从现有类(父类或基类)中复用其属性和方法。子类可以在继承的基础上增加新特性或修改现有行为,从而实现代码重用和层次结构的建立。
- 多态 (Polymorphism): 允许不同类型的对象对同一个消息(方法调用)做出不同的响应。它可以表现为方法重载(同一类中同名但参数不同的方法)和方法重写(子类重新定义父类的方法)。多态性增强了程序的灵活性和可扩展性。
面向对象编程有助于提高程序的可维护性、可扩展性和可重用性,是软件工程中广泛采用的设计和开发范式。
选择编程语言时要考虑的因素
在为特定项目选择编程语言时,通常需要综合考虑以下几个关键因素:
-
项目需求与目标:
- 领域适用性: 语言是否适合解决当前领域的问题(如 Web 开发、移动应用、数据科学、嵌入式系统)。
- 功能支持: 语言是否支持所需的功能(如并发、网络编程)和目标平台(如 iOS、Android、Web)。
- 性能要求: 对运行速度、内存消耗、实时性等是否有严格要求。
-
开发团队的熟悉程度与人才储备:
- 团队成员是否熟悉该语言及其生态系统?重新学习新语言会增加时间和成本。
- 市场上是否有足够的人才储备,以便项目后期扩展或人员替换。
-
语言的生态系统与社区支持:
- 类库和框架: 是否有丰富、成熟且高质量的第三方类库和框架,可以加速开发。
- 开发工具: 是否有完善的集成开发环境 (IDE)、调试器、自动化测试工具等。
- 社区活跃度: 活跃的社区意味着更容易找到解决方案、获得支持和最新的技术动态。
- 文档和教程: 是否有详尽、易懂的官方文档、教程和学习资源。
-
可维护性与可扩展性:
- 语言本身是否支持良好的代码结构设计(如面向对象、模块化),方便后期维护和功能扩展。
- 语言的语法和特性是否易于理解和调试。
-
安全性与稳定性:
- 语言本身是否具备内存安全、类型安全等机制,以减少常见的编程错误和安全漏洞。
- 语言的运行时环境是否健壮,错误处理机制是否完善。
-
跨平台能力:
- 是否可以在多个操作系统或设备上运行,例如 Java 的“一次编写,处处运行”特性,或 JavaScript 在前端和后端(Node.js)的应用。
-
成本与许可:
- 语言本身或其核心工具是否需要商业授权费用。
- 是否开源,这通常意味着更低的成本和更高的灵活性。
-
长期趋势与行业接受度:
- 该语言在行业中的发展趋势如何?是否具有长期潜力?
- 是否有大型企业或重要项目在使用,反映其稳定性和成熟度。
《第十章》
一、单选题
-
软件测试的目的是()。
A 证明软件是正确的
B 发现软件的错误
C 找出软件中的所有错误
D 评价软件的质量
-
白盒测试法又称为逻辑覆盖法,主要用于( )。
A 确认测试
B 系统测试
C a测试
D 单元测试
-
在软件工程中,白盒测试方法可用于测试程序的内部结构,此方法将程序作为()
A 循环的集合
B 路径的集合
C 目标的集合
D 地址的集合
-
成功的测试是指运行测试用例后()
A 发现了程序错误
B 未发现程序错误
C 证明程序正确
D 改正了程序错误
-
白盒测试是根据程序的( )来设计测试用例的方法。
A 输出数据
B 内部逻辑
C 功能
D 输入数据
-
在软件测试中,逻辑覆盖法属于()
A 黑盒测试方法
B 白盒测试方法
C 灰盒测试方法
D 软件验收方式
-
黑盒测试是从()角度进行的测试,白盒测试是从()角度进行的测试。
A 开发人员、管理人员
B 用户、开发人员
C 用户、管理人员
D 开发人员、用户
-
软件测试用例主要由输人数据和()两部分组成。
A 测试计划
B 测试规则
C 以往测试记录分析
D 预期输出结果
-
使用白盒测试方法时,确定测试数据应根据()和指定的覆盖标准。
A 程序的内部逻辑
B 程序的复杂程度
C 程序的难易程度
D 程序的功能
-
黑盒测试方法根据()设计测试用例。
A 程序的调用规则
B 软件要完成的功能
C 块间的逻辑关系
D 程序的数据结构
-
集成测试的主要方法有两个:一个是();另一个是()。
A 白盒测试方法、黑盒测试方法
B 价类划分法、边界值分析法
C 增量式测试方法、非增量式测试方法
D 因果图法、错误推测法
-
软件测试的目的是尽可能发现软件中的错误,通常( )是代码编写阶段可进行的测试,它是整个测试工作的基础。
A 集成测试
B 系统测试
C 验收测试
D 单元测试
-
单元测试主要针对模块的几个基本特征进行测试,该阶段不能完成的测试是()
A 系统功能
B 局部数据结构
C 重要的执行路径
D 错误处理
-
软件维护的副作用,是指()。
A 运行时误操作
B 隐含的错误
C 因修改软件而造成的错误
D 开发时的错误
-
影响软件可维护性的主要因素不包括()。
A 可修改性
B 可测试性
C 可用性
D 可理解性
二、判断题
-
软件测试是对软件需求规格说明、软件设计和编码的最全面也是最后的审查。
正确
-
如果通过软件测试没有发现错误,则说明软件是正确的。
错误
-
白盒测试无须考虑模块内部的执行过程和程序结构,只需了解模块的功能即可。
错误
-
软件测试的目的是尽可能多地发现软件中存在的错误,并将它作为纠错的依据。
正确
-
测试用例由输人数据和预期的输出结果两部分组成。
正确
-
白盒测试是结构测试,主要以程序的内部逻辑为基础设计测试用例。
正确
-
软件测试的目的是证明软件是正确的。
错误
-
单元测试通常应该先进行“人工走查”,再以白盒测试为主,辅以黑盒测试进行动态测试。
正确
-
白盒测试是一种静态测试方法,主要用于模块测试。
错误 (白盒测试既包括静态测试(如代码审查),也包括动态测试(如路径覆盖)。题目说“是一种静态测试方法”不够准确,且“主要用于模块测试”是正确的,但并非唯一用途。)
-
在等价类划分法中,为了提高测试效率,一个测试用例可以覆盖多个无效等价类。
错误 (一个测试用例通常只覆盖一个无效等价类。如果一个测试用例同时覆盖多个无效等价类,当测试失败时,将难以判断是哪个等价类引起的错误,从而降低了错误定位的效率。)
-
功能测试是系统测试的主要内容,用于检查系统的功能、性能是否与需求规格说明相同。
正确
-
适应性维护是在软件使用过程中,用户对软件提出新的功能和性能要求,为了满足这些新的要求而对软件进行修改,使之在功能和性能上得到完善和增强的活动。
错误 (这是完善性维护的定义。适应性维护是指为适应外部环境(如操作系统、数据库、硬件等)变化而进行的修改。)
三、填空题
-
在软件测试工作中,存在**缺陷的二八原则(或帕累托原则)**即约80%的错误会集中存在于约20%的代码中。
-
软件测试模型是指软件测试全部过程活动或任务的结构框架。
-
软件测试按照是否运行程序可分为静态测试和动态测试。
-
通过描述每个经过用例的可能路径,可以确定不同的用例场景,这个流经路径要从用例起点开始到结束,遍历其中所有基本流和备选流(或异常流)。
-
一般在软件测试过程中,既要用到黑盒测试,又要用到白盒测试。大的功能模块采用黑盒测试,小的组件采用白盒测试。
-
在确认测试的过程中仅使用模块黑盒测试技术。
-
在进行单元测试时,被测试的单元本身不是独立的程序,需要为其开发驱动模块和桩模块。
-
集成测试一般由测试人员和开发人员完成。
-
功能测试是系统测试中最基本的测试,它不管软件内部是如何实现的。
-
系统测试中,安全测试包含容错性测试和恢复测试。
-
β测试由最终用户实施,通常开发组织对其的管理很少或不管理。
-
软件维护可分为纠错性维护、适应性维护、完善性维护、预防性维护4类。
-
简单地说,软件部署就是将开发的软件拿给用户使用,给用户配置环境(包括硬件、软件的安装以及环境变量的设置等),使开发的软件能被用户正常使用的过程。
-
软件再工程是一类工程活动,它将逆向工程、重构和正向工程组合起来,将现存系统重新构造为新的形式。
四、主观题
42. 请对比白盒测试和黑盒测试。他们分别由哪些测试用例设计方法。
白盒测试和黑盒测试是软件测试中两种最基本且互补的测试方法,它们从不同的视角和目的进行测试。
42.1 白盒测试 (White-Box Testing)
-
定义: 白盒测试,又称结构测试或透明盒测试,是一种基于程序内部结构和逻辑的测试方法。测试人员需要了解程序的源代码、内部数据结构、算法和控制流程。
-
目的: 验证程序的内部运作是否符合设计规范,发现代码中未被执行的路径、逻辑错误、数据流错误、循环错误等。
-
测试对象: 程序的内部结构,如语句、分支、路径、循环等。
-
适用阶段: 主要应用于单元测试,也常用于集成测试的早期阶段。
-
优点:
- 能够检测到程序内部的缺陷,例如死循环、不可达代码、逻辑路径错误等。
- 对代码覆盖率有清晰的度量,有助于提高测试的彻底性。
- 有助于发现和排除开发人员容易忽略的低级错误。
-
缺点:
- 测试成本高,需要深入了解代码,测试用例设计复杂。
- 无法发现与功能需求不符的错误(例如,功能缺失或功能实现错误但内部逻辑正确)。
- 不适用于大规模复杂系统,测试用例数量可能呈指数级增长。
-
测试用例设计方法:
- 语句覆盖 (Statement Coverage): 确保程序中的每一条可执行语句至少被执行一次。
- 判定覆盖 (Decision Coverage) / 分支覆盖 (Branch Coverage): 确保程序中的每一个判定的所有可能结果(真/假分支)至少被执行一次。
- 条件覆盖 (Condition Coverage): 确保判定中的每个简单条件的所有可能结果(真/假)至少被执行一次。
- 判定/条件覆盖 (Decision/Condition Coverage): 组合判定覆盖和条件覆盖。
- 条件组合覆盖 (Condition Combination Coverage): 确保每个判定中所有条件的各种可能组合至少被执行一次。
- 路径覆盖 (Path Coverage): 确保程序中所有独立的执行路径至少被执行一次(这是最强的覆盖标准,但通常不可行)。
- 循环覆盖 (Loop Coverage): 针对程序中的循环结构设计测试用例,确保循环体在零次、一次、多次迭代以及边界条件下的行为正确。
- 基本路径测试 (Basis Path Testing): 根据程序的控制流图,计算其圈复杂度,从而确定程序中独立路径的数量,并为每条独立路径设计测试用例。
42.2 黑盒测试 (Black-Box Testing)
-
定义: 黑盒测试,又称功能测试或数据驱动测试,是一种在不了解程序内部结构的情况下,基于软件的功能需求和规格说明进行的测试。测试人员只关注软件的输入和输出,将其视为一个“黑盒子”。
-
目的: 验证软件是否符合用户需求和功能规格,发现功能缺失、功能错误、接口错误、数据处理错误、性能问题等。
-
测试对象: 软件的外部可见功能和行为。
-
适用阶段: 贯穿整个测试过程,主要应用于集成测试、系统测试和验收测试。
-
优点:
- 不需要了解程序的内部实现细节,测试人员可以与开发人员分离。
- 从用户角度出发,更容易发现用户关心的问题。
- 适用于任何复杂程度的软件。
- 测试用例设计相对简单,且可以根据需求规格直接生成。
-
缺点:
- 可能存在代码盲区,无法发现内部的逻辑错误或未被执行的代码路径。
- 测试用例可能存在冗余,效率不高。
- 难以穷尽所有可能的输入组合。
-
测试用例设计方法:
- 等价类划分法 (Equivalence Partitioning): 将程序的输入域划分为若干个等价类,从每个等价类中选取一个代表性的测试用例。
- 边界值分析法 (Boundary Value Analysis): 在等价类划分的基础上,针对输入或输出值的边界条件设计测试用例(例如,最大值、最小值、刚超过边界的值、刚好在边界上的值)。
- 因果图法 (Cause-Effect Graphing): 用于描述输入条件(原因)与输出结果(效果)之间的逻辑关系,并转换为决策表,从而设计测试用例。适用于具有复杂逻辑组合关系的场景。
- 错误推测法 (Error Guessing): 凭测试人员的经验和直觉,推测程序可能存在的缺陷,并有针对性地设计测试用例。
- 场景法 (Scenario-Based Testing): 根据用户故事、用例或业务流程,设计描述用户操作和系统响应的测试场景。
- 状态迁移测试 (State Transition Testing): 针对具有明确状态和状态转换的系统(如协议、UI交互)设计测试用例,确保所有状态和转换都被正确测试。
43. 为什么软件开发人员不能同时完成测试工作?
软件开发人员通常不适合独自完成软件的全部测试工作,主要有以下几个原因:
-
思维定势/“灯下黑”效应:
- 开发人员在编写代码时,思维往往会沿着预设的逻辑路径进行,很难跳出自己固有的思维框架去发现潜在的错误。他们倾向于测试代码“应该如何工作”,而不是“可能会如何失败”。
- 这种“灯下黑”效应导致开发人员容易忽略自己代码中的缺陷,因为他们对代码的实现细节过于熟悉,可能会无意识地跳过某些逻辑分支或极端情况。
-
利益冲突与心理障碍:
- 开发人员的绩效往往与代码的完成质量和进度挂钩。如果由他们自己测试并发现大量错误,可能会影响他们的自我评价或团队的进度考评,从而产生一种避免发现错误的潜意识。
- 承认自己的代码有缺陷需要一定的心理承受能力,可能会导致他们倾向于做“证实性测试”(证明代码是正确的),而不是“破坏性测试”(试图找出错误)。
-
测试技能与视角差异:
- 开发人员擅长构建和实现,他们的强项在于理解技术细节和编写高效代码。而测试工作需要不同的思维模式,如逆向思维、发散性思维、追求破坏性、注重边界条件和异常情况等。
- 专业测试人员拥有更丰富的测试理论知识、方法论和工具,能够从用户角度、业务角度、安全角度、性能角度等更全面的视角进行测试。
-
知识盲区和局限性:
- 开发人员对需求理解可能存在偏差,或者只关注了自己负责模块的功能。而独立的测试团队可以从系统整体视角出发,发现模块间的集成问题、接口问题以及潜在的需求理解偏差。
- 专业的测试人员更懂得如何模拟真实用户的使用场景,如何构造刁钻的输入数据,以及如何进行性能和安全性等非功能性测试。
-
时间与资源限制:
- 开发人员通常承担着开发进度压力,时间有限。如果同时承担大量的测试工作,可能会导致开发和测试都无法高质量完成。
- 将开发和测试分离,可以实现更专业的资源分配和并行工作,提高整体效率。
综上所述,软件测试需要一个独立、专业的团队来进行,以确保测试的客观性、全面性和有效性。开发人员更多地参与单元测试和自测试,但更高层面的集成测试、系统测试和验收测试通常由独立的测试团队完成。
44. 软件测试的目的是什么?
软件测试的目的是尽可能多地发现软件中存在的错误、缺陷和漏洞,并将其作为纠错的依据,以提高软件的质量和可靠性。
具体来说,软件测试的主要目的包括:
- 发现错误: 这是测试最直接和最重要的目的。通过执行测试用例,识别软件中与需求不符、行为异常、性能低下或存在安全风险的问题。
- 提高软件质量: 通过发现并修复错误,使软件更加健壮、可靠、可用和高效,从而提升软件的整体质量。
- 验证符合性: 验证软件的功能、性能、安全性等特性是否满足用户需求规格说明和设计文档的要求。这包括确认软件的功能是否正确实现、性能是否达到预期、用户界面是否符合预期等。
- 提供信息: 向项目团队、管理层和客户提供关于软件质量的客观信息。这些信息有助于决策者了解软件的风险、发布准备情况,以及是否可以投入使用。
- 建立信心: 通过系统的测试过程,增强开发团队和用户对软件产品质量的信心。当软件经过严格测试后,用户更愿意相信它的稳定性和可靠性。
- 预防缺陷: 虽然测试主要是发现现有错误,但测试过程中发现的问题和分析也可以反向指导开发过程,帮助开发人员避免在未来引入类似的错误,从而起到一定的预防作用。
- 评估风险: 帮助评估软件发布后的潜在风险,包括功能失效、数据丢失、安全漏洞等。
需要强调的是,软件测试的目的不是证明软件是正确的,也不是找出软件中的所有错误。由于软件的复杂性,穷尽所有测试路径是不可能的。测试只能尽可能地揭示错误的存在,而不能证明软件没有错误。正如Edsger Dijkstra所说:“程序测试能够揭示错误的存在,但不能证明其中没有错误。”
45. 软件测试应该划分为几个阶段?各个阶段应重点测试的内容是什么?
软件测试通常划分为以下几个主要阶段,每个阶段都有其特定的目标和测试重点:
45.1 单元测试 (Unit Testing)
- 阶段: 通常在编码阶段完成,是软件测试的第一个阶段。
- 测试对象: 程序的最小可测试单元,如函数、方法、类或模块。
- 测试者: 通常由开发人员完成。
- 测试方法: 主要采用白盒测试方法(如语句覆盖、分支覆盖、路径覆盖),辅以黑盒测试(如等价类划分、边界值分析)。
- 重点测试内容:
- 模块接口: 检查模块的参数传递、输入输出是否正确。
- 局部数据结构: 检查模块内部使用的数据结构是否正确。
- 独立路径: 确保模块中所有独立的执行路径(包括条件分支和循环)都能被至少执行一次。
- 错误处理: 验证模块对异常条件和错误输入的处理能力。
- 边界条件: 测试输入数据的边界值情况。
45.2 集成测试 (Integration Testing)
- 阶段: 在单元测试之后,将经过单元测试的模块逐步组合在一起进行测试。
- 测试对象: 模块之间、子系统之间的接口和相互作用。
- 测试者: 通常由开发人员和测试人员共同完成。
- 测试方法: 结合白盒测试(关注接口和内部结构)和黑盒测试(关注功能组合)。
- 主要方法:
- 增量式集成测试: 逐步集成模块,每次集成后进行测试。包括自顶向下、自底向上和混合(三明治)集成。
- 非增量式集成测试(大爆炸式): 将所有模块一次性集成,然后进行测试。
- 重点测试内容:
- 模块接口连接: 检查模块间数据传递、控制流传递的正确性。
- 功能组合: 验证模块组合后是否能正确实现其预期的功能。
- 全局数据结构: 检查模块间共享的全局数据结构是否正确。
- 与外部系统接口: 如果有,测试与外部系统或硬件的接口。
45.3 系统测试 (System Testing)
- 阶段: 在所有模块都集成完毕并进行过集成测试之后,对整个软件系统进行测试。
- 测试对象: 整个软件系统,包括功能和非功能特性。
- 测试者: 主要由专业测试人员完成。
- 测试方法: 主要采用黑盒测试方法。
- 重点测试内容:
- 功能测试: 验证系统是否满足需求规格说明中定义的所有功能。
- 性能测试: 测试系统的响应时间、吞吐量、资源利用率等。
- 安全性测试: 评估系统的安全性,防止未经授权的访问、数据泄露等。
- 可靠性测试: 测试系统在长时间运行和异常条件下的稳定性。
- 压力测试/负载测试: 在高负载或极端条件下测试系统的行为。
- 恢复测试: 测试系统从故障中恢复的能力。
- 兼容性测试: 测试系统在不同硬件、软件、网络环境下的兼容性。
- 安装/卸载测试: 验证软件的安装和卸载过程是否正确。
45.4 验收测试 (Acceptance Testing)
- 阶段: 软件部署前或部署后,由最终用户或客户进行的正式测试。
- 测试对象: 完整的、满足用户需求的软件产品。
- 测试者: 最终用户或客户,有时在测试人员协助下完成。
- 测试方法: 严格按照用户需求规格说明和业务场景,主要采用黑盒测试方法。通常包括 Alpha 测试和 Beta 测试。
- Alpha 测试: 在开发组织的受控环境下,由用户模拟或实际使用。
- Beta 测试: 在真实用户环境下进行,由大量真实用户使用并反馈问题。
- 重点测试内容:
- 用户需求符合性: 核心目标是验证系统是否满足用户的实际业务需求和期望。
- 业务流程正确性: 确保整个业务流程在系统中正确流转。
- 易用性: 评估用户界面的友好性和操作的便捷性。
- 文档有效性: 验证用户手册、操作指南等文档的准确性和实用性。
- 与业务环境的集成: 确保软件能无缝集成到用户现有的业务环境和流程中。
这四个阶段是递进和迭代的,共同构成了全面的软件测试策略,旨在在不同粒度上发现并修复软件缺陷,确保软件质量。
46. 为什么要进行软件维护?软件维护有哪几类,分别的作用有哪些?
46.1 为什么要进行软件维护?
软件维护是软件生命周期中非常重要且耗时的一个阶段。即使软件交付后,也需要进行持续的维护工作,其主要原因包括:
-
修复缺陷和错误: 任何软件都可能存在在开发和测试阶段未能发现的残留缺陷(bugs)。这些缺陷在使用过程中可能显现出来,导致系统崩溃、功能异常或数据错误,必须通过维护来修复。
-
适应环境变化: 软件不是孤立存在的,它运行在特定的硬件、操作系统、数据库、网络环境以及与其他系统的交互中。当这些外部环境发生变化(如操作系统升级、数据库版本更新、新的硬件设备出现、法规政策调整)时,软件可能需要修改以适应新的环境,确保兼容性和正常运行。
-
满足新的需求和增强功能: 随着业务发展和用户体验的提升,用户往往会提出新的功能需求或对现有功能进行改进和优化。为了保持软件的竞争力、提高用户满意度和业务价值,需要进行维护来添加新功能或增强现有功能。
-
提高性能和可靠性: 软件在实际运行中可能会出现性能瓶颈或效率低下,或者在特定条件下不稳定。维护工作可以包括性能优化、代码重构、架构调整等,以提高软件的运行效率、响应速度和稳定性。
-
延长软件生命周期: 软件资产的价值巨大。通过持续的维护,可以有效延长软件的使用寿命,避免因过时或问题积累而导致系统被废弃,从而保护投资。
-
提高可维护性: 有时在维护过程中,会发现现有代码结构混乱、难以理解。进行维护也可以改进软件的内部结构,使其更易于未来的修改和扩展。
46.2 软件维护的四种主要类型及作用
根据 IEEE Std 1219-1998 标准,软件维护通常分为四种类型:
-
纠错性维护 (Corrective Maintenance)
- 定义: 对在软件运行过程中发现的错误和缺陷进行诊断和修正的活动。
- 作用: 消除软件缺陷,确保软件能够按照预期的功能正常运行,提高软件的可靠性和稳定性。这是最基本的维护类型,通常是紧急且必须的。
- 示例: 修复一个导致系统崩溃的bug、修正一个计算错误、解决一个数据不一致的问题。
-
适应性维护 (Adaptive Maintenance)
- 定义: 为使软件能适应其外部环境变化而进行的修改。这些变化通常指硬件平台、操作系统、数据库、网络协议、外部接口或新法规政策等非功能性环境因素的变化。
- 作用: 确保软件在不断变化的外部环境中能够持续地兼容和正常运行,保持软件的可用性。
- 示例: 升级数据库版本后修改软件以兼容新版本、为适应新的操作系统版本而修改代码、调整税务系统以符合新的税法。
-
完善性维护 (Perfective Maintenance)
- 定义: 根据用户提出的新的功能需求、性能改进或用户体验优化等非缺陷性变更而进行的修改。目的是提高软件的效率、功能性和可维护性。
- 作用: 增强软件的功能和性能,提高用户满意度,增加软件的业务价值和竞争力。这是最能体现软件价值增值的维护类型。
- 示例: 增加新的报表功能、优化查询速度、改进用户界面、为提高效率重构部分代码。
-
预防性维护 (Preventive Maintenance)
- 定义: 在软件出现故障之前,为了提高软件的未来可维护性、可靠性或性能,而对软件进行的修改。它旨在预防潜在的问题或降低未来维护的难度。
- 作用: 降低未来维护成本,延长软件寿命,提高软件的内部质量(如结构清晰度、可读性),减少未来发生故障的可能性。
- 示例: 代码重构以提高可读性和模块化、更新过时的技术栈、改进文档、优化数据库索引以预期提高查询性能。
这四种维护类型共同构成了软件维护的完整视图,确保软件能够长期、稳定、高效地为用户提供服务,并随业务发展持续演进。
《第十一章》
一、单选题
-
(B)的作用是为有效地、定量地进行管理,把握软件工程过程的实际情况和它所产生的产品质量。
A 估算
B 度量
C 风险分析
D 进度安排
-
下列哪项不是风险管理的过程?(D)
A 风险规划
B 风险识别
C 风险评估
D 风险收集 (风险收集通常是风险识别的一部分,而不是独立的过程。)
-
按照软件配置管理的原始指导思想,受控制的对象应是(C)
A 软件过程
B 软件项目
C 软件配置项
D 软件元素
-
下面(A)不是人们常用的评价软件质量的4个因素之一。
A 可理解性 (通常是可靠性、可用性、可维护性和效率,或功能性、可靠性、易用性、效率、可维护性、可移植性等)
B 可靠性
C 可维护性
D 易用性
-
软件文档是软件工程实施的重要成分,它不仅是软件开发各阶段的重要依据,而且影响软件的(B)
A 可用性
B 可维护性
C 可扩展性
D 可移植性
-
CMM表示(A)。
A 软件过程能力成熟度模型
B 软件配置管理
C 软件质量认证
D 软件复用
二、判断题
-
代码行估算法是比较简单的定量估算软件规模的方法。
正确
-
功能点估算法依据对软件信息域特性和软件复杂性的评估结果,估算软件规模。
正确
-
常用的制定进度计划的工具主要有Word和Excel两种。
错误 (Word和Excel虽然可以用于简单的计划,但更专业的工具是项目管理软件,如Microsoft Project, Jira, GanttProject等,以及专门的甘特图和PERT图工具。)
-
民主制程序员组的一个重要特点是,小组成员完全平等,享有充分民主,通过协商做出技术决策。
正确
-
主程序员组的两个关键特性是专业化和层次性。
正确
-
现代程序员组中,技术组长既对技术工作负责,又负责非技术事务。
正确 (现代团队往往强调多职责,技术组长通常需要兼顾技术指导和部分管理协调工作。)
-
风险有两个显著特点:一个是不确定性;另一个是损失。
正确
-
回避风险指的是风险倘若发生,就接受后果。
错误 (这是接受风险的定义。回避风险是指采取措施消除风险或改变计划以避免风险发生。)
-
软件质量保证的措施主要有基于非执行的测试(也称为复审)、基于执行的测试和程序正确性证明。
正确
-
总体上说,软件工程文档可以分为用户文档、开发文档和管理文档3类。
正确
-
文档是影响软件可维护性的决定因素。
正确 (文档的质量直接影响软件的可理解性,进而影响其可维护性。)
-
软件生命周期的最后一个阶段是书写软件文档。
错误 (软件生命周期的最后一个阶段通常是退役或报废阶段,而文档工作贯穿软件生命周期的始终。)
-
CMM是指导软件开发的一种面向对象的新技术。
错误 (CMM是软件过程能力成熟度模型,与面向对象技术不是一个范畴,它关注的是组织如何管理和改进其软件开发过程,而不是一种开发技术。)
三、填空题
-
甘特图(Gantt Chart)是常用的进度管理工具,用于可视化任务时间安排。
-
进行配置控制是配置管理的关键,包括访问控制、版本控制、变更控制和产品发布控制等。
-
总体上说,软件工程文档可以分为用户文档、开发文档和管理文档三类。
-
根据ISO9126标准的定义,软件质量的特性包括功能性、可靠性、可用性、效率、可维护性和可移植性。