跳过正文

软件工程导论67题

·1372 字· loading · loading ·
Masterlong
作者
Masterlong
熬夜,但是世界之夜
目录

1. 概念:软件工程
#

目的在于建立和使用一套合理的工程原则,以使经济地获得可靠的、可以在实际机器上高效运行的软件。

研究并实现将系统化的、规范的、可量化的方法应用于软件的开发、运行和维护。

2. 概念:软件
#

你了解“软件”吗?到底什么是软件?软件与硬件之间的差别是什么?软件有哪些大类?“软件失效曲线图”说明了什么?什么是软件退化的根本原因?可复用构件对于工程师的意义是什么?

软件在形式上是指令的集合(程序)+ 数据结构 + 软件描述信息(文档)。

同硬件相比,软件是逻辑的而非物理的系统元素,因此:

  • 软件是设计开发的,而不是传统意义上生产建造的;

  • 软件不会“磨损”;

  • 虽然整个工业向着基于构件的构造模式发展,然而大多数软件仍是根据实际的顾客需求定制的;

七大类

  • 系统软件

  • 应用软件

  • 工程/科学软件

  • 嵌入式软件

  • 产品线软件

  • web应用软件

  • 人工智能软件

“软件失效曲线图”说明软件不会“磨损”,但存在退化现象:前期软件存在缺陷导致高失效率,而后逐渐被修复;而在完整生存周期中,软件面临每次变更带来的新错误,使得失效率一次又一次在变更点后再次上升。

不断的变更是软件退化的根本原因。

可复用构件使得工程师得以专心于设计中真正创新的部分。

软件工程研究的内容适合于所有软件大类的开发吗?为什么?

3. 软件危机
#

在软件产业发展至今,软件开发人员在开发中依然面临着与之前——可追溯到独立程序员时代同样的问题,它们有哪些?

何提高代码质量、如何提高开发效率、如何保证软件的可维护性、如何保证软件的安全性等。

4. 软件工程是一个层次化的技术
#

软件工程是一个层次化的技术。具体包含哪些层?各层分别解决什么问题,有哪些解决方案?

质量关注点-过程-方法-工具

支持软件工程的根基在于质量关注点(quality focus)。 软件工程的基础是过程(process) 层。软件过程将各个技术层次结合在一起,使得合理、及时地开发计算机软件成为可能。过程定义了一个框架,构建该框架是有效实施软件工程技术必不可少的。软件过程构成了软件项目管理控制的基础,建立了工作环境以便于应用技术方法、提交工作产品(模型、文档、数据、报告、表格等)、建立里程碑、保证质量及正确管理变更。

软件工程方法(method) 为构建软件提供技术上的解决方法(“ 如何做")。方法覆盖面很广,包括沟通、需求分析、设计建模、编程、测试和技术支持。软件工程方法依赖于一组基本原则,这些原则涵盖了软件工程所有技术领城,包括建模和其他描述性技术等。 软件工程工具(tool) 为过程和方法提供自动化或半自动化的支持。这些工具可以集成起来,使得一个工具产生的信息可被另外个工具使用,这样就建立了软件开发的支撑系统,称为计算机辅助软件工程(computer-aided software engineering)。

5. 软件过程
#

1,软件过程指什么?

2,为构建高品质有价值的软件,需要执行的框架活动和一系列普适性活动有哪些?它们是广泛适用的吗?

3,在软件产品构件过程中,活动、动作和任务之间的关系是什么?

4,可以如何组织框架中的活动、动作和任务?

软件过程是工作产品构建时所执行的一系列活动、 动作和任务的集合。

通用软件工程过程框架通常包括:沟通/策划/建模/构建。它们是广泛适用的。

活动主要实现宽泛的目标(如与利益相关者进行沟通),与应用领域、项目大小、结果复杂性或者实施软件工程的重要程度没有直接关系。动作(如体系结构设计)包含了主要工作产品(如体系结构设计模型)生产过程中的一系列任务。任务关注小而明确的目标,能够产生实际产品(如构建一个单元测试)。

过程流描述了在执行顺序和执行时间上,如何组织框架中的活动、动作和任务。

6. 理解解决问题的本质
#

实践的精髓指出在开发中我们需要做出的思考和行为,那么需要做哪些事情?做的每一件事情是为了解决哪些问题?

  • 理解问题(沟通和分析)

  • 计划解决方案(建模和软件设计)

  • 实施计划(代码生成)

  • 检查结果的正确性(测试和质量保证)

7. 软件工程实践一般原则
#

  • 存在价值

  • 保持简洁

  • 保持愿景

  • 关注使用者

  • 面向未来

  • 计划复用

  • 认真思考

8. 软件神话
#

对每一软件神话都问一问如下问题:

判断:这一软件神话对吗?为什么?不对的话,又应该如何做才是对的?

比如,

有人说: “我们已经有了一本写满软件开发标准和规程的宝典,难道不能提供我们所需了解的所有信息吗?” 这种说法对吗?为什么?不对的话,又应该如何做才是对的?

  • 我们已经有了一本写满软件开发标准和规程的宝典,难道不能提供我们所需了解的所有信息吗?

显然不对。原因和应对:即使存在这样的宝典,我们仍需要考虑它的实际应用价值如何、从业人员是否熟悉宝典、它是否具有时效性反映现状、是否全面且适应不同环境、能否兼顾交付时间和产品质量。在软件开发中,应当时刻联系客观的现实条件。

9. 分析判断
#

有人说:“直到程序开始运行,才能评估其质量。”这句话对吗?说一说你对质量评估的看法。请结合教科书中软件神话一部分提供的资料以及关于软件危机的思考做出解答。

不对。

“最有效的软件质量保证机制之一一技术评审, 可以从项目启动就开始实行。软件评审作为“质量过滤器”,已经证明可以比软件测试更为有效地发现多种类型的软件缺陷。”

在软件工程中,技术评审是一个为建造高质量软件所需要完成的活动、动作和任务的框架。评审相当于软件开发过程的“过滤器”,在软件开发的一些时间点上对中间产品执行评审,发现和排除错误,防止错误被遗留到后续阶段。

10. 软件过程框架
#

思考:什么是软件过程和软件过程框架?软件过程框架中,描述了哪些共同的、基本的活动?哪些是框架活动?哪些是普适性活动(即保护性辅助活动)?这些活动适用于何种软件开发?哪些是属于贯穿软件过程始终的活动呢?

软件过程是工作产品构建时所执行的一系列活动、 动作和任务的集合。

过程框架定义了若千个框架活动, 为实现完整的软件工程过程建立了基础。这些活动可广泛应用于所有软件开发项目,无论项目的规模和复杂性如何。

一个通用的软件工程过程框架通常包含以下5个活动:沟通/策划/建模/构建。

典型的普适性活动包括:软件项目跟踪和控制/风险管理/软件质量保证/技术评审/测量/软件配置管理/可复用管理/工作产品的准备和生产。

这些活动可广泛应用于所有软件开发项目,无论项目的规模和复杂性如何。

上述普适性活动贯穿软件过程始终。

11. 过程流
#

关于软件过程的另一个方面是过程流。过程流描述了什么?如何组织过程框架中活动、动作和任务呢?

过程流描述了在执行顺序和执行时间上,如何组织框架中白 活动、动作和任务,用于展示开发过程中不同任务和活动的相互关系,以及它们之间的执行顺序。

在组织过程框架中,活动、动作和任务可以根据它们的关系和依赖性来组织。以下是一些常见的组织方式:

  1. 阶段性组织:将软件开发过程划分为若干个阶段,每个阶段包含一组相关的活动和任务。例如,常见的软件开发阶段包括需求分析、设计、编码、测试和部署。每个阶段可以按照特定的顺序执行,并且在完成前一阶段的任务后才能进入下一阶段。
  2. 迭代式组织:软件开发可以按照迭代的方式进行,每个迭代包含一系列活动和任务,如需求定义、设计、实现和测试。每个迭代都会产生一个可工作的软件版本,可以进行评审和反馈,并根据反馈进行下一轮迭代。
  3. 并行组织:某些活动和任务可以并行进行,以加快软件开发进度。在过程框架中,这些并行的活动和任务可以同时进行,而不必等待前一个任务的完成。这可以提高开发效率,但需要确保活动之间没有太大的依赖性或冲突。
  4. 依赖关系组织:有些活动和任务之间存在依赖关系,必须按照特定的顺序执行。在过程框架中,这些依赖关系可以通过明确指定任务之间的前置条件和后置条件来进行组织。这可以确保在执行过程中不会出现任务之间的冲突或错误。

12. 过程模式
#

1,过程模式的定义?

2,如何描述一个过程模式?【参见教材中有关过程模式的描述模板和例子】

过程模式描述了软件工程工作中遇到的过程相关的问题、明确了问题环境并给出了针对该问题的一种或几种可证明的解决方案。 通俗地讲,过程模式提供了一个模板——一种在软件过程的背景 下,统一描述问题解决方案的方法。通过模式组合,软件团队可以解决问题并定义最符合项目需求的开发过程。


过程模式的描述模板: 模式名称。模式名称应能清楚地表述该模式在软件过程中的含义(例如,模式模板提供技术评审)。 驱动力。模式使用环境及主要问题,以明确主要难点并可能影响解决方案。 类型。定义模式类型。

  • 1.步骤模式(stage pattern),定义了与过程的框架活动相关的问题。由于框架活动包括很多动作和工作任务,步骤模式包括与步骤(框架活动)有关的许多任务模式(见以下描述)。 例如,建立沟通可能作为-一个步骤模式。该步骤模式可能包括需求获取等任务模式。 2.任务模式(task pattern), 定义了与软件工程动作或是工作任务相关、关系软件工程实践成败的问题(例如,需求获取是一个任务模式)。 3.阶段模式(phase pattern),定义在过程中发生的框架活动序列,即使这些活动流本质上是迭代的。例如,螺旋模型和原型开发就是两种阶段模式。

启动条件:它描述的是模式应用的前提条件。在应用模式之前需要明确: (1)在此之前,整个开发组织或是开发团队内已经有哪些活动? (2) 过程的进入状态是什么? (3) 已经有哪些软件工程信息或是项目信息? 例如,策划模式(阶段模式)需要的前提条件有: (1) 客户和软件工程师已经建立了合作的交流机制; (2) 已经成功完成- 些客户沟通模式中特定的任务模式,(3) 项目范围、基本业务需求和项目限制条件已经确定。 问题:描述模式将要解决的具体问题。 解决办法:描述如何成功实现模式。这部分主要讨论随着模式的启动,过程的初始状态(模式应用之前就已经存在)是如何发生改变的。解决方法也描述了随着模式的成功执行,模式启动之前所获得的软件工程信息和项目信息是如何变换的。 结束条件:描述模式成功执行之后的结果。模式结束时需要明确(1) 必须完成哪些开发组织或是开发团队相关的活动? (2) 过程的结束状态是什么? (3) 产生了哪些软件工程信息或是项目信息? 相关模式。以层次或其他图的方式列举与该模式直接相关的其他过程模式。例如步骤模式沟通包括了一组任务模式:项目团队组织、合作指导原则定义、范围分解、需求获取、约束描述以及场景模式的创建等。 已知应用实例:说明该模式可应用的具体实例。例如,沟通在每一个软件项 目的开始都是必需的,建议在整个软件项目过程中采用,并规定在部署活动中必须进行。

13. 过程模式分析
#

对书中所述的每一种过程模式(不限于书上列举的过程模式,请自行拓展),从这样几个方面去掌握:

•(1)适用场景,即该过程模式解决什么过程问题;比如原型模式,适用于的情形是这样的:“很多时候,客户提出了软件的一些基本功能,但是没有详细定义功能和特性需求。”或者“有时,开发人员可能对算法的效率、操作系统的兼容性和人机交互的形式等情况不确定。”

•(2)语义模型,即针对过程问题提出并经实践检验成功的解决方案。

你需要从这样一些方面掌握该过程模型:①该过程模型包含的活动有哪些?其组织形式是怎样的?②书上的示意图描述了该过程模式的活动和活动的组织形式,你需要着手画一画;③请自行用自己的方式,如活动图、思维导图等来描述该过程模式的活动和活动的组织形式。

•一些常规的过程模式有:(1)瀑布模型;(2)增量模型;(3)原型模型;(4)螺旋模型

(1) 瀑布模型: 适用场景:

  • 当项目需求明确、稳定,并且能够在项目开始时完全定义时,瀑布模型适用。这种模型适用于较小的项目或具有明确定义的功能和特性的项目。
  • 当项目具有线性、顺序的活动流程,各个阶段之间有明确的交付物和依赖关系时,瀑布模型是一种可行的选择。

语义模型: ① 瀑布模型包含以下活动:需求分析、系统设计、编码、测试和维护。这些活动按照顺序依次进行。 ② 组织形式:每个阶段在前一个阶段完成后开始。每个阶段的结果成为下一个阶段的输入。

③ 活动和组织形式的描述:

  • 需求分析阶段:识别和理解用户需求,并将其转化为软件需求规格说明。该阶段的输出是需求文档。
  • 系统设计阶段:在需求的基础上进行软件架构设计、模块划分和数据库设计等。输出是软件设计文档。
  • 编码阶段:根据设计文档编写代码,并进行单元测试。输出是可执行的软件模块。
  • 测试阶段:对软件进行系统测试、集成测试和验收测试,确保软件符合预期的功能和质量要求。输出是经过测试的软件产品。
  • 维护阶段:修复软件中的缺陷、添加新功能和进行升级。输出是经过维护的软件版本。

(2) 增量模型: 适用场景:

  • 当项目规模庞大、复杂度高,或者需求不完全明确时,增量模型适用。通过分阶段交付增量,可以更快地响应需求变化和获取用户反馈。
  • 当项目具有明确的核心功能,并可以通过迭代方式逐步添加新功能时,增量模型是一种有效的选择。

语义模型: ① 增量模型包含以下活动:需求分析、设计、实施和测试。每个活动在不同的增量中迭代进行。 ② 组织形式:每个增量包含一个完整的开发循环,包括需求分析、设计、实施和测试。每个增量的结果是一个可以交付的软件版本。

③ 活动和组织形式的描述:

  • 需求分析:收集和分析用户需求,并将其转化为增量需求规格说明。
  • 设计:在每个增量中进行系统设计和详细设计,包括架构设计和模块设计。
  • 实施:在每个增量中进行编码和单元测试,生成可执行的软件模块。
  • 测试:对每个增量进行系统测试和集成测试,确保增量的功能和质量要求满足用户需求。
  • 交付:每个增量完成后,交付一个部分功能完备的软件版本,可供用户评审和反馈。

14. 原型开发
#

思考:原型开发是一种过程模式,其更多的运用于定义需求,原型模型描述了一种构建原型系统的方法,使得利益相关者可以反复评估,以便识别和确定软件需求。现在的问题是经该过程得到的一个“可运行的原型”时,它可以发布吗?还是应该抛弃?为什么?

抛弃。

原型系统作为定义软件需求的一种机制,是为定义需求服务的,应当被丢弃(或至少是部分丢弃,慢慢演化为实际系统),实际的软件是以质量第一为目标开发的。

15. 敏捷软件开发宣言
#

请多读几遍“敏捷软件开发宣言”,并通过实践感受和思考。

我们在实践中发现,通过以下方式提供软件开发项目的最佳方案:

个体和互动 高于 流程和工具 可工作的软件 高于 面面俱到的文档 客户合作 高于 合同谈判 响应变化 高于 遵循计划 也就是说,尽管右侧有价值,我们更重视左侧的内容。

通过实践感受和思考,我的理解有:

个体和互动高于流程和工具: 敏捷方法注重团队成员之间的合作和沟通。工具和流程是辅助的,而真正的关键是人与人之间的交互作用。这意味着团队成员应该鼓励开放的沟通、合作和相互支持,以促进项目的成功。

可工作的软件高于面面俱到的文档: 敏捷方法鼓励快速交付可工作的软件,并通过迭代和增量的方式不断改进和完善。虽然文档在项目中仍然有其重要性,但软件的实际功能和价值更加重要。重点是实际交付可用的软件,以便及早获取用户的反馈和验证。

客户合作高于合同谈判: 敏捷方法鼓励开展与客户的密切合作。通过与客户的直接互动,团队可以更好地理解客户的需求和期望,并及时适应变化。与客户合作,建立信任和合作关系,比严格按照合同要求执行更有助于项目的成功。

响应变化高于遵循计划: 敏捷方法接受需求和环境的变化是正常且不可避免的。团队应该具备灵活性和适应能力,能够及时响应变化,并根据新的情况做出调整。灵活性和快速响应能够帮助团队更好地满足客户需求并提高项目的成功率。

敏捷方法帮助团队更好地应对变化,提供更有价值的软件,并与客户建立密切的合作关系。灵活性和适应能力是成功的关键,而敏捷软件开发宣言为我们提供了一个指导方向和原则。

16. 极限编程过程
#

思考:XP有哪些关键性的活动?在活动执行过程中,它强调什么?遵循什么?鼓励什么?如设计时,XP遵循KIS原则,对设计方案进行阐述;又如,设计时,XP鼓励使用CRC进行必要的设计,它还强调重构;再如,设计遇到困难时,XP建议给出Spike解决方案等等

Beck为实施XP的全部工作定义了五个有重要意义的要素,即沟通、简明、反馈、鼓励和尊重。这五个要素中的每一个都是完成特定的XP活动、动作和任务的驱动力。

XP强调快速迭代、灵活性和高度的协作。以下是XP中的一些关键性活动及强调、遵循和鼓励的原则:

用户故事(User Stories):XP使用用户故事来捕捉和表达系统的需求。用户故事是简洁的描述,强调从用户的角度描述功能和价值。XP鼓励团队与用户密切合作,确保对用户需求的准确理解。

小规模发布(Small Releases):XP强调快速交付可工作的软件版本,以获取用户的及早反馈。XP鼓励团队将开发工作切分为小的、可交付的增量,每个增量都是一个完整的软件版本。

测试驱动开发(Test-Driven Development,TDD):XP倡导在编写代码之前先编写测试。测试驱动开发的过程中,先编写失败的测试用例,然后编写代码使测试通过。这强调编写可测试的代码,并确保代码的正确性和可维护性。

集体代码所有权(Collective Code Ownership):XP鼓励团队成员共同拥有代码,并相互审查和修改彼此的代码。这鼓励团队合作、相互学习和共享知识。

持续集成(Continuous Integration):XP强调团队成员频繁地将代码集成到主代码库中。通过持续集成,团队可以及早发现和解决集成问题,确保软件始终处于可工作状态。

简单设计(Simple Design):XP遵循"保持简单"(Keep It Simple,KIS)原则,强调简单和可理解的设计。XP鼓励团队避免过度设计,保持设计的灵活性和可演化性,并根据实际需求进行必要的重构。

重构(Refactoring):XP强调持续改进代码质量和设计。团队被鼓励在不改变软件外部行为的前提下,通过重构改善代码的结构、可读性和可维护性。

点式估算(Planning Game):XP使用点式估算来估计和安排开发任务。团队根据任务的相对复杂度和工作量给出估算点数,以更好地规划工作和控制进度。

探索性编程(Exploratory Programming):XP鼓励团队成员通过实验和探索来解决复杂的问题。当面临难题时,XP建议采用Spike解决方案,进行快速原型开发和实验,以获取更多的洞察和理解。

这些是XP中的一些关键活动和原则,XP通过强调协作、快速迭代和持续改进,旨在提高软件开发的灵活性和质量。

17. 阅读下列材料,结合课程所学,谈一谈你从中获取的信息以及你的想法
#

Plan the solution. Now you understand the problem (or so you think) and you can’t wait to begin coding. Before you do, slow down just a bit and do a little design: . Have you seen similar problems before? Are there patterns that are recognizable in a potential solution? Is there existing software that implements the data, functions, and features that are required? Has a similar problem been solved? If so, are elements of the solution reusable? . Can subproblems be defined? If so, are solutions readily apparent for the sub problems? .Can you represent a solution in a manner that leads to effective implementation.?Can a design model be created?

从这段材料中,我获取到以下信息和想法:

  1. 计划解决方案:在开始编码之前,应该进行适当的设计和规划。这强调了在软件开发过程中的设计阶段的重要性。仅仅对问题的理解还不足以开始编码,需要花时间进行设计,思考可能的解决方案。
  2. 寻找相似问题和模式:在解决问题之前,要考虑是否曾经遇到过类似的问题,以及是否存在可识别的模式可以应用于潜在的解决方案。这强调了软件开发中的经验和复用的重要性。通过寻找现有的解决方案或已有的软件,可以节省时间和资源,提高开发效率。
  3. 划分子问题:问题可以划分为更小的子问题,这些子问题可能更容易解决。这提示了分解和模块化的思想。将大问题拆分为小的、可管理的子问题,可以更好地理解和解决问题。
  4. 有效的实施和设计模型:问题的解决方案需要以一种可实施的方式进行表示。这强调了设计模型的重要性。通过合适的设计模型,可以更好地实现和落地解决方案。

综上所述,这段材料强调了在软件开发过程中的设计阶段的重要性,并提供了一些思考问题和解决方案的指导。它提醒我们要在开始编码之前,花时间进行规划和设计,寻找相似问题和可复用的解决方案,划分子问题并建立有效的设计模型。这些思想和原则对于提高软件开发的效率和质量很有帮助。

18. 需求功能职责
#

阅读教材,理解“需求工程”的7项职能,然后填空:

Seven distinct requirements engineering functions—(),(),(), (),  () , ()and()—are conducted by members of the software team.

Inception Elicitation Elaboration Negotiation Specification Validation Requirements Management

19. stakeholder
#

思考:利益相关者是指?关于“利益相关者”,对于理解需求的意义是?

利益相关者是在软件项目中存在利害关系的人,任何受到系统影响或对系统开发产生影响的人,都是利益相关者。利益相关者可以包括项目发起人、用户、客户、管理层、开发团队、合作伙伴、竞争对手、政府机构等。

一般存在两组主要的利益相关者:

  • 客户(用户或系统所有者)
  • 开发者(分析员、设计员、程序员)

理解利益相关者对于理解需求非常重要。他们的参与可以帮助团队捕捉全面的需求视角,确定优先级和权衡决策,提供反馈和验证需求,并建立合作关系和共识。通过与利益相关者密切合作,团队可以更好地满足他们的需求,提高软件项目的成功度。

20. 概念辨析
#

思考:客户与最终用户的区别

  1. 客户(Customer):客户是指与软件开发项目直接合作并购买产品或服务的组织或个人。客户通常是项目的发起人或资助者,他们与开发团队合作确定项目的目标和需求,并提供资金和资源支持。客户可能包括企业、机构、组织等。他们代表了最终用户的利益,对项目的成功和最终交付的结果负有责任。
  2. 最终用户(End User):最终用户是指最终使用软件产品或服务的实际用户。他们是软件的最终受益者,使用软件来满足自己的需求和目标。最终用户可能是企业的员工、系统的操作者、网站的访问者、移动应用的用户等。他们使用软件来完成特定的任务、获得特定的功能或者享受特定的服务。

总的来说,客户是购买软件产品或服务的组织或个人,他们与开发团队合作确定需求,并提供项目的支持和资金。最终用户是实际使用软件的人群,他们直接与软件产品或服务进行交互,使用软件来满足自己的需求。客户代表了最终用户的利益,因此在软件开发过程中需要考虑和平衡两者的需求和期望。

21. 识别利益相关者,并向其收集信息
#

请完成:

1.找出A公司开发“公交站牌项目”的利益相关者

2.调研访谈前,请为其准备一张问题清单

  1. A公司开发“公交站牌项目”的利益相关者:
    • 公交集团:作为项目的发起者和资助者,公交集团对项目的成功和实现实时报站功能有直接的利益关系。
    • B公司:作为提供实时公交到站信息的服务器提供商,B公司对项目的成功和数据的准确性有直接的利益关系。
    • 公交站点管理人员:负责站牌的安装、维护和操作,对于实时报站功能和公告信息的展示有直接的关注。
    • 公交乘客:作为最终用户,他们将受益于实时报站功能和公告信息的提供。
  2. 调研访谈问题清单:
    • 对于公交集团:
      1. 你们对于“公交站牌项目”的期望和目标是什么?
      2. 你们对于实时报站功能和公告信息的展示有什么具体要求?
      3. 在项目实施过程中,你们希望获得怎样的沟通和参与机制?
    • 对于B公司:
      1. 你们提供的实时公交到站信息的可用性和准确性如何保证?
      2. 在集成你们的服务器时,需要注意哪些技术规格和安全要求?
      3. 你们对于A公司开发的“公交站牌项目”有什么建议或要求?
      4. 成本价格如何确定?
    • 对于公交站点管理人员:
      1. 你们对于实时报站功能和公告信息的展示有什么具体需求和意见?
      2. 在站牌的安装和维护过程中,有哪些特殊考虑或技术要求?
    • 对于公交乘客:
      1. 你们对于实时报站功能和公告信息的提供有什么期望和需求?
      2. 你们希望在公交站牌上看到哪些信息或功能,希望何种显示策略模式?

22. 用户访谈,获取“用户故事”
#

阅读下列材料,仿照“案例一,着火了的仓库“和”案例二,Alice报告了一个Bug”用户故事:路面坑洼被修复了!请详细描述使用软件的情景。

用户故事名称:修复路面坑洼

用户故事描述: 作为一位城市居民,我希望能够使用基于Web的跟踪和修补路面坑洼系统(PHTRS)报告路面坑洼,以便能够及时修复路面坑洼问题。

用户故事情景:

  1. 我打开PHTRS的Web站点,并登录我的账户。
  2. 在Web界面上,我看到一个报告路面坑洼的选项。我点击该选项以进入报告界面。
  3. 在报告界面,我填写路面坑洼的街道地址,选择坑洼的大小(从比例1到10),指定坑洼的位置(中央、路边等),并根据街道地址确定所属的地区。
  4. 我选择修补优先级,该优先级基于坑洼的大小。我希望较大的坑洼能够优先得到修补。
  5. 在完成报告信息的填写后,我点击提交按钮,将路面坑洼信息保存到PHTRS系统中。
  6. 系统为我生成一个唯一的标识号,用于跟踪和识别该路面坑洼的修补工作订单。
  7. 我可以随时登录系统,使用该标识号查询坑洼的修复状态和进展情况。
  8. 维修组收到系统分配的工作订单后,他们根据工作订单中的信息,包括坑洼的位置和大小、分配的人员数量、所需的设备等进行修复工作。
  9. 在修复过程中,维修组会及时更新工作订单中的状态,标记为“正在处理中”。
  10. 当修复完成后,维修组会将工作订单标记为“已修复”,并记录使用的填充材料数量、修复耗时、修复成本等信息。
  11. 系统会生成一份损失文件,记录该坑洼所造成的损失报告信息,包括公民的姓名、地址、电话号码、损失类型和损失金额等。
  12. 我可以在系统中查看该损失文件,了解坑洼修复对公民造成的损失和影响。

23. 质量功能部署
#

QFD对软件开发的影响:

  1. 确保满足客户需求:QFD通过收集、分析和转化客户的需求,确保软件开发过程中的设计和实现能够满足客户的期望。这有助于确保软件产品的质量和用户满意度。
  2. 提高需求管理:QFD通过建立需求与功能之间的关联,帮助开发团队更好地理解和管理需求。它提供了一种系统化的方法,确保需求的准确性、一致性和可追溯性,避免需求漏掉或误解。
  3. 促进跨部门协作:QFD通常涉及到多个团队或部门的合作,包括业务部门、开发团队、测试团队等。通过QFD,这些团队可以共同参与需求分析和转化的过程,促进跨部门的协作和沟通,确保各方的利益和关注点得到充分考虑。
  4. 强调质量导向:QFD将质量视为核心目标,并将其融入到整个软件开发过程中。通过QFD的质量功能转化和质量特性分析,开发团队能够有针对性地制定质量控制策略和测试计划,以确保软件产品的质量达到或超出客户的期望。
  5. 促进持续改进:QFD强调对客户需求和反馈的持续关注和改进。通过不断迭代和反馈循环,开发团队可以及时调整和改进软件开发过程,以满足客户的不断变化的需求和市场竞争。

总之,QFD在软件开发中可以帮助团队更好地理解和转化客户需求,确保软件产品的质量和用户满意度。它促进了团队之间的协作和沟通,强调质量导向和持续改进,从而提高软件开发过程的效率和质量。

24. 上下文建模
#

首先需要从软件所在环境的背景信息中识别上下文对象。它们是与软件交互的现实的对象以及其它子系统,识别对象时需要从文字信息中提取名词或名词性短语。接下来要描述上下文对象的属性,属性分为两种:第一种是关于对象特征的属性,以描述性内容出现;另一种是对象之间的关系属性,包括关联、聚合、组合等。通过关注描述中的动词,明确过程中对象之间的关系。接着需要根据软硬件情况定义接口规范和交互行为,最后完成评审。上下文环境可以用可视化的方式进行建模。

25.
#

image-20230623222225263

26.
#

用例名称: Withdraw Funds

用例描述: 该用例描述了ATM客户从其账户中取款的过程。

执行者: ATM客户

前置条件: ATM客户已经通过验证,并且账户中有足够的余额可供取款。

后置条件: 资金成功从ATM客户的账户中取款,并且账户余额相应减少。

主过程描述:

  1. ATM客户选择取款功能。
  2. 系统验证客户的PIN码。
  3. ATM客户输入要取款的金额。
  4. 系统检查账户余额是否足够。
  5. 如果账户余额足够,系统更新账户余额,并将相应金额支付给ATM客户。

**无障碍描述:**ATM客户请求取款功能 - 系统验证客户PIN码 - ATM客户请求输入取款金额 - 系统检查账户余额 - 系统更新账户余额 - 系统支付取款金额给ATM客户

**分支过程描述:**如果账户余额不足,系统拒绝取款请求,并向ATM客户显示相应的错误信息。

**异常过程描述:**如果系统无法验证客户的PIN码,系统拒绝取款请求,并向ATM客户显示相应的错误信息。

**业务规则:**取款金额必须小于或等于账户余额。

**涉及的业务实体:**ATM客户的账户


用例名称: Query Account

用例描述: 该用例描述了ATM客户查询其账户余额的过程。

执行者: ATM客户

前置条件: ATM客户已经通过验证。

后置条件: ATM客户能够查看其账户的余额信息。

主过程描述:

  1. ATM客户选择查询账户功能。
  2. 系统验证客户的PIN码。
  3. 系统显示账户余额给ATM客户。

无障碍描述:

ATM客户请求查询账户功能 - 系统验证客户PIN码 - 系统显示账户余额给ATM客户

分支过程描述:

异常过程描述:

如果系统无法验证客户的PIN码,系统拒绝查询请求,并向ATM客户显示相应的错误信息。

**业务规则:**无

**涉及的业务实体:**ATM客户的账户


用例名称: Transfer Funds

用例描述: 该用例描述了ATM客户在不同账户之间转账的过程。

执行者: ATM客户

前置条件: ATM客户已经通过验证,并且源账户中有足够的余额可供转账。

后置条件: 资金成功从源账户转移到目标账户,并且相应账户余额发生变化。

主过程描述:

  1. ATM客户选择转账功能。
  2. 系统验证客户的PIN码。
  3. ATM客户输入转账金额和目标账户信息。
  4. 系统检查源账户余额是否足够。
  5. 如果源账户余额足够,系统更新源账户和目标账户的余额。

**无障碍描述:**ATM客户请求转账功能 - 系统验证客户PIN码 - ATM客户输入转账金额和目标账户信息 - 系统检查源账户余额 - 系统更新源账户和目标账户余额

分支过程描述:

如果源账户余额不足,系统拒绝转账请求,并向ATM客户显示相应的错误信息。

异常过程描述:

如果系统无法验证客户的PIN码,系统拒绝转账请求,并向ATM客户显示相应的错误信息。

**业务规则:**转账金额必须小于或等于源账户余额。

**涉及的业务实体:**ATM客户的源账户和目标账户

27.
#

image-20230623222626611

28.
#

image-20230623223145189

29.
#

向利益相关者收集需求的手段可以包括以下几种:

  1. 面对面访谈:与利益相关者进行面对面的访谈,直接交流和收集他们的需求和期望。
  2. 集体讨论:组织利益相关者之间的集体讨论,促进彼此之间的意见交流和共享需求信息。
  3. 问卷调查:设计问卷并发送给利益相关者,以收集他们的意见和需求。
  4. 观察和实地调研:观察利益相关者在实际环境中的行为和需求,并进行记录和分析。
  5. 原型演示:通过展示原型或模型让利益相关者亲自体验,并提供反馈和需求意见。

从收集的一手需求信息中导出功能性需求和非功能性需求的过程如下:

  1. 识别功能性需求:关注利益相关者对系统所期望的具体功能和行为,从需求信息中提取涉及系统功能的要求和规范。例如,识别出需要系统能够扫描商品、计算总价、接受不同支付方式等功能性需求。
  2. 识别非功能性需求:关注利益相关者对系统性能、安全性、可用性等方面的要求,从需求信息中提取涉及系统属性和约束的需求。例如,识别出需要系统具有良好的易用性、能够快速响应用户操作、保护用户隐私等非功能性需求。

针对给定的材料,可以识别出以下非功能性需求:

非功能性需求:Usability(可用性) 该需求描述了用户对系统易用性的要求,包括以下方面:

  • 用户能够方便地扫描所购商品。
  • 营业员能够友好地与用户进行交流和询问。
  • 用户能够方便地进行支付操作,支持多种支付方式。

识别过程: 从材料中可以看到用户使用故事超市购物的经历,其中描述了用户与系统的交互过程和用户体验。通过分析这些描述,我们可以发现用户对系统的易用性有一些期望,例如方便的商品扫描、友好的交流和支付方式的多样性。这些期望属于非功能性需求中的可用性需求。

总结导出非功能性需求的方法:

  1. 分析用户故事和使用场景:仔细分析用户故事和使用场景,识别出用户对系统性能、可靠性、安全性、可用性等方面的要求。
  2. 倾听利益相关者的反馈:与利益相关者进行沟通和交流,听取他们对系统的期望和关注点,从中获取非功能性需求信息。
  3. 观察用户行为和环境:观察用户在实际环境中的行为和操作习惯,注意他们对系统的反应和体验,从中推断出非功能性需求。
  4. 参考相关标准和指南:参考行业标准和设计指南,了解和应用其中的非功能性需求原则和准则。
  5. 使用原型和模型:通过展示原型和模型,让利益相关者体验系统并提供反馈,从中获取非功能性需求。

30.
#

image-20230623223531121

从给定的材料中,可以识别出以下功能性需求:

  1. 新建Bug:测试人员可以在缺陷管理系统中创建新的Bug,将问题描述、关联信息等填写并提交。
  2. 分配Bug:分配人员负责将新建的Bug分配给相应的开发人员,以便其解决。
  3. 解决Bug:开发人员负责解决分配给他们的Bug,进行修复并向检查人员报告。
  4. 检查Bug:检查人员负责检查解决后的Bug,决定是否关闭,并做出相应的操作。

这些功能性需求是通过分析材料中描述的参与者和他们在缺陷管理系统中的操作得出的。

导出功能性需求的方法总结如下:

  1. 分析参与者和其职责:识别系统中的各个参与者,了解他们在系统中的角色和职责。
  2. 理解操作流程:分析参与者之间的交互和操作流程,关注他们的输入、处理和输出,以识别出系统所需的功能性需求。
  3. 挖掘关键词和动作:仔细阅读需求材料,关注其中的关键词和动作,如新建、分配、解决、检查等,以确定涉及的功能性需求。
  4. 利用用例分析:将材料中描述的操作和参与者组织成用例,通过用例分析来识别功能性需求。
  5. 借鉴领域知识和行业标准:参考相关的领域知识和行业标准,了解常见的功能性需求模式和规范,以辅助需求识别的过程。

31.
#

image-20230623224155527

功能性需求:

实地巡逻干事能够发现并报告紧急事件,突发事件中心调度能针对报告的突发事件给出相应的解决方法以及ETA,实地巡逻干事能够请求医护人员,实地巡逻干事能确认突发事件中心调度给出的ETA。

导出功能性需求并建模生成用例图的方法:

  • 识别用例
  • 完成上下文领域建模
  • 以用例角度对用例进行建模,生成用例图

32.
#

用例名称:电影票预定

前置条件:顾客向电影院员工提出需求

0、 订票系统主页启动

1、 电影院员工进入电影院订票系统

2、 电影院订票系统响应员工的进入请求

3、 员工输入客户要求的场次时间

4、 系统反馈有无场次

5、 员工输入顾客要求的座位

6、 系统反馈有无座位

7、 员工观测到订票成功

后置条件:系统返回主页

33.
#

image-20230623224934561
  1. 确定系统的活动范围:确定要建模的系统或过程的边界和范围,明确需要呈现的活动。
  2. 确定活动的起点和终点:确定活动图的起点和终点,即系统开始执行某项活动的地方以及完成该活动后系统所处的状态。
  3. 确定活动的顺序和条件:确定各个活动之间的顺序关系和条件约束,即哪些活动在何种条件下可以执行,以及它们之间的执行顺序。
  4. 识别活动的动作和决策点:将活动细分为具体的动作和决策点,动作表示系统执行的具体步骤,决策点表示根据某些条件进行选择的地方。
  5. 绘制活动图:使用活动图的符号和连接线,根据上述确定的活动顺序、条件、动作和决策点,绘制出活动图。
  6. 完善活动图:添加必要的注释和说明,使活动图更加清晰易懂。

34.
#

Checkout GUI将顾客输入的借阅文档的索书号传送到LIS Controller中,由Controller委托Book Manager进行查询,Book Manager通过Book Db Manager完成数据库查询,将结果转化保存为Book信息,传递给Controller,Controller再将checkout内容传递给GUI显示。

(我写完才发现后面题干涉及的顺序图里有完善的设计,不改了)

运用GRASP详述非简单步骤的方法:

1、明确上下文领域,了解系统中涉及的业务和概念;

2、应用高内聚低耦合的设计原则;

3、根据系统需求识别系统中的参与者以及它们的职责;

4、最后进行验证以及迭代,确保涉及满足系统要求和质量标准

35.
#

image-20230623225353554
  1. 确定参与者和系统边界:确定需要建模的系统或过程的参与者和系统边界。
  2. 识别交互对象:确定系统与外部实体或参与者之间的交互对象,包括系统内部的模块、组件或对象。
  3. 确定顺序关系:确定各个交互对象之间的顺序关系,即哪些对象在何种条件下进行交互。
  4. 识别消息和操作:确定交互对象之间发送的消息和执行的操作,包括方法调用、请求和响应等。
  5. 确定消息的顺序和时机:确定消息的发送顺序和时机,即消息在交互对象之间的传递顺序和触发时机。
  6. 绘制顺序图:使用顺序图的符号和连接线,根据上述确定的交互对象、顺序关系、消息和操作,绘制出顺序图。
  7. 完善顺序图:添加必要的注释和说明,使顺序图更加清晰易懂。

36.
#

问题:DB中setavailable原本是false的记录也会被返回:“Checkout successful”

​ 在新建loan之前,先判断DB中相应书籍对应的setavailable是否为false,如果是则直接Msg =“Document not available”。

37.
#

LoginController内部控制细节过多,耦合程度高。LoginController直接参与控制。

不解决,难以增添新功能,验证过程不安全

OCP原则

// 伪代码表示
// 不想画图qwq
class LoginController {
  private PasswordValidator passwordValidator;
  private PasswordRetriever passwordRetriever;
  
  public void login(String id, String pwd) {
    String storedPwd = passwordRetriever.getPassword(id);
    boolean isValid = passwordValidator.verify(pwd, storedPwd);
    ...
  }
}

class PasswordValidator {
  public boolean verify(String enteredPwd, String storedPwd) {
    ...
  }
}

class PasswordRetriever {
  public String getPassword(String id) {
    ...
  }
}

38.
#

image-20230623230655240

运用GRASP详述非简单步骤的方法:1、明确上下文领域,了解系统中涉及的业务和概念;2、应用高内聚低耦合的设计原则;3、根据系统需求识别系统中的参与者以及它们的职责;4、最后进行验证以及迭代,确保涉及满足系统要求和质量标准

生成通信图:先画出流程图,以及状态图;2、然后根据流程图和状态图确定通信图的通信对象以,通信目标,通信流;3、画出通信图的简图;4、根据软件背景对简图进行优化,完善。

39.
#

image-20230623231043202

40.
#

image-20230623231404748

1)从顺序图(时序图)或交互图中获取类的方法可以按照以下步骤进行:

  • 观察参与者(actors):识别顺序图中的参与者,这些参与者通常表示系统的外部实体或角色。每个参与者可能对应一个类或多个类。
  • 观察消息传递:注意顺序图中的消息传递,包括方法调用、请求和响应等。通过分析消息传递可以识别出系统中的类和它们之间的交互关系。
  • 识别类:根据观察到的参与者和消息传递,识别出类。类可以是系统中的实体对象、服务对象或控制对象。注意识别出类的属性和方法,并确定它们之间的关系。
  • 确定关系:根据消息传递的方式和顺序,确定类之间的关系,如关联、依赖、继承、实现等。

2)代码映射的方法是将类图转换为具体编程语言的代码实现。以下是一般的代码映射方法:

  • 类和对象映射:将类图中的类映射为具体编程语言的类或对象。根据编程语言的语法和规范,创建相应的类和对象,并定义属性和方法。
  • 属性映射:将类图中的属性映射为具体编程语言的变量或属性。根据属性的类型和访问控制,使用合适的语法和命名约定在类中声明属性。
  • 方法映射:将类图中的方法映射为具体编程语言的方法或函数。根据方法的参数、返回类型和访问控制,使用合适的语法和命名约定在类中定义方法。
  • 关系映射:将类图中的关系映射为具体编程语言的关系,如关联、继承、依赖等。根据编程语言的特性和语法,使用适当的关键字或符号表示类之间的关系。

41.
#

image-20230623231521989

(1) 从通信图等交互图中获取类的方法:

  • 识别角色和参与者:阅读通信图或其他交互图,识别出涉及的角色和参与者。角色通常表示系统的不同组成部分或模块,而参与者表示与系统进行交互的外部实体。
  • 识别消息和方法调用:分析通信图中的消息和方法调用,注意消息的发送者和接收者以及它们之间的交互关系。这些消息和方法调用可以提示可能涉及的类和它们之间的关系。
  • 识别类和对象:根据角色和参与者以及消息和方法调用,识别可能的类和对象。考虑类的责任和行为,并确定它们之间的关联关系和依赖关系。
  • 确定属性和方法:根据类的责任和行为,确定类应该具有的属性和方法。属性表示类的状态和特征,方法表示类的行为和功能。
  • 优化和重构:根据实际需求和设计原则,对识别的类进行优化和重构,确保其符合设计要求和良好的设计原则。

(2) 代码映射的方法:

  • 根据类的属性和方法,在目标编程语言中创建类和对象。使用合适的语法和约定来定义类和对象,并为属性和方法添加适当的访问修饰符。
  • 将类之间的关联关系映射为目标编程语言的关联关系,如组合、聚合、继承等。使用合适的语法和关键字来表示类之间的关系,并确保关系符合设计要求。
  • 实现类的方法体,根据方法的功能和行为编写相应的代码。考虑方法的输入参数和返回值,并根据需求实现适当的逻辑和算法。
  • 检查代码的正确性和一致性,确保所有的类、属性、方法和关联关系都正确地映射为目标编程语言的代码。
  • 进行测试和调试,验证代码的功能和正确性。根据实际需求编写测试用例,并使用合适的测试框架进行测试和调试,确保代码的质量和可靠性。
  • 根据需要进行优化和重构,根据实际性能和可维护性要求对代码进行优化和重构。使用合适的技术和方法,改进代码的效率和可读性,提高代码的可维护性和可扩展性。

42.
#

类名 职责 协作者
电影院订票系统 保存座位预订,查询场次,保存顾客信息 剧场、场次、座位、顾客
剧场 提供座位预订情况,返回座位信息 电影院订票系统、场次
座位 保存座位状态(已预订或可用),提供座位信息 剧场、电影院订票系统
顾客 提供顾客信息(电话号码等),与座位预订相关 电影院订票系统
场次 保存电影、日期、时间等场次信息,提供场次细节 电影院订票系统、剧场
电影 保存电影名称和其他相关信息 场次
日期 保存日期信息 场次
时间 保存时间信息 场次

CRC模型建立方法:

  1. 确定系统中的参与者(类、对象或角色)。
  2. 为每个参与者创建一个CRC卡,并在卡片上写下参与者的名称。
  3. 确定每个参与者应该承担的职责。
  4. 在每个CRC卡的职责栏中列出确定的职责。
  5. 确定与每个参与者合作的其他参与者。
  6. 在每个CRC卡的协作者栏中列出与该参与者合作的其他参与者。
  7. 审查和调整CRC模型,确保职责和协作者的分配合理。
  8. 在场景模拟中识别额外的职责和协作者,并进行记录和更新。

43.
#

  1. 需求描述:对系统需求的描述,可以是基于场景、类、行为或流程的方式。
    • 场景驱动:使用具体的场景来描述系统的功能和用户交互。
    • 类驱动:识别系统中的类、属性和关系,以及它们之间的行为和协作。
    • 行为驱动:描述系统的行为和交互方式,通常使用用例和活动图等工具。
    • 流程驱动:基于业务流程或工作流程来描述系统的功能和操作步骤。
  2. 需求模型向设计模型的转换关系是将需求模型中的元素转化为设计模型中的元素,以便于实现和构建系统。这涉及到从行为和结构两个方面进行思考:
    1. 从行为方面思考:将需求模型中的行为描述转换为设计模型中的组件、接口和流程等元素。
      • 场景转换为组件:将场景中的功能和行为转化为系统的组件和模块。
      • 类和行为转换为接口:将类和行为描述转换为接口定义,定义模块之间的协作关系。
      • 流程转换为流程图或状态图:将流程描述转换为系统的流程图或状态图,描述系统的操作流程和状态转换。
    2. 从结构方面思考:将需求模型中的结构描述转换为设计模型中的组件、接口和数据/类等元素。
      • 类转换为组件:将类和对象转换为系统的组件,定义组件之间的关系和接口。
      • 数据转换为类和数据结构:将数据描述转换为类和数据结构,定义系统的数据模型。
      • 架构转换为系统架构:将需求模型中的架构描述转换为系统的整体架构,包括分层结构、模块划分等。

44.
#

建立E-R图的一般步骤:

  1. 确定实体:识别系统中的关键实体,它们是建模的主要对象或概念。
    1. 例如,对于一个学生信息管理系统,实体可能包括学生、课程、教师等。
  2. 确定实体的属性:为每个实体确定其相关的属性。属性是描述实体特征的属性或字段。
    1. 例如,学生实体的属性可能包括学生ID、姓名、年龄等。
  3. 确定实体之间的关系:确定实体之间的关系和连接方式。关系可以是一对一、一对多或多对多的。可以部分参与或完全参与。
    1. 例如,学生和课程之间的关系可以是一个学生可以注册多门课程,而一门课程可以有多个学生注册。
  4. 描述关系的属性:对于具有关系的实体,确定关系本身的属性。
    1. 例如,学生和课程之间的关系可能有注册日期、成绩等属性。
  5. 绘制E-R图:使用适当的符号和符号表示法,将实体、属性和关系表示为图形元素,并使用线条连接它们。通常,实体用矩形框表示,属性用椭圆形表示,关系用菱形表示。
  6. 完善E-R图:确保E-R图的完整性和准确性。检查图中是否遗漏了任何实体、属性或关系,并确保关系的类型和基数正确表示。
  7. 优化E-R图:根据需要进行优化和调整。根据实际需求和设计目标,可能需要修改实体、属性或关系,以使E-R图更准确和有效。

45.
#

image-20230623212810292

(1) 如何得到某对象的状态迁移表: 要得到某对象的状态迁移表,可以按照以下步骤进行:

  1. 确定对象的状态:分析对象在系统中可能具有的不同状态,将其列举出来。
  2. 确定触发条件:确定导致状态转换发生的触发条件或事件,例如用户的输入、系统的响应等。
  3. 填写状态迁移表:根据状态迁移图,填写状态迁移表。表格中的行表示对象的不同状态,列表示触发条件,表格中的每个单元格表示从一个状态到另一个状态的转换条件。

(2) 总结状态建模的方法: 状态建模是一种对系统或对象的状态进行描述和建模的方法。以下是状态建模的一般步骤:

  1. 确定对象:确定需要进行状态建模的对象或系统。
  2. 确定状态:分析对象在系统中可能具有的不同状态,将其列举出来。
  3. 确定状态转换条件:确定导致状态转换发生的触发条件或事件,例如用户的输入、系统的响应等。
  4. 绘制状态图:根据对象的状态和状态转换条件,绘制状态图。状态图由状态节点和状态转换边组成,状态节点表示对象的不同状态,状态转换边表示状态之间的转换条件。
  5. 分析状态转换逻辑:分析状态之间的转换逻辑,确定在不同状态下对象的行为和状态转换条件。
  6. 验证和修改:对绘制的状态图进行验证,并根据需要进行修改和优化,确保状态图准确地描述了对象的状态和状态转换。

(3) 从状态图中获取类的方法: 从状态图中获取类的方法主要包括以下步骤:

  1. 确定类的状态:根据状态图中的状态节点,确定需要建立的类和类的不同状态。
  2. 确定类的属性:根据状态图中的状态节点和状态转换边,确定类的属性,属性可以表示类在不同状态下的特征和状态转换所需的数据。
  3. 确定类的方法:根据状态图中的状态转换边,确定类的方法,方法可以表示类在不同状态下的行为和状态转换的操作。
  4. 考虑状态模式:如果状态图中的状态较多且复杂,可以考虑使用状态模式进行设计,将每个状态抽象为一个独立的类,并定义统一的接口。

(4) 如何将状态图映射为代码: 将状态图映射为代码的过程可以通过以下步骤完成:

  1. 创建类:根据状态图中的状态节点,创建表示不同状态的类。每个类表示对象的一个具体状态。
  2. 定义类的属性:根据状态图中的状态节点和状态转换边,定义类的属性,属性可以表示类在不同状态下的特征和状态转换所需的数据。
  3. 定义类的方法:根据状态图中的状态转换边,定义类的方法,方法可以表示类在不同状态下的行为和状态转换的操作。
  4. 实现状态转换:在类的方法中,根据状态图中的状态转换条件,实现状态之间的转换逻辑。可以使用条件语句、状态模式等方式来实现状态转换。
  5. 客户端代码:编写客户端代码,创建对象并调用相应的方法来触发状态转换。

46.
#

image-20230623213648709

基于需求/设计的文本陈述建立状态模型可以遵循以下步骤:

  1. 理解需求/设计文本:仔细阅读给定的需求/设计文本,确保对系统或组件的行为和状态转换有一个清晰的理解。
  2. 确定关键对象:确定与需求/设计相关的关键对象,这些对象通常是系统或组件的核心元素。
  3. 确定状态:识别对象可能具有的不同状态。状态是对象在特定条件下的行为和属性的集合。
  4. 确定状态之间的转换:确定对象在不同状态之间的转换条件和触发事件。这些条件可以是特定的操作、事件或条件的发生。
  5. 绘制状态图:使用状态图表示对象的状态和状态之间的转换关系。状态图是一种图形化表示,它显示对象的状态作为节点,状态之间的转换作为箭头。
  6. 添加行为和动作:对于每个状态,确定与之关联的行为和动作。行为是对象在特定状态下执行的操作,动作是状态转换的触发器。
  7. 完善状态模型:根据需要进一步完善状态模型,例如添加约束、条件和特殊情况。

47.
#

image-20230623205723891

语法匹配器作为控制器不应亲自处理系统事件,其职责应是创建软件内部对象并协调它们处理系统事件。

利用Switch进行状态判断和转移,是典型的控制语句高耦合模式。

状态图模型是一种控制耦合的设计方案;运用GOF的”状态模式”解耦——结构的构成元素由“活动”或“状态”,改变为“对象”,关系也由“顺序”或“转移”,改变为“关联”、“依赖”、“实现”或“泛化”,得到结构更加优秀的软件。

GOF中的"状态模式"是一种行为型设计模式,它用于在对象内部状态发生变化时改变其行为,而不需要直接依赖于具体的状态。状态模式的目标是实现状态与行为之间的解耦,以便可以轻松地添加新的状态或修改现有状态的行为,而不会影响到其他部分的代码。

在状态模式中,对象的行为取决于其当前的状态对象,而不是由对象自身控制。它通过将每个具体状态封装为一个独立的类,并且这些状态类都实现同一个抽象状态类(或接口)来实现解耦。对象内部维护一个对当前状态对象的引用,根据当前状态对象的不同来执行相应的行为。

通过使用状态模式,可以将复杂的条件语句转换为对象间的消息传递,从而提高了代码的可维护性和扩展性。当新增一种状态时,只需新增一个状态类,并在上下文对象中设置相应的状态切换逻辑,而无需修改其他已有代码。

重构之后:

image-20230623205923267

总结

  1. 从状态图导出类图的方法:
  • 首先,确定状态图中的状态和状态之间的转换关系。状态表示对象在不同状态下的行为和属性,转换关系表示对象在不同状态之间的切换条件和动作。
  • 根据状态图中的状态,将每个状态抽象为一个类,该类包含与该状态相关的行为和属性。可以使用抽象类或接口来定义状态类。
  • 根据状态图中的转换关系,确定状态之间的切换条件和动作。可以在状态类中定义方法来处理状态之间的切换逻辑。
  • 根据状态图中的状态转换,将状态之间的关系表示为类之间的关联关系或方法调用关系。这可以通过在类图中使用关联线或方法调用箭头来表示。
  • 根据需要,可以添加其他类和接口来实现状态模式所需的上下文类和其他支持类。
  1. 应用设计模式(状态模式)进行重构的过程:
  • 首先,分析现有代码中的状态逻辑,判断是否存在复杂的条件语句用于处理对象的不同状态下的行为。
  • 根据状态逻辑,确定对象的各个状态以及状态之间的转换关系。
  • 根据状态模式的结构,创建状态类和上下文类,将现有代码中与状态相关的行为和属性分别封装到对应的状态类中。
  • 在上下文类中维护一个对当前状态对象的引用,并定义方法来触发状态之间的转换。
  • 重构现有代码,将原来的条件语句替换为状态模式中的状态切换逻辑,并通过调用当前状态对象的方法来执行相应的行为。
  • 测试和验证重构后的代码,确保状态切换和行为执行的正确性。
  1. 代码映射技术:

代码映射是将设计模式中的概念映射到具体编程语言中的实现技术。对于状态模式的代码映射,可以采用以下技术:

  • 使用类和接口:根据状态图中的状态和转换关系,创建对应的状态类和上下文类。可以使用抽象类或接口来定义状态类,以及上下文类中对状态对象的引用和状态切换的方法。
  • 多态性:通过多态性实现不同状态下的行为的动态绑定。每个具体的状态类都实现了抽象状态类或接口中定义的方法,并根据自身的状态进行具体的实现。
  • 方法调用:根据状态之间的转换关系,在上下文类中调用当前状态对象的方法来执行相应的行为。状态切换时,通过修改当前状态对象的引用来实现状态的切换。
  • 事件驱动:可以使用事件驱动的机制来触发状态之间的转换。当发生特定的事件时,调用上下文类中的方法来触发状态切换。

48.
#

  1. 抽象(Abstraction):抽象是指将系统中的实体或概念简化为更高层次的概括和概念,以便更好地理解和处理系统。它帮助我们忽略不必要的细节,关注于系统的核心概念和功能。
  2. 求精(Refinement):求精是指通过逐步细化和完善设计,将高层次的抽象转化为更具体和可执行的设计方案。求精过程涉及到详细设计和实现细节,并确保设计能够满足系统的要求和目标。
  3. 体系结构(Architecture):体系结构是系统设计的基础架构,它定义了系统的组织结构、模块和组件之间的关系,以及系统的行为和功能。良好的体系结构可以提供系统的可扩展性、可维护性和可重用性。
  4. 关注点分离(Separation of Concerns):关注点分离是指将系统的不同关注点(例如数据存储、用户界面、业务逻辑等)分离开来,以便更好地管理和维护系统。通过将不同的关注点分配给不同的模块或组件,可以提高系统的可读性、可维护性和灵活性。
  5. 模块化(Modularity):模块化是指将系统划分为相互独立、可重用和可替换的模块或组件。模块化设计有助于提高系统的可维护性、可测试性和可扩展性,并促进团队合作和并行开发。
  6. 信息隐藏(Information Hiding):信息隐藏是一种设计原则,它通过限制模块之间的接口和访问权限,将模块内部的实现细节隐藏起来。这样可以减少模块之间的依赖关系,提高模块的独立性和封装性。
  7. 功能独立(Functional Independence):功能独立是指系统中的不同功能模块之间相互独立,彼此之间没有强耦合关系。这种独立性使得系统更容易维护、测试和修改,同时也提高了系统的可重用性。
  8. 方面(Aspects):方面是指系统中与主要功能逻辑相对独立的横切关注点(cross-cutting concern)。通过使用方面技术,可以将这些关注点从主要功能模块中分离出来,提高系统的模块性、可维护性和可理解性。

  1. 封装、继承和多态:这是面向对象编程的三个基本概念。封装指将数据和操作封装在一个单独的单元中,继承指子类可以继承父类的属性和方法,多态指对象可以根据上下文表现出不同的行为。
  2. 设计类(Design Classes):在系统设计中,设计类是对系统中的实体、对象或概念进行建模和设计的基本单元。设计类包含属性和方法,描述了类的特征和行为。
  3. 重构(Refactoring):重构是指对现有代码进行修改和调整,以改善其结构、可读性、可维护性和性能,而不改变其外部行为。重构旨在提高代码质量和可理解性。
  4. 模式(Pattern):模式是在软件设计中广泛使用的可重用解决方案。设计模式提供了一套经过验证的设计思想和方法,用于解决常见的设计问题,并提供了一种共享设计经验的方式。
  5. 内聚(Cohesion):内聚度是指模块或类内部元素之间的联系和相关性程度。高内聚度意味着模块或类的元素紧密相关,实现了单一的责任或目标。
  6. 耦合(Coupling):耦合度是指模块或类之间相互依赖的程度。低耦合度意味着模块或类之间的依赖关系较弱,修改一个模块不会对其他模块造成太大影响。
  7. FURPS:FURPS是一个术语,代表软件工程中的不同方面和要素。它包括功能(Functionality)、可用性(Usability)、可靠性(Reliability)、性能(Performance)和支持性(Supportability)等方面,用于描述和评估软件的不同特性和要求。

49.
#

  1. 过多的控制细节:takeTurn() 方法中包含了掷骰子和走棋的逻辑,这导致了太多的细节暴露在方法中,使方法的可读性和可维护性降低。

重构过程中的改进:

  1. 抽象掷骰子逻辑:将掷骰子的逻辑抽象为一个独立的方法,例如 rollDice() 方法,使得方法的目的和行为更加清晰。
  2. 抽象走棋逻辑:将走棋的逻辑抽象为一个独立的方法,例如 movePiece() 方法,使得方法的目的和行为更加清晰。
  3. 封装细节:将细节操作隐藏在抽象的方法内部,只暴露必要的接口给外部调用。
public void takeTurn() {
    int rollTotal = rollDice();
    movePiece(rollTotal);
}
private int rollDice() {
    int rollTotal = 0;
    for (int i = 0; i < dice.length; i++) {
        dice[i].roll();
        rollTotal += dice[i].getFaceValue();
    }
    return rollTotal;
}
private void movePiece(int rollTotal) {
    Square newLoc = board.getSquare(piece.getLocation(), rollTotal);
    piece.setLocation(newLoc);
}

总结:

重构是通过对代码的修改来改进其设计、提高可读性、可维护性和扩展性等方面的过程。在这个例子中,采取了以下手段:

  1. 抽象:将掷骰子和走棋的逻辑抽象为独立的方法,通过抽象来减少方法的复杂性和细节暴露。
  2. 封装:将细节操作封装在私有方法内部,只暴露必要的接口给外部调用,实现细节的隐藏。
  3. 分离职责:将不同功能的代码分离成独立的方法,提高代码的可读性和可维护性。

抽象的设计概念:

抽象是软件设计中的一个重要概念,它可以将复杂的系统或问题领域简化为更高层次的概念或模型,从而降低复杂性并提高可理解性。通过抽象,我们可以忽略不必要的细节,关注于问题的本质和关键点,使设计更加清晰、可扩展和易于修改。

在实践中,抽象可以通过使用设计模式、定义抽象类和接口、封装和模块化等手段来实现。通过合理的抽象,可以隐藏细节,降低代码的耦合性,提高代码的可维护性。

50.
#

image-20230623182302820

显然不符合方面的设计规范。B*横切A,作为横切关注点,应当被单独建模设计为一个类。

image-20230623182906402
  • 关注点
    • 一个关注点是一个特征/行为,被指定为软件需求模型的一部分,可以说用例、特征、数据结构等
  • 横切关注点
    • 从规格中识别,有两个需求X、Y,若X不被满足则Y不能被满足,那么:
      • X*为横切关注点
      • X*被设计为一个类
  • 方面
    • 横切关注点的表示(设计方案)
    • 需求X的设计表示X*,被称作方面
  • 方面设计原则
    • 将一个方面作为独立的模块进行实施,而不是分散或纠缠的诸多片段

50.
#

image-20230623182302820

显然不符合方面的设计规范。B*横切A,作为横切关注点,应当被单独建模设计为一个类。

image-20230623182906402
  • 关注点
    • 一个关注点是一个特征/行为,被指定为软件需求模型的一部分,可以说用例、特征、数据结构等
  • 横切关注点
    • 从规格中识别,有两个需求X、Y,若X不被满足则Y不能被满足,那么:
      • X*为横切关注点
      • X*被设计为一个类
  • 方面
    • 横切关注点的表示(设计方案)
    • 需求X的设计表示X*,被称作方面
  • 方面设计原则
    • 将一个方面作为独立的模块进行实施,而不是分散或纠缠的诸多片段

51.
#

image-20230623183005452

根据高内聚原则,一个 Controller 应该负责协调和控制,而不应该包含具体的实现逻辑。因此,在这种情况下,重构的建议是将具体的实现逻辑移出 loginController,将其转移到其他独立的类中。

// 伪代码表示
// 不想画图qwq
class LoginController {
  private PasswordValidator passwordValidator;
  private PasswordRetriever passwordRetriever;
  
  public void login(String id, String pwd) {
    String storedPwd = passwordRetriever.getPassword(id);
    boolean isValid = passwordValidator.verify(pwd, storedPwd);
    ...
  }
}

class PasswordValidator {
  public boolean verify(String enteredPwd, String storedPwd) {
    ...
  }
}

class PasswordRetriever {
  public String getPassword(String id) {
    ...
  }
}

内聚性(Cohesion)是指一个构件内各个元素之间的关联程度,即构件内各个元素彼此之间相关的程度。高内聚性表示构件内部的元素相互关联程度高,功能紧密相关。

耦合性(Coupling)是指一个构件与其他构件之间的关联程度,即构件之间相互依赖的程度。低耦合性表示构件之间的依赖程度低,独立性高。

52.
#

image-20230623184201154

很明显,由于sensor具有多样性,采用switch判断种类在这里体现了典型的高控制耦合。

基于开闭原则OCP,进行相关重构:

image-20230623184705569

53.
#

  • OCP

    • 开闭原则
    • 模块/构件应该对外延(需求会发生变化的部分)具有开放性,对修改(Client内部逻辑)具有封闭性。
      • 使用接口 避免高控制耦合
  • LSP

    • L氏替换原则
    • 子类可以替换它们的基类
      • 类的设计依据 不满足时,可以向下分解类
  • DIP

    • 依赖倒置原则
    • 依赖于抽象,而非具体实现
      • 上层依赖于接口,下层再去实现接口方法
  • MIP–→ISP

    • 接口分离原则
    • 多个客户专用接口比一个通用接口要好
  • 构件

    • 通常来讲,构件是计算机软件中的一个模块化的构造块。再正式一点,OMG统一建模语言规范[OMG03a]是这样定义构件的:“系统中模块化的、可部署的和可替换的部件,该部件封装了实现并暴露–组接口。”

    • 在面向对象中,构件通常是指类或对象的实例,它们具有封装的属性和方法,并通过定义的接口来与其他构件进行交互。构件在 OOP 中被视为可重用的模块,具有独立的功能和责任。

      在面向过程中,构件可能更倾向于指代过程、函数或子程序。它们代表了一段可独立执行的代码,执行特定的功能或任务。

54.
#

image-20230623185503436

显然不能满足OCP原则对外延部分开放性的要求。如果Driver习得了新的驾驶载具,则需要多增加一个drive方法。

更改后的模式如下:

image-20230623185637004

55.
#

image-20230623185729532

基于OCP的重构结果:

image-20230623190210972

56.
#

image-20230623190627051

根据描述,当执行Client的letbirdfly(Bird)方法时,期望输出语句为"fly free in the air"。然而,当将基类Bird替换为子类Penguin时,输出语句"I cannot fly"与预期不一致。

根据LSP,子类应该能够替代父类。而Penguin类无法执行"fly free in the air"的操作,因此在替换Bird基类时,导致了不一致的行为。

一种改进方案是引入一个新的抽象类,例如FlyingBird,作为具有飞行能力的鸟类的基类。

更改让鸟飞方法的参数类型为 +letBirdFly(bird:FlyingBird)
Bird类不再具有方法fly
image-20230623191338951

57.
#

image-20230623191419077

Q1.

image-20230623191503674

Q2.

  1. LSP要求子类能够替代父类。当客户代码根据对象的具体类型进行条件判断时,暗示了对不同类型对象的特殊处理,而不是将它们视为同一种类型的统一接口。这导致了使用基于类型的条件判断的代码逻辑在子类替代父类时可能会被打破。子类的行为与父类的行为不一致,无法无缝替换,因此违反了LSP。
  2. 基于类型的 if-else 判断需要在客户代码中手动添加新的条件分支来处理新的类型。这导致在添加新类型时需要修改客户代码,违反了OCP原则对外延的开放性。如果在系统中频繁添加新的类型,这种修改将变得繁琐且容易引入错误。

58.
#

image-20230623191840518

应用DIP重构:

image-20230623192321383

59.
#

image-20230623192004314

显然存在设计问题,具体而言是”宽接口问题“。FloorPlan同时提供了安全部分和监视部分的接口方法,不满足ISP指出的多个专用接口的要求。

image-20230623192856471

60.
#

image-20230623193225974 image-20230623193335548

61.
#

思考:

  • 为了给界面设计任务建立牢固的基础,我们需要做界面分析,界面分析主要包括哪些任务呢?

    • 界面分析
      • 所有软件工程过程模型的一个重要原则是:在试图设计一个解决方案之前,最好对问题有更好的理解。在用户界面的设计中,理解问题就意味着了解:(1)通过界面和系统交互的人(最终用户),(2)最终用户为完成工作要执行的任务,(3)作为界面的一部分而显示的内容:(4)任务处理的环境。
        • 用户分析
        • 任务分析和建模
        • 显示内容分析
        • 工作环境分析
  • 简述界面设计的步骤。

    • 用户界面的分析和设计全过程始于创建不同的系统功能模型(从外部看对系统的感觉)。用以完成系统功能的任务被分为面向人的和面向计算机的,考虑那些应用到界面设计中的各种设计问题:各种工具被用于建造原型并最终实现设计模型,最后由最终用户从质量的角度对结果进行评估。
      • 分析和设计用户界面时要考虑4种模型:工程师(或者软件工程师)建立用户模型,软件工程师创建设计模型,最终用户在脑海里对界面产生映像,称为用户的心理模型或系统感觉,系统的实现者创建实现模型。
    • 用户界面的分析和设计过程是迭代的,可以用螺旋模型表示。用户界面分析和设计过程开始于螺旋模型的内部,且包括4个不同的框架活动:(1)界面分析及建模。(2)界面设计。(3)界面构造。(4)界面确认。
    • 界面设计步骤
      • 1.使用界面分析中获得的信息,定义界面对象和动作(操作)。
      • 2.定义那些导致用户界面状态发生变化的事件(用户动作),并对行为建模。
      • 3.描述每个界面状态,就像最终用户实际看到的那样。
      • 4.简要说明用户如何从界面提供的界面信息来解释系统状态。

62.
#

image-20230623194946646

圈复杂度是一种软件度量指标,用于衡量代码中的复杂性。它通过计算程序中的独立路径数来评估代码的复杂程度。

基础路径是一种路径的集合,它覆盖了程序中所有可能的路径,并且没有重复的路径。基础路径用于计算软件的测试覆盖率和执行路径的数量。

规划测试时的基础路径时,不要提前优化分支,这样保证:基础路径 == 圈复杂度。

63.
#

image-20230623193335548
  1. 测试用例:本省快件,重量小于等于25公斤
    • 输入:省内收货地点、重量为15公斤
    • 预期输出:快件费用为 15 * 8 = 120 元
  2. 测试用例:本省慢件,重量小于等于25公斤
    • 输入:省内收货地点、重量为20公斤
    • 预期输出:慢件费用为 20 * 4 = 80 元
  3. 测试用例:外省快件,重量小于等于25公斤
    • 输入:外省收货地点、重量为18公斤
    • 预期输出:快件费用为 18 * 12 = 216 元
  4. 测试用例:外省慢件,重量小于等于25公斤
    • 输入:外省收货地点、重量为22公斤
    • 预期输出:慢件费用为 22 * 8 = 176 元
  5. 测试用例:本省快件,重量大于25公斤
    • 输入:省内收货地点、重量为30公斤
    • 预期输出:快件费用为 (25 * 8) + ((30 - 25) * 2) = 190 元
  6. 测试用例:本省慢件,重量大于25公斤
    • 输入:省内收货地点、重量为28公斤
    • 预期输出:慢件费用为 (25 * 4) + ((28 - 25) * 2) = 92 元
  7. 测试用例:外省快件,重量大于25公斤
    • 输入:外省收货地点、重量为32公斤
    • 预期输出:快件费用为 (25 * 12) + ((32 - 25) * 2) = 308 元
  8. 测试用例:外省慢件,重量大于25公斤
    • 输入:外省收货地点、重量为27公斤
    • 预期输出:慢件费用为 (25 * 8) + ((27 - 25) * 2) = 78 元

64.
#

image-20230623200027395

复杂度7

基础路径:

image-20230623200731089

测试集:

a b i
1 0 2
1 0 1
0 1 10
0 1 11
1 1 0

65.
#

  1. 验证(Verification):验证是确认产品、系统或组件是否满足规定的需求和规范的过程。它是通过检查、评估和测试来验证产品是否符合预期的功能和性能。验证的目标是确保产品按照规定的要求进行构建。
  2. 确认(Validation):确认是确定产品、系统或组件是否满足最终用户的期望和需求的过程。它是通过实际使用和测试产品来确认其是否符合用户的实际需求和预期。确认的目标是确保产品对用户来说是可接受的和有效的。
  3. 黑盒测试(Black Box Testing):黑盒测试是一种测试方法,它不考虑内部的实现细节,而是基于对系统功能和需求的理解来设计测试。测试人员只关注输入和输出,不关注内部的代码逻辑。黑盒测试的目标是检查系统是否按照规定的功能和规范运行。
  4. 白盒测试(White Box Testing):白盒测试是一种测试方法,它考虑系统的内部结构和代码逻辑。测试人员可以查看源代码和内部实现细节,以设计测试用例来验证代码的正确性和覆盖率。白盒测试的目标是确保系统的内部逻辑正确,代码无误。
  5. 回归测试(Regression Testing):回归测试是在对软件进行修改、修复或增强后重新执行现有测试用例的过程。它旨在确保在进行更改后,系统的已有功能没有受到负面影响或引入新的错误。回归测试的目标是捕获并修复在修改过程中引入的错误。
  6. 𝛼测试(Alpha Testing)和𝛽测试(Beta Testing):𝛼测试是在开发环境中进行的内部测试,由开发团队执行。它旨在发现并解决软件中的问题和错误。𝛽测试是在实际使用环境中进行的外部测试,由最终用户或一组选择的用户执行。它旨在评估产品在真实环境中的性能和可行性。
  7. 单元测试(Unit Testing):单元测试是对软件的最小可测试单元(如函数、方法或模块)进行测试的过程。它用于验证单个单元的行为和功能是否正常工作。单元测试通常由开发人员编写和执行。
  8. 集成测试(Integration Testing):集成测试是将多个独立的单元或组件组合在一起进行测试的过程。它旨在验证不同组件之间的交互和集成是否正确。集成测试可以检测到在组件集成时可能出现的错误和问题。
  9. 确认测试(Acceptance Testing):确认测试是由最终用户或客户执行的测试,旨在确认系统是否满足其预期的业务需求和用户需求。确认测试通常在软件开发的后期阶段进行,以确保软件可以交付并满足用户的期望。
  10. 系统测试(System Testing):系统测试是对完整的软件系统进行测试的过程。它测试整个系统的功能、性能、安全性等方面,以确保系统在各个方面都符合预期的要求。系统测试通常在集成测试之后进行,旨在验证整个系统的完整性和正确性。

66.
#

1.用户操纵控制。

2.减少用户的记忆负担。

3.保持界面一致。

image-20230623193935565

67.
#

  1. 客户/服务器(Client/Server):这是一种常见的拓扑结构,其中客户端和服务器之间建立连接。客户端向服务器发送请求并接收响应。这种拓扑结构适用于许多应用程序,如Web应用程序、数据库系统等。
  2. 分布式(Distributed):分布式拓扑结构将系统的不同组件分布在多个计算节点上,这些节点可以在同一网络中或分布在不同的地理位置。这种拓扑结构适用于需要高度可扩展性和容错性的系统,如大规模分布式系统、云计算环境等。
  3. 对等网络(Peer-to-Peer):对等网络拓扑结构中,所有节点都是对等的,它们之间可以直接通信并共享资源。这种拓扑结构适用于文件共享、协作应用程序等。
  4. 集中式(Centralized):在集中式拓扑结构中,所有的处理和决策都由一个中心节点或服务器完成。这种拓扑结构适用于需要集中控制的系统,如管理系统、调度系统等。
  5. 混合式(Hybrid):混合式拓扑结构是不同拓扑结构的组合。它可以根据系统的特定需求和复杂性来设计,包括客户/服务器和分布式结构的混合、对等网络与集中式结构的混合等。

相关文章

计网一些题
·768 字· loading · loading
数据库-函数依赖
·195 字· loading · loading
计网实验-ospf
·10 字· loading · loading