第3章 结构化分析

第3章 结构化分析

为了开发出真正满足用户需求的软件产品,首先必须知道用户的需求。对软件需求的深入理解是软件开发工作获得成功的前提和关键,不论我们把设计和编码工作做得如何出色,不能真正满足用户需求的程序只会给用户带来失望,给开发者带来烦恼。

传统的软件工程方法学采用结构化分析(structured analysis,SA)技术完成需求分析工作。本章讲述结构化分析过程和准则、与用户沟通获取用户需求的方法、分析建模与规格说明、实体—关系图、数据流图、状态转换图、数据字典等内容。

3.1 概述

需求分析是发现、求精、建模、规格说明和复审的过程。为了发现用户的真正需求,首先应该从宏观角度调查、分析用户所面临的问题。也就是说,需求分析的第1步是尽可能准确地了解用户当前的情况和需要解决的问题。例如,仅仅知道“用户需要一个计算机辅助设计系统,因为他们的手工设计系统很糟糕”是远远不够的。除非开发人员准确地知道目前使用的手工系统什么地方很糟糕,否则新开发出的计算机辅助设计系统很可能也同样糟糕。类似地,如果一个个人计算机制造商打算开发一个新的操作系统,他首先应该做的工作就是评价目前使用的操作系统并准确地分析它不能令人满意的原因。只有开发人员对用户面临的问题有了清楚的了解之后,才能正确地回答出“什么是新产品必须做到的”这个关键问题。

如果软件是新开发的计算机系统的一个组成部分,则系统工程师所确定的软件职责范围,可以作为软件需求分析的出发点。

分析员对用户提出的初步要求应该反复求精多次细化,才能充分理解用户的需求,得出对目标系统的完整、准确和具体的要求。

为了更好地理解问题,人们常常采用建立模型的方法。所谓模型,就是为了理解事物而对事物做出的一种抽象,是对事物的一种无歧义的书面描述。通常,模型由一组图形符号和组织这些符号的规则组成。在技术层次上,软件工程是从一系列建模活动开始的,这些建模活动导致对要求开发的软件的完整的需求规格说明和全面的设计表示。结构化分析就是一种建立模型的活动,通常建立数据模型、功能模型和行为模型3种模型。除了用分析模型表示软件需求之外,还要写出准确的软件需求规格说明。模型既是软件设计的基础,也是编写软件规格说明的基础。

在分析软件需求和编写软件规格说明的过程中,软件开发者和软件用户都起着关键的、必不可少的作用。只有用户才真正知道他们需要什么,用户必须尽量把他们对软件功能和性能的模糊需求准确、具体地描述出来,而开发者则是软件需求的询问者、顾问和实现者。

表面看来,需求分析和规格说明好像是比较简单的工作,实际上完全相反,这是一项相当艰巨复杂的工作。用户与开发者之间需要沟通的内容非常多,在双方交流信息的过程中很容易出现误解或遗漏,也可能存在二义性,因此,不仅在整个需求分析过程中应该采用行之有效的沟通方法,集中精力过细工作,而且对需求分析的结果(分析模型和规格说明)必须严格审查。尽管目前存在许多不同的结构化分析方法,但是,所有这些分析方法都遵守下述准则。

  • 必须理解和表示问题的信息域,根据这条准则应该建立数据模型。
  • 必须定义软件应完成的功能,这条准则要求建立功能模型。
  • 必须表示作为外部事件结果的软件行为,这条准则要求建立行为模型。
  • 必须对描述信息、功能和行为的模型进行分解,用层次的方式展示细节。
  • 分析过程应该从要素信息移向实现细节。

3.2 与用户沟通的方法

软件需求分析总是从两方或多方之间的沟通开始。用户面临的问题需要用基于计算机的方案来解决;开发者应该对用户的需求作出反应,给用户提供帮助。这样就产生了相互沟通的需求。从开始沟通到真正相互理解的道路通常是充满坎坷的,良好的沟通方法有助于加快理解的过程。

3.2.1 访谈

访谈(或称为会谈)是最早开始运用的获取用户需求的技术,也是迄今为止仍然广泛使用的主要的需求分析技术。

访谈有两种基本形式,正式的访谈和非正式的访谈。在正式的访谈中,系统分析员将提出一些事先准备好的具体问题。例如,询问客户公司销售的商品种类、雇用的销售人员数目、信息反馈时间应该多快等。在非正式的访谈中,将提出一些可以自由回答的开放性问题,以鼓励被访问的人员表达自己的想法。例如,询问用户为什么对目前正在使用的系统感到不满意。当需要调查大量人员的意见时,向被调查的人员分发调查表是一个十分有效的做法。经过仔细考虑的书面回答可能比被访者对问题的口头回答更准确。系统分析员仔细阅读收回的调查表,然后再有针对性地访问一些用户,以便向他们询问在分析调查表时发现的新问题。

在对用户进行访谈的过程中使用情景分析技术往往非常有效。所谓情景分析就是对用户运用目标系统解决某个具体问题的方法和结果进行分析。例如,假定目标系统是一个制定减肥计划的软件,当给出某个肥胖症患者的年龄、姓别、身高、体重、腰围及其他数据时,就出现了一个可能的情景描述。系统分析员根据自己对目标系统应具备的功能的理解,给出适用于该患者的菜单。客户公司的饮食学家可能指出,哪些菜单对于有特殊饮食需求的病人(如糖尿病人、素食者)是不合适的。这就使系统分析员认识到,在目标系统制定菜单之前还应该先询问患者的特殊饮食需求。利用情景分析技术,使得系统分析员能够获知用户的具体需求。情景分析的用处主要体现在下述两个方面:①它能在某种程度上演示产品的行为,从而便于用户理解,而且还可能进一步揭示出一些系统分析员目前还不知道的需求;②由于情景分析较易为用户所理解,因此,使用这种技术能保证用户在需求分析过程中始终扮演一个积极主动的角色。需求分析的目标是了解用户的真正需求,而这一信息的唯一来源是用户,让用户起积极主动的作用对需求分析工作获得成功是至关重要的。

3.2.2 简易的应用规格说明技术

使用传统的访谈技术定义需求时,用户和开发者往往有意无意地区分“我们和他们”。由于不能做到像同一个团队的人那样同心协力地识别和精化需求,这种方法的效果有时并不理想(经常发生误解,还可能遗漏重要的信息)。

为了解决上述问题,人们研究出了一种面向团队的需求收集法,称为简易的应用规格说明技术。这种方法提倡用户与开发者密切合作,共同标识问题,提出解决方案的要素,商讨不同的方法并指定基本的需求。今天,简易的应用规格说明技术已经成为信息系统界使用的主流技术。尽管存在许多不同的简易应用规格说明方法,但是它们遵循的基本准则是相同的。

  • 在中立地点举行由开发者和用户双方出席的会议。
  • 制定准备会议和参加会议的规则。
  • 提出一个议事日程,这个日程应该足够正式,以便能够涵盖所有要点;同时这个日程又应该足够非正式,以便鼓励自由思维。
  • 由一个“协调人”来主持会议,他既可以是用户,也可以是开发者,还可以是从外面请来的人。
  • 使用一种“定义机制”(如工作表、图表等)。
  • 目标是标识问题、提出解决方案要素、商讨不同的方法以及在有利于实现目标的氛围中指定初步的需求。

通常,首先进行初步的访谈(见3.2.1小节),通过用户对基本问题的回答,对于待解决问题的范围和解决方案有了总体认识,然后开发者和用户都写出“产品需求”。选定会议地点、日期和时间,并选举一个协调人,邀请开发者和用户双方组织的代表出席会议,在会议日期之前把写好的产品需求分发给每位与会者。

要求每位与会者在开会的前几天认真复审产品需求,并且列出作为系统环境组成部分的对象、系统将产生的对象以及系统为了完成自己的功能将使用的对象。此外,还要求每位与会者列出操作这些对象或与这些对象交互的服务(即处理或功能)。最后,还应该列出约束条件(如成本、规模、完成日期)和性能标准(如速度、精度)。并不期望每位与会者列出的内容都是毫无遗漏的,但是希望能准确表达出每个人对目标系统的认识。

会议开始之后,讨论的第1个议题为是否需要这个新产品。一旦大家都同意确实需要这个新产品,每位与会者就应该展示他们在会前准备好的列表供大家讨论。可以把这些列表抄写在大纸上钉在墙上,或者写在白板上挂在墙上。理想的情况是,表中每一项都能单独移动,这样就能删除或增添表项,或组合不同的列表。在这个阶段,严格禁止批评与争论。

在展示了每个人针对某个议题的列表之后,小组共同创建一张组合列表。在组合列表中消去了冗余项,加入了在展示过程中产生的新想法,但是并不删除任何实质性内容。在针对每个议题的组合列表都建立起来之后,由协调人主持讨论。组合列表将被缩短、加长或重新措辞,以便更恰当地描述将被开发的产品。讨论的目标是,针对每个议题(对象、服务、约束和性能)都创建出一张意见一致的列表。

一旦得出了意见一致的列表,就把与会者分成更小的小组,每个小组的工作目标是为每张列表中的一个或多个项目制定出小型规格说明。小型规格说明是对列表中包含的单词或短语的准确说明。

然后,每个小组都向全体与会者展示他们制定出的小型规格说明供大家讨论。通过讨论可能会增加或删除一些内容,也可能做一些进一步的精化工作。在讨论过程中还可能提出一些无法在这次会议中解决的问题,应该保存问题清单,以便这些想法在以后的活动中起作用。在完成了小型规格说明之后,每个与会者都制定出产品的一整套确认标准,并把自己制定的列表提交会议讨论,以创建出意见一致的确认标准列表。最后,由一名或多名与会者根据会议成果起草完整的规格说明。

简易的应用规格说明技术并不是解决需求分析阶段遇到的所有问题的“万能灵药”。但是,这种面向团队的需求收集方法确实有许多突出的优点:开发者与用户不分彼此,集思广益密切合作;即时讨论和求精;有能导出规格说明的具体步骤。

3.2.3 软件原型

正如前面介绍的,快速建立软件原型是最准确、最有效、最强大的需求分析技术。快速原型就是快速建立起来的旨在演示目标系统主要功能的程序。构建原型的要点是,它应该实现用户看得见的功能(如屏幕显示或打印报表),省略目标系统的“隐含”功能(如修改文件)。快速原型应该具备的第1个特性是“快速”。快速原型的目的是尽快向用户提供一个可在计算机上运行的目标系统的模型,以便使用户和开发者在目标系统应该“做什么”这个问题上尽可能快地达成共识。因此,原型的某些缺陷是可以忽略的,只要这些缺陷不严重地损害原型的功能,不会使用户对产品的行为产生误解,就不必管它们。快速原型应该具备的第2个特性是“容易修改”。如果原型的第1版不是用户所需要的,就必须根据用户的意见迅速地修改它,构建出原型的第2版,以更好地满足用户的需求。在实际开发软件产品时,“修改—试用—反馈”的过程可能重复多遍,如果修改耗时过多,势必延误软件开发时间。

为了快速地构建和修改原型,通常可以使用下述3种方法和工具。

(1)第四代技术(4GT)

第四代技术包括众多数据库查询和报表语言、程序和应用系统生成器以及其他非常高级的非过程语言。因为第四代技术使得软件工程师能够快速地生成可执行的代码,因此,它们是理想的快速原型工具。

(2)可重用的软件构件

另外一种快速构建原型的方法,是使用一组已有的软件构件(或称为组件)来装配(而不是从头构造)原型。软件构件可以是数据结构(或数据库),或软件体系结构构件(即程序),或过程构件(即模块)。必须把软件构件设计成能在不知其内部工作细节的条件下重用。应该注意,现有的软件产品可以被用做“新的或改进的”产品的原型,这也是软件原型重用的一种形式。

(3)形式化规格说明和原型环境

在过去的二十几年中,人们已经开发出来一系列形式化规格说明语言和工具,用于替代自然语言规格说明技术。今天,这些形式化语言的开发者正在开发交互式环境,目的是:①使得分析员能够交互地创建基于语言的规格说明;②调用自动工具把基于语言的规格说明翻译成可执行的代码;③使得用户能够使用可执行的原型代码去精化形式化的需求。

3.3 分析建模与规格说明

3.3.1 分析建模

结构化分析实质上是一种创建模型的活动。通过需求分析而建立的模型必须达到下述的3个基本目标。

  • 描述用户的需求。
  • 为软件设计工作奠定基础。
  • 定义一组需求,一旦开发出软件产品之后,就可以用这组需求为标准来验收。

为了达到上述这些目标,在结构化分析过程中导出的分析模型的形式,如图3.1所示。

0301

图3.1 分析模型的结构

分析模型的核心是“数据字典”,它描述软件使用或产生的所有数据对象。围绕着这个核心有3种不同的图:“实体—关系图”描绘数据对象之间的关系,它是用来进行数据建模活动的图形,图中出现的每个数据对象的属性可以在“数据对象描述”中描述。

创建“数据流图”有两个目的:①指出当数据在软件系统中移动时怎样被变换;②描绘变换数据流的功能和子功能。数据流图是功能建模的基础,在“处理规格说明”中给出了对出现在数据流图中的每个功能的描述。

“状态转换图”指明了作为外部事件结果的系统行为。为此,状态转换图描绘了系统的各种行为模式(称为“状态”)和在不同状态间转换的方式。状态转换图是行为建模的基础,在“控制规格说明”中包含了有关软件控制的附加信息。

3.3.2 软件需求规格说明

通过需求分析除了创建分析模型之外,还应该写出软件需求规格说明,它是分析阶段的最终成果。下面给出的简略大纲可以作为软件需求规格说明的框架。

Ⅰ.引言

  A.系统参考文献

  B.整体描述

  C.软件项目约束

Ⅱ.信息描述

  A.信息内容

  B.信息流

    1.数据流

    2.控制流

Ⅲ.功能描述

  A.功能分解

  B.功能描述

    1.处理说明

    2.限制

    3.性能需求

    4.设计约束

    5.支撑图

  C.控制描述

    1.控制规格说明

    2.设计约束

Ⅳ.行为描述

  A.系统状态

  B.事件和动作

Ⅴ.确认标准

  A.性能范围

  B.测试种类

  C.预期的软件响应

  D.特殊考虑

Ⅵ.参考书目

Ⅶ.附录

“引言”部分陈述软件的目标。实际上,它可能就是计划文档中描述的软件范围。“信息描述”部分详细陈述软件必须解决的问题,并且描述了信息内容、信息关系、信息流和信息结构,此外,还针对外部系统元素和内部软件功能描述了硬件、软件及人—机界面。“功能描述”部分给出为解决问题而需要的每个功能。其中,说明了完成每个功能的处理过程;叙述并论证了设计约束;描述了性能特征;用若干张图描绘了软件的整体结构及软件功能与其他系统元素间的相互影响。

“行为描述”部分说明作为外部事件和内部产生控制结果的软件操作。软件需求规格说明中最重要然而又最常被忽略的内容,可能就是“确认标准”。我们怎样判断软件实现是否成功?为了确认功能、性能和约束符合需要,应该进行哪些类型的测试?之所以会忽略这些内容,是因为要写出它们需要对软件需求有透彻的理解,然而有时我们在这个阶段还未能做到彻底地理解软件需求。实际上,写出确认标准是对其他所有需求的隐式复审,因此,把时间和精力用到这部分内容上是至关重要的。

最后,在软件需求规格说明中还应该包括“参考书目”和“附录”。参考书目列出与该软件有关的全部文档,其中包括其他软件工程文档、技术参考文献以及厂商资料及标准。附录中包含了规格说明的补充信息:表格数据、详细算法、图表及其他材料。

在许多情况下,软件需求规格说明可能都附有可执行的原型(在某些情况下可替代规格说明)及初步的用户手册。初步的用户手册把软件看做一个黑盒子,也就是说,手册重点描述用户的输入和软件的输出结果。通过该手册往往能发现人—机界面问题。

3.4 实体—关系图

数据模型包含3种相互关联的信息:数据对象、描述数据对象的属性及数据对象彼此间相互连接的关系。

1.数据对象

数据对象是对软件必须理解的复合信息的表示。所谓复合信息是指具有一系列不同性质或属性的事物,因此,仅有单个值的事物(例如宽度)不是数据对象。

数据对象可以是外部实体(如产生或使用信息的任何事物)、事物(如报表或屏幕显示)、行为(如打电话)或事件(如响警报)、角色(如销售员)、单位(如会计科)以及地点(如仓库)或结构(如文件)等。例如,教师、学生、课程、汽车等都可以认为是数据对象,因为它们都可以由一组属性来定义。“数据对象描述”(见图3.1)中包含了数据对象及它们的所有属性。

数据对象彼此间是有关联的,如教师“教”课程,学生“学”课程,教或学的关系表示教师和课程或学生和课程之间的一种特定的连接。

数据对象只封装了数据而没有对作用于数据上的操作的引用,这是数据对象与面向对象范型(见本书第3篇)中的“类”或“对象”的显著区别。

2.属性

属性定义了数据对象的性质。属性可以具有下述3种不同的特性之一,也就是说,可以用属性来:①为数据对象的实例命名;②描述该实例;③引用另一个数据对象的实例。此外,必须把一个或多个属性定义为“标识符”,即当我们希望找到数据对象的一个实例时,标识符属性成为“关键字”。

应该根据对所要解决的问题的理解,来确定特定数据对象的一组合适的属性。例如,为了开发机动车管理系统,描述汽车的属性应该是制造商、品牌、型号、发动机号码、车体类型、颜色、车主姓名、住址、驾驶证号码、生产日期、购买日期等。但是,为了开发设计汽车的CAD系统,用上述这些属性描述汽车就不合适了,其中车主姓名、住址、驾驶证号码、生产日期、购买日期等属性应该删去,而描述汽车技术指标的大量属性应该添加进来。

3.关系

数据对象彼此之间相互连接的方式称为关系,也称为联系。客观世界中的事物彼此间往往是有联系的,如教师与课程间存在“教”这种联系,而学生与课程间则存在“学”这种联系。联系可分为以下3类。

(1)一对一联系(1∶1)

例如,一个部门有一个经理,而每个经理只在一个部门任职,则部门与经理的联系是一对一的关系。

(2)一对多联系(1∶N

例如,某校教师与课程之间存在一对多的联系“教”,即每位教师可以教多门课程,但是每门课程只能由一位教师来教(见图3.2)。

(3)多对多联系(MN

例如,图3.2表示学生与课程间的联系(“学”)是多对多的关系,即一个学生可以学多门课程,而每门课程可以有多个学生来学。

0302

图3.2 某校教学管理ER图

联系也可能有属性。例如,学生“学”某门课程所取得的成绩,既不是学生的属性也不是课程的属性。由于“成绩”既依赖于某名特定的学生又依赖于某门特定的课程,所以这是学生与课程之间的联系“学”的属性(见图3.2)。

4.实体—关系图的符号

通常,使用实体—关系图(entity-relationship diagram)来建立数据模型,从而可以满足3.1节中讲述的第1条分析准则。常把实体—关系图简称为ER图,相应地,用ER图描绘的数据模型也称为ER模型。

ER图中包含了实体(即数据对象)、关系和属性3种基本成分。通常用矩形框代表实体,用连接相关实体的菱形框表示关系,用椭圆形或圆角矩形表示实体(或关系)的属性,并用无向边把实体(或关系)与其属性连接起来。图3.2所示为某学校教学管理的ER图。

人们通常就是用实体、联系和属性这3个概念来理解现实问题的,因此,ER模型比较接近人的习惯思维方式。此外,ER模型使用简单的图形符号表达系统分析员对问题域的理解,不熟悉计算机技术的用户也能理解它,因此,ER模型可以作为用户与分析员之间有效的交流工具。

3.5 数据流图

当信息在软件中移动时,它将被一系列“变换”所修改。数据流图(data flow diagram,DFD)是一种图形化技术,它描绘信息流和数据从输入移动到输出的过程中所经受的变换。在数据流图中没有任何具体的物理元素,它只是描绘信息在软件中流动和被处理的情况。因为数据流图是系统逻辑功能的图形表示,即使不是专业的计算机技术人员也容易理解它,所以是分析员与用户之间极好的沟通工具。此外,设计数据流图时只需考虑系统必须完成的基本逻辑功能,完全不需考虑怎样具体地实现这些功能,因此,它也是今后进行软件设计很好的出发点。

可以在任何抽象层次上使用数据流图表示系统或软件。事实上,可以分层次地画数据流图,层次越低表现出的信息流细节和功能细节也越多。数据流图既提供了功能建模机制也提供了信息流建模机制,从而满足了3.1节中讲述的第2条分析准则。

3.5.1 数据流图符号

如图3.3(a)所示,数据流图有4种基本符号:正方形(或立方体)表示数据的源点或终点;圆角矩形(或圆形)代表变换数据的处理;开口矩形(或两条平行横线)代表数据存储;箭头表示数据流,即特定数据的流动方向。注意,数据流与程序流程图中用箭头表示的控制流有本质不同,注意不要混淆。熟悉程序流程图的初学者在画数据流图时,往往试图在数据流图中表现分支条件或循环,殊不知这样做将造成混乱,画不出正确的数据流图。在数据流图中应该描绘所有可能的数据流向,而不应该描绘出现某个数据流的条件。

0303

图3.3 数据流图的符号

处理并不一定是一个程序。一个处理框可以代表一系列程序、单个程序或者程序的一个模块;它甚至可以代表用穿孔机穿孔或目视检查数据正确性等人工处理过程。一个数据存储也并不等同于一个文件,它可以表示一个文件、文件的一部分、数据库的元素、记录的一部分等;数据可以存储在磁盘、磁带、磁鼓、主存、微缩胶片、穿孔卡片及其他任何介质上(包括人脑)。

数据存储和数据流都是数据,仅仅所处的状态不同。数据存储是处于静止状态的数据,数据流是处于运动中的数据。

通常在数据流图中忽略出错处理,也不包括诸如打开或关闭文件之类的内务处理,数据流图的基本要点是描绘“做什么”而不考虑“怎样做”。

有时数据的源点和终点相同,这时如果只用一个符号代表数据的源点和终点,则将有两个箭头和这个符号相连(一个进一个出),可能其中一条箭头线相当长,这将降低数据流图的清晰度。另一种表示方法是再重复画一个同样的符号(正方形或立方体)表示数据的终点。有时数据存储也需要重复,以增加数据流图的清晰程度。为了避免可能引起的误解,如果代表同一个事物的同样符号在图中出现在n个地方,则在这个符号的一个角上画n−1条短斜线做标记。除了上述4种基本符号之外,有时也使用几种附加符号。星号(*)表示数据流之间是“与”关系(同时存在);加号(+)表示“或”关系;( \oplus )号表示只能从中选一个(互斥的关系)。图3.3(b)所示为这些附加符号的含义。

3.5.2 例子

下面通过一个简单例子具体说明怎样画数据流图。假设一家工厂的采购部每天需要一张定货报表,报表按零件编号排序,表中列出所有需要再次定货的零件。对于每个需要再次定货的零件应该列出下述数据:零件编号、零件名称、定货数量、目前价格、主要供应者和次要供应者。零件入库或出库称为事务,通过放在仓库中的终端把事务报告给定货系统。当某种零件的库存数量少于库存量临界值时就应该再次定货。

数据流图有4种成分:源点或终点、处理、数据存储和数据流。画出上述定货系统的数据流图可采用以下步骤。

① 从问题描述中提取数据流图的4种成分。首先考虑数据的源点和终点,从上面对系统的描述可以知道“采购部每天需要一张定货报表”,“通过放在仓库中的终端把事务报告报告给定货系统”,所以采购员是数据终点,而仓库管理员是数据源点。

② 接下来考虑处理。再一次阅读问题描述,“采购部需要报表”,显然他们还没有这种报表,因此必须有一个用于产生报表的处理。事务的后果是改变零件库存量,而任何改变数据的操作都是处理,因此,对事务进行的加工是另一个处理。注意,在问题描述中并没有明显地提到需要对事务进行处理,但是通过分析可以看出这种需要。

③ 最后考虑数据流和数据存储:系统把定货报表送给采购部,因此定货报表是一个数据流;事务需要从仓库送到系统中,显然事务是另一个数据流。产生报表和处理事务这两个处理在时间上明显不匹配——每当有一个事务发生时立即处理它,然而每天只产生一次定货报表,因此,用来产生定货报表的数据必须存放一段时间,也就是应该有一个数据存储。

注意,并不是所有数据存储和数据流都能直接从问题描述中提取出来。例如,“当某种零件的库存数量少于库存量临界值时就应该再次定货”,这个事实意味着必须在某个地方有零件库存量和库存量临界值这样的数据。因为这些数据元素的存在时间看来应该比单个事务的存在时间长,所以认为有一个数据存储保存库存清单数据是合理的。

表3.1列出了上面分析的结果,其中加星号标记的是在问题描述中隐含的成分。

表3.1 组成数据流图的元素可以从描述问题的信息中提取

源点/终点

处  理

数 据 流

数 据 存 储

采购员
仓库管理员

产生报表
处理事务

定货报表
 零件编号
 零件名称
 定货数量
 目前价格
 主要供应者
 次要供应者
事务
 零件编号*
 事务类型
 数量*

定货信息
(见定货报表)

库存清单*
 零件编号*
 库存量
 库存量临界值

一旦把数据流图的4种成分分离出来后,就可以着手画数据流图了。但是要注意,数据流图是系统的逻辑模型,而任何计算机系统实质上都是信息处理系统,也就是说计算机系统本质上都是把输入数据变换成输出数据。因此,任何系统的基本模型都由若干个数据源点/终点以及一个处理组成,这个处理就代表了系统对数据加工变换的基本功能。对于上述的定货系统可以画出如图3.4所示的基本系统模型。

0304

图3.4 定货系统的基本系统模型(突出表明了数据的源点和终点)

从基本系统模型这样非常高的抽象层次开始画数据流图是一个好办法。在这个高层次的数据流图上是否列出了所有给定的数据源点/终点是一目了然的,因此它是很有价值的沟通工具。

然而,图3.4所示的基本系统模型毕竟太抽象了,从这张图上对定货系统所能了解到的信息非常有限。下一步应该把基本系统模型细化,描绘系统的主要功能。从表3.1可知,“产生报表”和“处理事务”是系统必须完成的两个主要功能,它们将代替图3.4中的“定货系统”(见图3.5)。此外,细化后的数据流图中还增加了两个数据存储:处理事务需要“库存清单”数据;产生报表和处理事务在不同时间,因此需要存储“定货信息”。除了表3.1中列出的两个数据流之外还有另外两个数据流,它们与数据存储相同。这是因为从一个数据存储中取出来的或放进去的数据通常和原来存储的数据相同,也就是说,数据存储和数据流只不过是同样数据的两种不同形式。

在图3.5中给处理和数据存储都加了编号,这样做的目的是便于引用和追踪。

0305

图3.5 定货系统的功能级数据流图

接下来应该对功能级数据流图中描绘的系统主要功能进一步细化。考虑通过系统的逻辑数据流,当发生一个事务时必须首先接收它;随后按照事务的内容修改库存清单;最后如果更新后的库存量少于库存量临界值时,则应该再次定货,也就是需要处理定货信息。因此,把“处理事务”这个功能分解为下述3个步骤:“接收事务”、“更新库存清单”和“处理定货”(见图3.6),这在逻辑上是合理的。

0306

图3.6 把处理事务的功能进一步分解后的数据流图

我们为什么不进一步分解“产生报表”这个功能呢?因为定货报表中需要的数据在存储的定货信息中全都有,产生报表只不过是按一定顺序排列这些信息,再按一定格式打印出来。然而这些考虑纯属具体实现的细节,不应该在数据流图中表现。同样道理,对“接收事务”或“更新库存清单”等功能也没有必要进一步细化。总之,当进一步分解将涉及如何具体地实现一个功能时,就不应该再分解了。

在对数据流图分层细化时必须保持信息连续性,即当把一个处理分解为一系列处理时,分解前和分解后的输入/输出数据流必须相同。例如,图3.4和图3.5所示的输入/输出数据流都是“事务”和“定货报表”,图3.5中“处理事务”这个处理框的输入/输出数据流是“事务”、“库存清单”和“定货信息”,分解成“接收事务”、“更新库存清单”和“处理定货”3个处理之后(见图3.6),它们的输入/输出数据流仍然是“事务”、“库存清单”和“定货信息”。

此外,还应该注意在图3.6中对处理进行编号的方法。处理1.1,1.2和1.3是更高层次的数据流图(见图3.5)中处理1的组成元素。如果处理2被进一步分解,它的组成元素的编号将是2.1,2.2……如果把处理1.1进一步分解,则将得到编号为1.1.1,1.1.2……的处理。

3.5.3 命名

数据流图中每个成分的命名是否恰当,直接影响数据流图的可理解性,因此,给这些成分命名时应该仔细推敲。下面介绍在命名时应注意的问题。

1.为数据流(或数据存储)命名

  • 名字应代表整个数据流(或数据存储)的内容,而不是仅仅反映它的某些成分。
  • 不要使用空洞的、缺乏具体含义的名字(如“数据”、“信息”、“输入”之类)。
  • 如果在为某个数据流(或数据存储)起名字时遇到了困难,则很可能是因为对数据流图分解不恰当造成的,应该试试重新分解,看是否能克服这个困难。

2.为处理命名

  • 通常先为数据流命名,然后再为与之相关联的处理命名。这样命名比较容易,而且体现了人类习惯的“由表及里”的思考过程。
  • 名字应该反映整个处理的功能,而不是它的一部分功能。
  • 名字最好由一个具体的及物动词加上一个具体的宾语组成。应该尽量避免使用“加工”、“处理”等空洞笼统的动词作为名字。
  • 通常名字中仅包括一个动词。如果必须用两个动词才能描述整个处理的功能,则把这个处理再分解成两个处理可能更恰当些。
  • 如果在为某个处理命名时遇到困难,则很可能是发现了分解不当的迹象,应考虑重新分解。

数据源点/终点并不需要在开发目标系统的过程中设计和实现,它并不属于数据流图的核心内容,只不过是目标系统的外围环境部分(可能是人员、计算机外部设备或传感器装置)。通常,为数据源点/终点命名时采用它们在问题域中习惯使用的名字(如“采购员”、“仓库管理员”等)。

3.6 状态转换图

根据本章3.1节讲述的第3条分析准则,在需求分析过程中应该建立起目标系统的行为模型。状态转换图(简称状态图)通过描绘系统的状态及引起系统状态转换的事件,来表示系统的行为。此外,状态图还指出了作为特定事件的结果系统将做哪些动作(如处理数据)。因此,状态图提供了行为建模机制,可以满足第3条分析准则的要求。

3.6.1 状态

状态是任何可以被观察到的系统行为模式,一个状态代表系统的一种行为模式。状态规定了系统对事件的响应方式。系统对事件的响应,既可以是做一个(或一系列)动作,也可以是仅仅改变系统本身的状态,还可以是既改变状态又做动作。

在状态图中定义的状态主要有:初态(即初始状态)、终态(即最终状态)和中间状态。在一张状态图中只能有一个初态,而终态则可以有0至多个。

状态图既可以表示系统循环动作过程,也可以表示系统单程生命期。当描绘循环运行过程时,通常并不关心循环是怎样启动的。当描绘单程生命期时,需要标明初始状态(系统启动时进入初始状态)和最终状态(系统运行结束时到达最终状态)。

3.6.2 事件

事件是在某个特定时刻发生的事情,它是对引起系统做动作或(和)从一个状态转换到另一个状态的外界事件的抽象。例如,内部时钟表明某个规定的时间段已经过去,用户移动鼠标、点击鼠标等都是事件。简而言之,事件就是引起系统做动作或(和)转换状态的控制信息。

3.6.3 符号

在状态图中,初态用实心圆表示,终态用一对同心圆(内圆为实心圆)表示。中间状态用圆角矩形表示,可以用两条水平横线把它分成上、中、下3个部分。上面部分为状态的名称,这部分是必须有的;中间部分为状态变量的名字和值,这部分是可选的;下面部分是活动表,这部分也是可选的。

活动表的语法格式如下:

事件名(参数表)/动作表达式

其中,“事件名”可以是任何事件的名称。在活动表中经常使用下述3种标准事件:entry、exit和do。entry事件指定进入该状态的动作,exit事件指定退出该状态的动作,而do事件则指定在该状态下的动作。需要时可以为事件指定参数表。活动表中的动作表达式描述应做的具体动作。状态图中两个状态之间带箭头的连线称为状态转换,箭头指明了转换方向。状态变迁通常是由事件触发的,在这种情况下应在表示状态转换的箭头线上标出触发转换的事件表达式。

如果在箭头线上未标明事件,则表示在源状态的内部活动执行完之后自动触发转换。事件表达式的语法如下:

事件说明[守卫条件]/动作表达式

其中,事件说明的语法为:事件名(参数表)。

守卫条件是一个布尔表达式。如果同时使用事件说明和守卫条件,则当且仅当事件发生且布尔表达式为真时,状态转换才发生。如果只有守卫条件没有事件说明,则只要守卫条件为真状态转换就发生。

动作表达式是一个过程表达式,当状态转换开始时执行该表达式。

图3.7所示为状态图中使用的主要符号。

0307

图3.7 状态图中使用的主要符号

3.6.4 例子

为了具体说明怎样用状态图建立系统的行为模型,下面举一个例子。图3.8所示为人们非常熟悉的电话系统的状态图。

图中表明,没人打电话时电话处于闲置状态;有人拿起听筒则进入拨号音状态,这时电话的行为是响起拨号音并计时;如果拿起听筒的人改变主意不想打电话了,他把听筒放下(挂断),电话重又回到闲置状态;如果拿起听筒很长时间不拨号(超时),则进入超时状态……

读者对电话都很熟悉,无须仔细解释也很容易看懂图3.8所示的状态图,因此,这里不再逐一讲述图中每个状态的含义,以及状态间的转换过程了。

0308

图3.8 电话系统的状态图

3.7 数据字典

如前所述,分析模型包括数据模型、功能模型和行为模型。在上述任何一种模型中,数据对象或控制信息都有重要作用,因此,需要有一种系统化的方式来表示每个数据对象和控制信息的特性,数据字典正是用来完成这项任务的。

数据字典是为了描述在结构化分析过程中定义对象的内容时,使用的一种半形式化的工具。下面是对这个重要的建模工具的定义。

数据字典是所有与系统相关的数据元素的有组织的列表,并且包含了对这些数据元素的精确、严格的定义,从而使得用户和系统分析员双方对输入、输出、存储的成分甚至中间计算结果有共同的理解。简而言之,数据字典是描述数据的信息的集合,是对系统中使用的所有数据元素的定义的集合。

目前,数据字典几乎总是作为CASE“结构化分析与设计工具”的一部分实现的。尽管不同工具中数据字典的形式不同,但是绝大多数数据字典都包含下列信息。

  • 名字:数据、控制项、数据存储或外部实体的主要名称。
  • 别名:第1项中所列诸对象的其他名字。
  • 使用地点与方式:使用数据或控制项的处理的列表,以及使用这些对象的方式(如作为处理的输入,从处理输出,作为数据存储,作为外部实体)。
  • 内容描述:描述数据或控制项内容的符号。
  • 补充信息:关于数据类型、预置值、限制等的其他信息。

一旦把数据对象或控制项的名字和别名输入数据字典,就可以保持命名的一致性。也就是说,支持数据字典的CASE工具能够发现重名现象并发出警告信息,这提高了分析模型的一致性,有助于减少错误。

“使用地点与方式”信息是从数据流图中自动提取的。表面看起来,数据字典工具的这项功能好像并不重要,实际上这是数据字典的最主要优点之一。在分析过程中几乎始终在进行修改。但对于大型项目来说,确定修改的影响往往很困难。许多软件工程师都遇到过下述问题:“这个数据对象在什么地方使用?如果修改了它,相应地还应该再修改哪些对象?这个改动在整体上有什么影响?”利用数据字典中的“使用地点与方式”信息,完全可以回答上述问题。

下面介绍用于书写“内容描述”信息的符号,也就是定义数据的方法。定义绝大多数复杂事物的方法,都是用被定义事物成分的某种组合来表示这个事物,这些组成成分又由更低层的成分的组合来定义。从这个意义上说,定义就是自顶向下的分解,所以数据字典中的定义,就是对数据自顶向下的分解。那么,应该把数据分解到什么程度呢?一般说来,当分解到不需要进一步定义,每个和工程有关的人也都清楚其含义的元素时,这种分解过程就完成了。由数据元素组成数据的方式只有下述3种基本类型。

  • 顺序:以确定次序连接两个或多个分量。
  • 选择:从两个或多个可能的元素中选取一个。
  • 重复:把指定的分量重复零次或多次。

因此,可以使用上述3种关系算符定义数据字典中的任何条目。为了说明重复次数,重复算符通常和重复次数的上限和下限同时使用(当上限和下限相同时表示重复次数固定)。当重复的上限和下限分别为1和0时,可以用重复算符表示某个分量是可选的(可有可无的)。但是,“可选”是由数据元素组成数据时的一种常见的方式,把它单独列为一种算符可以使数据字典更清晰一些。因此,增加了下述的第4种关系算符:

  • 可选:即一个分量是可有可无的(重复零次或一次)。

虽然可以使用自然语言描述由数据元素组成数据的关系,但是为了更加清晰简洁起见,建议采用下列符号:

=意思是等价于(或定义为);

+意思是和(即连接两个分量);

[ ] 意思是或(即从方括弧内列出的若干个分量中选择一个),通常用“|”号分开供选择的分量;

{ } 意思是重复(即重复花括弧内的分量);

( ) 意思是可选(即圆括弧里的分量可有可无)。常常使用上限和下限进一步注释表示重复的花括弧。一种注释方法是在开括弧的左边用上角标和下角标分别表明重复的上限和下限;另一种注释方法是在开括弧左侧标明重复的下限,在闭括弧的右侧标明重复的上限。例如,51{A}和1{A}5含义相同。

下面举例说明上述描述数据内容的符号的使用方法:某种程序设计语言规定,用户说明的标识符是长度不超过8个字符的字符串,第1个字符必须是字母字符,随后的字符既可以是字母字符也可以是数字字符。利用上面讲述的符号,可以像下面那样定义标识符:

标识符   = 字母字符+字母数字串

字母数字串 = 0{字母或数字}7

字母或数字 = [字母字符|数字字符]

由于和项目有关的人都知道字母字符和数字字符的含义,因此,关于标识符的定义分解到这种程度就可以结束了。

在开发大型软件系统的过程中,数据字典的规模和复杂程度迅速增加,事实上,人工维护数据字典几乎是不可能的,因此,应该使用CASE工具来创建和维护数据字典。

3.8 结构化分析实例

初次学习软件工程的读者,往往感到书中讲述的系统分析过程和方法比较空洞、难于掌握。为帮助读者深入具体地理解系统分析的过程和方法,本节详细讲述一个结构化分析的实际例子。

3.8.1 问题陈述

某校财务科长要求系统分析员研究一下用学校自己的计算机生成工资明细表和各种财务报表的可能性。请问,系统分析员怎样用结构化分析技术完成这项工作?

通常,结构化分析过程包括问题定义、可行性研究和需求分析3个阶段,这3个阶段的工作基本上是按顺序完成的。下面分别叙述这3个阶段的分析过程。

3.8.2 问题定义

从何处着手解决财务科长提出的问题呢?立即开始考虑实现工资支付系统的详细方案并动手编写程序,对技术人员无疑是很有吸引力的。但是,在这样的早期阶段就考虑具体的技术问题,却很可能会使我们迷失前进的方向。会计部门(用户)并没有要求在学校自己的计算机上实现工资支付系统,仅仅要求研究这样做的可能性。后者是和前者很不相同的问题,它实际上是问,这样做预期将获得的经济效益能超过开发这个系统的成本吗?换句话说,这样做值得吗?

优秀的系统分析员还应该进一步考虑,用户面临的问题究竟是什么。财务科长为什么想研究在自己的计算机上实现工资支付系统的可能性呢?询问财务科长后得知,该校一直由会计人工计算工资并编制财务报表,随着学校的规模扩大,工作量也越来越大。目前每个月都需要两名会计紧张工作半个月才能完成,不仅效率低而且成本高。今后学校规模将进一步扩大,人工计算工资的成本还会进一步提高。

因此,目标是寻找一种比较便宜的生成工资明细表和各种财务报表的办法,并不一定必须在学校自己的计算机上实现工资支付系统。财务科长提出的要求,实际上并没有描述应该解决的问题,而是在建议一种解决问题的方案。这种解决方案可能是一个好办法,分析员当然应该认真研究它,但同时还应该考虑其他可能的解决方案,以便选出最好的方案。良好的问题定义应该明确地描述实际问题,而不是隐含地描述解决问题的方案。

分析员应该考虑的另一个关键问题,是预期的项目规模。为了改进工资支付系统最多可以花多少钱呢?虽然没人明确提出来,但是肯定会有某个限度。应该考虑下述3个基本数字:目前计算工资所花费的成本、新系统的开发成本和运行费用。新系统的运行费用必须低于目前的成本,而且节省的费用应该能使学校在一个合理的期限内收回开发新系统时的投资。

目前,每个月由两名会计用半个月时间计算工资和编制报表,一名会计每个月的工资和岗位津贴共约2 000元,每年为此项工作花费的人工费约2.4万元。显然,任何新系统的运行费用也不可能减少到小于零,因此,新系统每年最多可能获得的经济效益是2.4万元。

为了每年能节省2.4万元,投资多少钱是可以接受的呢?绝大多数单位都希望在3年内收回投资,因此,7.2万元可能是投资额的一个合理的上限值。虽然这是一个很粗略的数字,但是它确实能使用户对项目规模有一些了解。

为了请客户(会计科和学校校长)检验分析员对需要解决的问题和项目规模的认识是否正确,以便在双方达成共识的基础上开发出确实能满足用户实际需要的新系统,典型的做法是分析员用一份简短的书面备忘录表达他对问题的认识,这份文档称为“关于工资支付系统规模和目标的报告书”(见表3.2)。

表3.2 关于工资支付系统规模和目标的报告书2002.12.26

项 目 名 称

工 资 支 付

问题

目前计算工资和编制报表的费用太高

项目目标

研究开发费用较低的新工资支付系统的可能性

项目规模

开发成本应该不超过7.2万元(±50%)

初步设想

用学校自己的计算机系统生成工资明细表和财务报表

可行性研究

为了更全面地研究工资支付项目的可能性,建议进行大约历时两周的可行性研究。这个研究的成本不超过4 000元

校长和财务科经过研究同意了上述报告书,于是可以对工资支付项目进行更仔细的研究了。

3.8.3 可行性研究

可行性研究是抽象和简化了的系统分析和设计的全过程,它的目标是用最小代价尽快确定问题是否能够解决,以避免盲目投资带来的巨大浪费。

本项目的可行性研究过程由下述8个步骤组成。

1.澄清系统规模和目标

为了确保从一个正确的出发点着手进行可行性研究,首先通过访问财务科长和校长进一步验证上一阶段写出的“关于工资支付系统规模和目标的报告书”的正确性。

通过访问,分析员对人工计算工资存在的弊端有了更具体的认识,并且了解到工资总数应该记入分类日记账。显然,新工资支付系统不能忽略与分类账系统的联系。

2.研究现有的系统

了解任何应用领域的最快速有效的方法,就是研究现有的系统。通过访问具体处理工资事务的两名会计,可以知道处理工资事务的大致过程。开始时把工资支付系统先看做一个黑盒子,图3.9所示的系统流程图描绘了处理工资事务的大致过程。

处理工资事务的大致过程是,每月月末教师把他们当月实际授课时数登记在课时表上,由各系汇总后交给财务科;职工把他们当月完成承包任务的情况登记在任务表上,汇总后交给财务科。两名会计根据这些原始数据计算每名教职工的工资,编制工资表、工资明细表和财务报表。然后,把记有每名教职工工资总额的工资表报送银行,由银行把钱打到每名教职工的工资存折上,同时把工资明细表发给每名教职工。

接下来应该搞清楚图3.9中黑盒子(工资支付系统)的内容。

0309

图3.9 处理工资事务的大致过程

通过反复询问财务人员,可以知道现有的人工系统计算工资和编制报表的流程如下:接到课时表和任务表之后,首先审核这些数据,然后把审核后的数据按教职工编号排序并抄到专用的表格上,该表格预先印有教职工编号、姓名、职务、职称、基本工资、生活补贴、书报费、交通费、洗理费等数据。接下来根据当月课时数或完成承包任务情况,计算课时费或岗位津贴。算出每个人的工资总额之后,再计算应该扣除的个人所得税,应交纳的住房公积金和保险费,最后算出每个人当月的实发工资数。把算出的上述各项数据登记到前述的专用表格上,就得到了工资明细表。然后对数据进行汇总,编制出各种财务报表,而工资表不过是简化的工资明细表,它只包含工资明细表中的教职工编号、姓名和实发工资这3项内容。图3.10所示的系统流程图描绘了现有的人工工资支付系统的工作流程。

必须请有关人员仔细审查图3.10所示的系统流程图,有错误及时纠正,有遗漏及时补充。

0310

图3.10 现有的工资支付系统

3.导出高层逻辑模型

系统流程图很好地描绘了具体的系统,但在这样的流程图中把“做什么”和“怎样做”这两类不同范畴的知识混在一起了。我们的目标不是一成不变地复制现有的人工系统,而是开发一个能完成同样功能的新系统,因此,应该着重描绘系统的逻辑功能。

删除图3.10中表示的有关具体实现方法的信息,把它抽象成图3.11所示的数据流图。在这张数据流图中用“事务数据”代表课时表和任务表中包含的数据,用“加工事务数据”笼统地代表计算课时费、岗位津贴、工资总额、个人所得税、住房公积金、保险费、实发工资等一系列功能。这张数据流图描绘的是系统高层逻辑模型,在可行性研究阶段还不需要考虑完成“加工事务数据”功能的具体算法,因此,没必要把它分解成一系列更具体的数据处理功能。

0311

图3.11 工资支付系统的数据流图

在图3.11中的处理框“更新分类账”虽然不属于本系统应完成的功能,但是工资支付系统至少必须和“更新分类账”所在的系统通信,因此,搞清楚它们之间的接口要点是很重要的。

在数据流图上直接注明关键的“定时假设”很有必要,在以后的系统设计过程中这些假设将起重要作用。清楚地注明这些假设也可以增加及时发现和纠正误解的可能性。

4.进一步确定系统规模和目标

现在,分析员再次访问会计和财务科长,讨论的焦点集中在图3.11所示的数据流图,它代表了到现在为止分析员对所要开发的系统的认识。通过仔细分析和讨论数据流图,能够及时发现并纠正分析员对系统的误解,补充被忽视了的内容。

分析员现在对工资支付系统的认识已经比问题定义阶段深入多了,根据现在的认识,可以更准确地确定系统规模和目标。如果系统规模有较大变化,则应及时报告给客户,以便做出新的决策。

可行性研究的上述4个步骤可以看做是一个循环。分析员定义问题,分析这个问题,导出试探性的逻辑模型,在此基础上再次定义问题……重复这个循环直至得出准确的逻辑模型为止,然后分析员开始考虑实现这个系统的方案。

5.导出供选择的解法

现在分析员对用户的问题已经有了比较深入的理解,但问题有行得通的解决办法吗?

回答这个问题的唯一方法是,导出一些供选择的解法,并且分析这些解法的可行性。导出供选择解法的一个常用方法是从数据流图出发,设想几种划分自动化边界的模式,并且为每种模式设想一个系统。

在分析供选择的解法时,首先考虑的是技术上的可行性。显然,从技术角度看不可能实现的方案是没有意义的。但是,技术可行性只是必须考虑的一个方面,还必须能同时通过其他检验,这种方案才是可行的。

接下来考虑操作可行性。例如,在对学生开放的公共计算机房内运行工资支付程序显然是不合适的。这样做不仅不安全,而且会暴露教职工的个人隐私。因此,必须为工资支付系统单独购置一台计算机及必要的外部设备,并且放在一间专用的房间里。

最后,必须考虑经济可行性问题,即“效益大于成本吗?”分析员必须对已经通过了技术可行性和操作可行性检验的解决方案再进行成本/效益分析。

分析员在进行成本/效益分析的时候必须认识到,投资是现在进行的,效益是将来获得的,因此,不能简单地比较成本和效益,应该考虑货币的时间价值。

通常用利率的形式表示货币的时间价值。假设年利率为i,如果现在存入P元,则n年后可以得到的钱数为:F = P(1+i)n

这也就是P元钱在n年后的价值。反之,如果n年后能收入F元钱,那么这些钱的现在价值是:P = F(1+i)n

为了给客户提供在一定范围内进行选择的余地,分析员应该至少提出3种类型的供选择方案:低成本系统、中等成本系统和高成本系统。

如果把每月发一次工资改为每两个月发一次工资,则人工计算工资的成本大约可减少一半,即每年可节省1.2万元。除了已经进行的可行性研究的费用外,不再需要新的投资。这是一个很诱人的低成本方案。

当然,也必须充分认识上述低成本方案的缺点:违反常规;教职工反对;不能解决根本问题。随着学校规模扩大,人工处理工资事务的费用也将成比例地增加。

作为中等成本的解决方案,建议基本上复制现有系统的功能:课时表和任务表交到处理工资事务的专用机房,操作员把这些数据通过终端送入计算机,数据收集程序接收并校核这些事务数据,把它们存储在磁盘上。然后运行工资支付程序,它从磁盘中读取事务数据,计算工资,打印出工资表、工资明细表和财务报表。图3.12所示的系统流程图描绘了上述系统。

0312

图3.12 中等成本方案的系统流程图

上述中等成本方案看起来比较现实,因此,对它进行了完整的成本/效益分析,分析结果列在表3.3中。从分析结果可以看出,中等成本的解决方案是比较合理的,经济上是可行的。

表3.3 中等成本方案的成本/效益分析

开发成本
人力(4人月,8 000元/人月) 3.2万元
购买硬件 1.0万元
总计 4.2万元
新系统的运行费用  
人力和物资(250元/月) 0.3万元/年
维护 0.1万元/年
总计 0.4万元/年
现有系统的运行费用 2.4万元/年
每年节省的费用 2.0万元
节 省 现在值(以5%计算) 累计现在值
1 20 000元 19 047.62元 19 047.62元
2 20 000元 18 181.82元 37 229.44元
3 20 000元 17 241.38元 54 470.82元
投资回收期 2.28年
纯收入 12 470.82元

最后,考虑一种成本更高的方案:建立一个中央数据库,为开发完整的管理信息系统做好准备,并且把工资支付系统作为该系统的第1个子系统。这样做开发成本大约将增加到12万元,然而从工资支付这项应用中获得的经济效益并不变,如果仅考虑这一项应用,投资是不划算的。但是,将来其他应用系统(如教学管理,物资管理,人力资源管理)能以较低成本实现,而且这些子系统能集成为一个完整的系统。如果校长对这个方案感兴趣,可以针对它完成更详尽的可行性研究(费用大约需要用1万元)。

6.推荐最佳方案

低成本方案虽然诱人,但是很难付诸实现;高成本的系统从长远看是合理的,但是它所需要的投资超出了预算。从已经确定的系统规模和目标来看,显然中等成本的方案是最好的。

7.草拟开发计划

应该为推荐的最佳方案草拟一份开发计划。把系统生命周期划分成阶段,有助于制定出相对合理的计划。当然,在这样的早期开发阶段,制定出的开发计划是比较粗略的,表3.4所示为实现中等成本的工资支付系统的粗略计划。

表3.4 实现中等成本的工资支付系统的粗略计划

阶  段

需要用的时间(月)

可行性研究

0.5

需求分析

1.0

概要设计

0.5

详细设计

1.0

实现

2.0

总计

5.0

8.写出文档提交审查

分析员归纳整理本阶段的工作成果,写成正式文档(其中成本/效益分析的内容,根据表3.4所示的实现计划适当修正),提交由校长和财务科全体人员参加的会议审查。

3.8.4 需求分析

需求分析的目的是确切地回答:“系统必须做什么?”

需求分析在可行性研究的基础上进行。前一阶段产生的文档,特别是数据流图(见图3.11),是需求分析的出发点。在需求分析过程中分析员将设计出更精确的数据流图,并将写出数据字典及一系列简明的算法描述,它们都是软件需求规格说明书的重要组成部分。

需求分析的主要任务是更详尽地定义系统应该完成的每一个逻辑功能。怎样完成这个任务呢?

任何数据处理系统的基本功能,都是把输入数据转变成需要的输出信息。数据决定了处理和算法,看来数据应该是分析工作的出发点。必须经过计算才能得到的数据元素引出了必要的算法,算法反过来又引出了更多的数据元素。对数据的描述,记录在数据字典中;对算法的描述,记录在一组初步的IPO表中(目前描述的是说明数据处理功能的原理性算法,本书4.5.1小节将仔细介绍IPO表)。

对系统有了更深入的认识之后,可以进一步细化数据流图。在细化数据流图的过程中,又会进一步加深对系统的认识。这样一步一步地分析,将更详尽、更准确地定义出所需要的逻辑系统。

下面叙述工资支付系统的需求分析过程。

1.沿数据流图回溯

为了把数据流和数据存储定义到元素级,一般说来,从数据流图的输出端着手分析是有意义的。这是因为,系统最基本的功能是产生需要的输出数据,在输出端出现的数据元素决定了系统的基本构成。

从图3.11的数据终点“教师”和“职工”开始分析,流入他们的数据流是“工资明细表”。工资明细表由哪些数据元素组成呢?从该校目前使用的工资明细表上可以看出它包含许多数据元素,表3.5列出了这些数据元素。这些数据元素是从什么地方来的呢?既然它们是工资支付系统的输出,它们或者是从外面输入进系统的,或者是由系统经过计算产生出来的。沿数据流图从输出端往输入端回溯,分析员应该可以确定每个数据元素的来源。如果分析员不能确定某个数据元素的来源,那么需要再次调查访问。这样有条不紊地分析下去,分析员将逐渐定义出系统的详细功能。

表3.5 工资明细表上包含的数据元素

教职工编号 职称 洗理费 个人所得税
教职工姓名 生活补贴 课时费 住房公积金
基本工资 书报费 岗位津贴 保险费
职务 交通费 工资总额 实发工资

例如,表3.5中的数据元素“工资总额”是怎样得出来的呢?从图3.11可以看出,包含数据元素“工资总额”的工资明细表,是从处理4(“分发工资明细表”)输出到数据终点的,但是这个处理的功能是分发已经打印好的工资明细表,并不能生成新的数据元素。沿着数据流图回溯(即逆着数据流箭头方向前进),接下来遇到数据存储D3(“工资明细表”)。不过数据存储只是保存数据的介质,它不具有变换数据的功能,因此也不会生成工资总额这项数据元素。再回溯则来到处理3(“加工事务数据”)。显然,工资总额是由这个处理框计算出来的,因此应该确定相应的算法,以便更准确地定义这个处理框的功能。

根据常识,工资总额等于各项收入(基本工资、生活补贴、书报费、交通费、洗理费、课时费或岗位津贴)之和。虽然不同教职工的基本工资、生活补贴、书报费、交通费和洗理费的数额可能并不相同,但是对同一个人来说,在一段时间内这些数值是稳定不变的,不需要在每次计算工资总额时都从外面输入这些数据。事实上,在输入的事务数据中并不包含这些数据元素,因此,它们必定保存在某个数据存储中。目前,还不知道这些数据保存在何处,分析员在笔记本中记下“必须搞清楚基本工资、生活补贴、书报费、交通费、洗理费等数据元素存储在何外”。此外,为了计算工资总额必须先计算课时费或岗位津贴,分析员在笔记本中记下“必须弄清课时费和岗位津贴的计算方法”。然后,着手分析另一个重要的数据元素“实发工资”。

显然,从工资总额中扣除个人所得税、住房公积金和保险费之后,余下的就是实发工资。沿数据流图回溯可知,个人所得税、住房公积金和保险费的数值都由处理3(“加工事务数据”)计算得出。但是,目前还不知道怎样计算这些数值,分析员在笔记本中记下“必须搞清楚个人所得税、住房公积金和保险费的计算方法”。

2.写出文档初稿

分析员在分析过程中不断加深对目标系统的认识,应该把获得的信息用一种容易修改、容易更新的形式记录下来。

通常,一个系统会涉及许多人,他们彼此理解是至关重要的。文档是主要的沟通工具,因此,文档必须是一致的和容易理解的。结构化分析方法要求,在需求分析阶段完成的正式文档(软件需求规格说明书)中必须至少包含3个重要成分:数据流图、数据字典,以及一组黑盒形式的算法描述。

数据字典是描述数据的信息的集合。在分析阶段数据字典能帮助分析员组织有关数据的信息,并且是和用户交流信息的有力工具。此外,它还能起备忘录的作用。在设计阶段,可以根据它确定记录、文件或数据库的格式;在实现阶段,程序员可以根据数据字典确定数据描述;在系统投入运行以后,数据字典可以清楚地告诉维护人员,具体的数据元素在系统中是怎样使用的。当必须修改程序时,这样的信息是极其宝贵的。

在手边没有数据字典软件包可用时,可以用卡片形式人工建立数据字典。例如,为工资支付系统中几个数据元素填写的数据字典卡片如图3.13所示。

0313

图3.13 工资支付系统的数据字典卡片

分析员还应该以黑盒形式记录算法。所谓黑盒子就是不考虑一个功能的具体实现方法,只把它看做给予输入之后就能够产生一定输出的盒子。这正是在早期开发阶段分析员对算法应持有的正确观点,目的是用原理性算法准确地定义功能,算法的细节可以等到以后的开发阶段再确定。

通常使用IPO表记录对算法的初步描述,以后可以进一步精化它,而且在详细设计阶段可以把它作为HIPO图的一部分(本书4.5.1小节将介绍HIPO图)。图3.14所示为描述计算工资总额初步算法的IPO表。

0314

图3.14 描述工资总额初步算法的IPO表

至此写出的文档还仅仅是初稿。写文档初稿的目的,一方面是记录已经知道的信息,另一方面是供用户审查。随着需求分析工作的深入,这些文档还将进一步修改完善。

3.定义逻辑系统

通过前一步的工作,已经划分出许多必须在工资支付系统中流动的数据元素,并且把它们记录在初步的数据字典中。此外,还把某些算法以黑盒形式记录在IPO表中。上述这些工作成果正确吗?某些数据元素(如基本工资、生活补贴、书报费、交通费、洗理费)是从哪里来的呢?分析员必须设法得到这些问题的答案。

关于工资支付系统的详细信息只能来源于直接工作在这个系统上的人,因此,再次访问财务科长和具体处理工资事务的两位会计。数据流图(见图3.11)是使讨论时焦点集中的极好工具,从数据流图的数据源点开始,沿着数据流循序讨论。事务数据从教职工流进收集数据这个处理中,以前已经在数据字典中描述了组成事务数据的元素(图3.13中未列出这张卡片),这个描述正确吗?有没有遗漏?“收集数据”的功能是什么?审核数据的算法是什么?……对于分析员来说,数据流图、数据字典和算法描述可以作为校核时的清单或备忘录。必须审核已经知道的信息,还必须补充目前尚不知道的信息,填补文档中的空白。

例如,考虑工资总额的算法。假设分析员和会计正在讨论数据流图中“加工事务数据”这个处理。在前一步骤中已经用IPO表(见图3.14)描述了计算工资总额的算法,并且知道基本工资、生活补贴、书报费、交通费、洗理费等数据应该存储起来。那么,它们到底存储在哪个数据存储中呢?会计说,这些数据属于人事数据。但是,在图3.11所示的数据流图中并没有一个数据存储保存人事数据,显然应该修改数据流图,补充进这个数据存储。这样一步一步地分析数据流找出未知的数据元素,未知的数据元素引出访问时的问题,而问题的答案又引入一个以前不知道的系统成分——人事数据存储。

人事数据存储是从哪里进入系统的呢?经询问得知,这些数据的来源是人事科,而且需要增加一个新的处理——更新人事数据。

接下来讨论计算课时费和岗位津贴的方法。会计告诉分析员,课时费等于教师当月的授课时数乘上每课时的课时费,再乘上职称系数和授课班数系数;岗位津贴由职工的职务和完成当月任务的情况决定。通过讨论还进一步了解到,应在每年年末计算超额课时费。也就是说,如果一位教师一年的授课时数超过学校规定的定额,则超出部分每课时的课时费按正常值的1.2倍计算。显然,为了计算超额课时费需要保存每位教师当年完成的授课时数,也就是说,需要一个数据存储来存放“年度数据”。

接下来讨论“加工事务数据”这个处理需要的其他算法。例如,在讨论住房公积金的算法时了解到,根据国务院2002年3月24日修订的《住房公积金管理条例》的规定,“职工住房公积金的月缴存额为职工本人上一年度月平均工资乘以职工住房公积金缴存比例”,“职工和单位住房公积金的缴存比例均不得低于职工上一年度月平均工资的5%”。因此,需要存储每名教职工上一年度的月平均工资。显然,这个数据元素也应该存储在“年度数据”中。表3.6所示为年度数据包含的数据元素。相应地,应该增加一个处理(“更新年度数据”)在每年年末更新年度数据。

表3.6 年度数据包含的数据元素

教职工编号 本年度累计实发工资
教职工姓名 本年度累计授课时数
本年度累计工资总额 上年度月平均工资

最后,把新发现的数据源点、数据处理和数据存储补充到数据流图中,得到新的数据流图(见图3.15)。

0315

图3.15 补充后的工资支付系统数据流图

4.细化数据流图

经过上述工作分析员对工资支付系统已经有了更深入、更具体的认识,原有的数据流图已经不能充分表达他对系统的认识,应该进一步地细化数据流图。

选取数据流图上功能过分复杂的处理,把它分解成若干个子功能,这些较低层次的子功能成为新数据流图上的处理,它们有自己的数据存储和数据流。

例如,图3.15中“加工事务数据”这个处理的功能太复杂了,用一个处理框不能清晰地描绘它的功能,应该把它进一步分解细化。根据分析员现在对加工事务数据功能的了解,把这个处理分解成下述5个逻辑功能。

① 取数据:取出事务数据、人事数据和年度数据。

② 计算正常工资:计算不包含超额课时费的工资。

③ 计算超额课时费:年终计算超额课时费,算得的钱数加到12月份的工资总额中。

④ 更新年度数据:每月工资总额、实发工资及授课时数累加到相应的年度数据中,并在年终计算本年度的月平均工资。

⑤ 印表格:印出工资表、工资明细表和各种财务报表。

上述5个子功能及它们之间的关系,可以用一张数据流分图来描绘(见图3.16)。把分解“加工事务数据”处理框的结果加到原来的数据流图中,得到一张更详细的新数据流图(见图3.17)。

0316

图3.16 对“加工事务数据”的细化

新数据流图对工资支付系统的逻辑功能描绘得比以前更深入、更具体了。分析本系统其他处理功能后得知,对于这个具体系统来说,已经没有必要再分解其他功能了。一般说来,如果进一步分解将促使你开始考虑为了完成该功能需要写出的代码,就不应该再分解了。在需求分析阶段分析员应该只在逻辑功能层工作,代码已经属于物理实现层了。

5.书写正式文档

数据流图细化之后,组成系统的各个元素之间的逻辑关系变得更清楚了。以细化后的数据流图为基础,可以对系统需求做更进一步地分析。随着分析过程的进展,通过询问与回答的反复循环,会把目标系统定义得越来越准确。最终,分析员对系统需求有了令人满意的认识,应该把这些认识用正式文档“软件需求规格说明书”准确地记录下来。细化到适当层次的数据流图、数据字典和黑盒形式的算法描述,是构成软件需求规格说明书的重要成分。

6.技术审查和管理复审

由从外单位聘请来的一位有经验的系统分析员担任组长,并由具体处理工资事务的两名会计及本系统的分析员作为小组成员,组成技术审查小组。图3.17所示的数据流图是审查的重点;用数据字典和IPO表辅助对数据流图的理解。作为小组组员的一名会计朗读软件需求规格说明书,大家仔细审查这份文档。审查的目的是发现错误或遗漏,而不是对前一阶段的工作进行批评或争论。本系统的分析员负责改正审查小组发现的问题。

0317

图3.17 工资支付系统完整的数据流图

除了技术审查之处,在转入概要设计之前还必须进行管理方面的复审。由财务科长和学校校长对本项目的经费支出情况和开发进度,从管理角度进行审查。

小结

传统的软件工程方法学使用结构化分析技术,完成分析用户需求的工作。需求分析是发现、求精、建模、规格说明和复审的过程。需求分析的第一步是了解用户当前所处的情况,发现用户所面临的问题。接下来应该通过与用户交流,对用户的基本需求反复细化,以得出对目标系统的完整、准确和具体的需求。

为了详尽地了解并正确地理解用户的需求,必须使用适当的方法与用户沟通和交流。访谈是历史悠久的与用户沟通方法,至今仍被系统分析员广泛采用。为了促使用户与分析员密切合作共同分析需求,人们研究出一种面向团队的需求收集法,称为“简易的应用规格说明技术”。现在,这种技术已经成为信息系统界使用的主流技术。实践表明,快速建立软件原型是最准确、最有效和最强大的需求分析技术。快速原型应该具备的基本特性是“快速”和“容易修改”,因此,必须有适当的软件工具支持快速原型技术。通常使用第四代技术、可重用的软件构件及形式化规格说明与原型环境等工具,快速地构建和修改原型。

为了更好地理解问题,人们常常采用建立模型的方法,结构化分析实质上就是一种建模活动,通常建立数据模型、功能模型和行为模型。在需求分析阶段建立起来的模型,在软件开发过程中有许多重要作用。

  • 模型能帮助分析员更好地理解软件系统的信息、功能和行为,从而使得需求分析工作更容易完成,使需求分析的结果更系统化。
  • 模型是复审需求分析成果时的焦点,因此,也成为验证规格说明的完整性、一致性和准确性的重要依据。
  • 模型是设计的基础,为设计者提供了软件的实质性表示,通过设计工作将把这些表示转化成软件实现。

除了创建分析模型之外,在需求分析阶段还应该写出软件需求规格说明,经过认真评审并得到用户确认之后,作为这个阶段的最终成果。

通常,使用实体—关系图来建立数据模型,读者应该掌握这种图形的基本符号,能够正确地使用这些符号建立软件系统的数据模型。

数据流图是描绘信息流和数据从输入移动到输出的过程中所经受的变换的图形化技术。可以在任何抽象层次上使用数据流图来表示信息处理系统或软件。它是分析员与用户之间沟通、交流的有效工具,也是进行软件设计的极好出发点。由于结构化分析通常主要关注目标系统应该完成的逻辑功能,而数据流图提供了功能建模的基本机制,因此,数据流图是结构化分析过程中使用的最主要的建模工具。读者应该熟练掌握数据流图的基本符号,并能正确地使用这些符号建立目标系统的功能模型。

状态转换图通过描绘系统的状态及引起系统状态转换的事件,表示系统的行为,从而提供了行为建模的机制。

数据字典描述在数据模型、功能模型和行为模型中出现的数据对象和控制信息的特性,给出这些对象的精确定义。因此,数据字典成为把3种分析模型黏合在一起的“黏合剂”,是分析模型的“核心”。在开发大型软件系统的过程中,数据字典的规模和复杂程度都迅速增加,通常需要使用CASE工具来创建和维护数据字典。

本章最后讲述了一个结构化分析的实际例子。认真阅读并仔细思考这个例子,有助于读者更深入具体地理解用结构化技术完成系统分析工作的过程和方法,并逐步学会用结构化分析技术解决实际问题。

习题

一、判断题

1.需求规格说明书在软件开发中具有重要的作用,它也可以作为软件可行性分析的依据。                   

(  )

2.需求分析的主要目的是解决软件开发的具体方案。       

(  )

3.需求规格说明书描述了系统每个功能的实现。        

(  )

4.非功能需求是从各个角度对系统的约束和限制,反映了应用对软件系统质量和特性的额外要求。

(  )

5.需求评审人员主要由开发人员组成,一般不包括用户。

(  )

6.分层的DFD图可以用于可行性分析阶段,描述系统的物理结构。

(  )

7.信息建模方法是从数据的角度来建立信息模型的,最常用的描述信息模型的方法是E-R图。

(  )

8.用于需求分析的软件工具,应该能够保证需求的正确性,即验证需求的一致性、完整性、现实性和有效性。

(  )

9.需求分析是开发方的工作,用户的参与度不大。

(  )

二、选择题

1.需求工程的主要目的是(  )。

  A.系统开发的具体方案 B.进一步确定用户的需求

  C.解决系统是“做什么的问题” D.解决系统是“如何做的问题”

2.需求分析的主要方法有(  )。

  A.形式化分析方法  B.PAD图描述

  C.结构化分析SA方法 D.程序流程图

3.SA法的主要描述手段有(  )。

  A.系统流程图和模块图 B.DFD图、数据词典、加工说明

  C.软件结构图、加工说明 D.功能结构图、加工说明

4.画分层DFD图的基本原则有(  )。

  A.数据守恒原则 B.分解的可靠性原则

  C.子、父图平衡的原则 D.数据流封闭的原则

5.在E-R模型中,包含以下基本成分(  )。

  A.数据、对象、实体 B.控制、关系、对象

  C.实体、关系、控制 D.实体、属性、关系

6.在下面的叙述中哪一个不是软件需求分析的任务?(  )。

  A.问题分解  B.可靠性与安全性要求

  C.结构化程序设计   D.确定逻辑模型

7.需求规格说明书的作用不应包括(  )。

  A.软件设计的依据 

  B.用户与开发人员对软件要做什么的共同理解

  C.软件验收的依据

  D.软件可行性研究的依据

8.软件需求规格说明书的内容不应该包括(  )。

  A.对重要功能的描述 B.对算法的详细过程描述

  C.对数据的要求  D.软件的性能

9.软件需求分析阶段的工作,可以分为以下4个方面:对问题的识别、分析与综合、编写需求分析文档以及(  )。

  A.总结 B.阶段性报告 

  C.需求分析评审 D.以上答案都不正确

10.下述任务中,不属于软件工程需求分析阶段的是(  )。

  A.分析软件系统的数据要求 B.确定软件系统的功能需求

  C.确定软件系统的性能要求 D.确定软件系统的运行平台

11.进行需求分析可使用多种工具,但(  )是不适用的。

  A.数据流图 B.PAD图 C.状态转换图 D.数据词典

12.在需求分析之前有必要进行(  )工作。

  A.程序设计 B.可行性分析 C.ER分析 D.2NF分析

13.数据流图是进行软件需求分析的常用图形工具,其基本图形符号是(  )。

  A.输入、输出、外部实体和加工

  B.变换、加工、数据流和存储

  C.加工、数据流、数据存储和外部实体

  D.变换、数据存储、加工和数据流

14.在结构化分析方法中,用以表达系统内数据的运动情况的工具是(  )。

  A.数据流图 B.数据字典 C.结构化语言 D.判定表与判定树

三、简答题

1.如何理解需求分析的作用和重要性。

2.如何理解结构化需求分析方法的基本思想。

3.如何进行结构化需求分析,其建模方法都有哪些?

4.为什么需求分析特别重要?

5.需求分析的目的和工作目标是什么?

6.需求开发经过哪些步骤?每个步骤有何作用?

7.需求分析的难点在哪里?

8.需求分析的理论基础有哪些?

9.为什么说需求过程是一个迭代过程?

10.需求管理过程的目标和内容是什么?

11.用户需求报告与需求分析规格说明书有何差异?

12.需求评审的作用是什么?为什么必须评审?评审的标准是什么?

13.请简述可行性研究所研究的问题。

14.请简述数据流图的作用。

15.请简述数据字典的作用。

四、应用题

1.某旅馆的电话服务如下:可以拨分机号和外线号码。分机号是从7201至7299。外线号码先拨9,然后是市话号码或长话号码。长话号码是由区号和市话号码组成。区号是从100到300中任意的数字串。市话号码是以局号和分局号组成。局号可以是455、466、888、552中任意一个号码。分局号是任意长度为4的数字串。

请写出在数据字典中,电话号码数据条目的组成。

2.某银行计算机储蓄系统的工作流程大致如下:储户填写的存款单或取款单由业务员键入系统,如果是存款则系统记录存款人的姓名、住址(或电话号码)、身份证号码、存款类型、存款日期、到期日期、利率及密码(可选)等信息,并印出存款单给储户;如果是取款,而且存款时留有密码,则系统首先核对储户密码,若密码正确或存款时未留密码,则系统计算利息并印出利息清单给储户。

请用数据流图描绘本系统的功能。

3.有如下一个学生选课系统:教师提出开课计划,系统批准后给教师下发开课通知。学生可向系统提出选课申请,系统批准后给学生下发选课申请结果通知。课程结束后,系统还可以帮助教师录入学生成绩,同时把成绩单发送给学生。

请画出该系统顶层的数据流图。

4.办公室复印机的工作过程大致如下:未收到复印命令时处于闲置状态,一旦接收到复印命令则进入复印状态,完成一个复印命令规定的工作后又回到闲置状态,等待下一个复印命令:如果执行复印命令时发现缺纸,则进入缺纸状态,发出警告,等待装纸,装满纸后进入闲置状态,准备接收复印命令;如果复印时发生卡纸故障,则进入卡纸状态,

发出警告,等待维修人员来排除故障,故障排除后回到闲置状态。

请用状态转换图描绘复印机的行为。

目录

  • 版权
  • 内容提要
  • 出版者的话
  • 第4版前言
  • 第1篇 软件工程与软件过程
  • 第1章 软件工程概述
  • 第2章 软件过程
  • 第2篇 传统方法学
  • 第3章 结构化分析
  • 第4章 结构化设计
  • 第5章 结构化实现
  • 第3篇 面向对象方法学
  • 第6章 面向对象方法学导论
  • 第7章 面向对象分析
  • 第8章 面向对象设计
  • 第9章 面向对象实现
  • 第10章 统一建模语言
  • 第4篇 软件项目管理
  • 第11章 计划
  • 第12章 组织
  • 第13章 控制
  • 第14章 软件维护与软件文档
  • 第5篇 高级课题
  • 第15章 形式化方法
  • 第16章 软件重用
  • 参考文献

推荐用户

同系列书

人邮微信
本地服务
教师服务
教师服务
读者服务
读者服务
返回顶部
返回顶部