系统设计(案例|论文)
系统设计是系统分析的延伸与拓展。系统分析阶段解决“做什么”的问题,而系统设计阶段解决“怎么做”的问题。
概要设计
系统设计的主要内容包括概要设计和详细设计。概要设计又称为系统总体结构设计,它是系统开发过程中很关键的一步,其主要任务是将系统的功能需求分配给软件模块,确定每个模块的功能和调用关系,形成软件的模块结构图,即系统结构图。在概要设计中,将系统开发的总任务分解成许多个基本的、具体的任务。
详细设计
为每个具体任务选择适当的技术手段和处理方法的过程称为详细设计。根据任务的不同,详细设计又可分为多种,例如,网络设计、代码设计、输入输出设计、处理流程设计、数据存储设计、用户界面设计、安全性和可靠性设计等。
用户界面设计
通常情况下,良好的用户界面设计需要遵循如下一些基本原则:
- ( 1 ) 置于用户控制之下。在定义人机交互方式时,不强迫用户采用不是必需的或者不情愿的方式来进行操作,允许交互的中断和撤销。
- ( 2 ) 减轻用户的记忆负担。尽量减轻对用户记忆的要求,创建有意义的默认设置,定义一些符合用户直觉的访问途径,适当定义一些快捷方式,视觉布局应该尽量与真实世界保持一致,并能够以不断扩展的方式呈现信息。
- ( 3 ) 保持界面一致性。用户应以一致的方式提供或获取信息,所有可视信息的组织需要按照统一的设计标准,在系列化的应用软件中需要保持一致性,用户已经很熟悉的一些界面交互模型不到万不得已时,不要随意进行修改。
以上三条原则由著名用户界面设计专家 Theo Mandel 博士所创造,通常称之为人机交互的“黄金三原则”。另外,在设计用户界面时,还需要保证界面的合理性和独特性,有效进行组合,注重美观与协调;恰到好处地提供快捷方式,注意资源协调等。
处理流程设计概述
处理流程设计的任务是设计出系统所有模块以及它们之间的相互关系,并具体设计出每个模块内部的功能和处理过程,为开发人员提供详细的技术资料。
流程设计概述
ISO 9000 定义业务流程(Business Process) 为一组将输入转化为输出的相互关联或相互作用的活动。流程具有目标性、内在性、整体性、动态性、层次性和结构性等特点。一般来说,流程包括 6 个基本要素,分别是输入资源、活动、活动的相互作用(结构)、输出结果、用户和价值。例如,在线教育平台系统中的“开通课程”流程,其 6 个要素。如表所示。
工作流管理系统
工作流管理系统(WFMS)通过软件定义、创建工作流并管理其执行。它运行在-个或多个工作流引擎上,这些引擎解释对过程的定义与工作流的参与者相互作用,并根据需要调用其他 IT 工具或应用。
WFMS 基本功能包括对工作流建模(定义活动和规则,对应现实业务处理过程)、工作流执行(创建和执行实际工作流)、业务过程管理和分析(监控管理执行中的业务情况)。
工作流参考模型(WRM ) 包含 6 个基本模块,分别是工作流执行服务、工作流引擎、流程定义工具、客户端应用、调用应用和管理监控工具。工作流参考模型(WRM ) 为工作流管理系统(WFMS)关键模块提供了功能描述,并描述了关键模块之间的交互,而且这个描述是独立于特定产品或技术的实现的。
流程设计工具
在处理流程设计过程中,为了清晰表达过程规则说明,常用的流程设计工具分为三类:图形工具、表格工具和语言工具。
大类 | 工具名称 | 描述 |
---|---|---|
图形工具 | 程序流程图 (PFD) | 用图框表示各种操作,独立于任何程序设计语言,直观且 易于掌握,但符号不规范、随意转移控制的问题需要改进。 |
N-S 图 (盒图) | 以方框代替传统的 PFD,包括顺序型、选择型、WHILE 循环型、UNTIL 循环型和多分支选择型控制结构,具有强烈的结构化特征。 | |
IPO 图 | 描述模块的输入、输出和数据加工,结构清晰,常用于系 统设计文档。 | |
问题分析图 (PAD) | 由日立公司提出,支持结构化程序设计,包含五种基本的控制结构,执行顺序明确,适合嵌套和层次关系的表示。 | |
判定树 | 用树形结构表示逻辑判断,条件和处理流程直观,适合复 杂条件判断。 | |
表格工具 | 判定表 | 结构清晰、简明,用表格形式表示逻辑判断问题,条件和行动一目了然,适合多个互相联系的条件和多种结果的描述。 |
语言工具 | 过程设计语言 (PDL) | 也称伪代码,混合自然语言词汇和结构化程序设计语言语法,用于描述处理过程,灵活且有助于逐步求精和详细设。 |
面向对象设计(重点)
面向对象设计(面向对象设计)是面向对象分析(OOA) 方法的延续,其基本思想包括抽象、封装和可扩展性,其中可扩展性主要通过继承和多态来实现。在面向对象设计 中,数据结构和在数据结构上定义的操作算法封装在一个对象之中。
设计类分类(重点)
在系统设计过程中,类可以分为三种类型:实体类、边界类和控制类。
- 实体类
实体类映射需求中的每个实体,实体类保存需要存储在永久存储体中的信息,例如, 在线教育平台系统可以提取出学员类和课程类,它们都属于实体类。实体类通常都是永久性的,它们所具有的属性和关系是长期需要的,有时甚至在系统的整个生存期都需要。
实体类是对用户来说最有意义的类,通常采用业务领域术语命名,一般来说是一个名词,在用例模型向领域模型的转化中,一个参与者一般对应于实体类。通常可以从**软件需求规格说明书(SRS)**中的那些与数据库表(需要持久存储)对应的名词着手来找寻实体类。通常情况下,实体类一定有属性,但不一定有操作。
- 控制类
控制类是用于控制用例工作的类,一般是由动宾结构的短语(“动词+名词” 或 “名 词+动词”)转化来的名词,例如,用例 “身份验证”可以对应于一个控制类“身份验证器”,它提供了与身份验证相关的所有操作。控制类用于对一个或几个用例所特有的控制行为进行建模,控制对象(控制类的实例)通常控制其他对象,因此它们的行为具有协调性。
控制类将用例的特有行为进行封装,控制对象的行为与特定用例的实现密切相关,系统执行用例的时候,就产生了一个控制对象,控制对象经常在其对应的用例执行完毕后消亡。通常情况下,控制类没有属性,但一定有方法。
- 边界类
边界类用于封装在用例内、外流动的信息或数据流。边界类位于系统与外界的交界处,包括所有窗体、报表、打印机和扫描仪等硬件的接口,以及与其他系统的接口。要寻找和定义边界类,可以检查用例模型,每个参与者和用例交互至少要有一个边界类,边界类使参与者能与系统交互。边界类是一种用于对系统外部环境与其内部运作之间的交互进行建模的类。常见的边界类有窗口、通信协议、打印机接口、传感器和终端等。实际上,在系统设计时,产生的报表都可以作为边界类来处理。边界类用于系统接口与系统外部进行交互,边界对象将系统与其外部环境的变更(例如,与其他系统的接口的变更、用户需求的变更等)分隔开,使这些变更不会对系统的其他部分造成影响。通常情况下,边界类可以既有属性也有方法。
面向对象设计原则(重点)
在面向对象设计中,可维护性的复用是以设计原则为基础的。常用的面向对象设计原则包括单一职责原则(S)、开闭原则、里氏替换原则、依赖倒置原则、
组合/聚合复用原则、接口隔离原则和最少知识原则等。
设计原则 | 详细描述 |
---|---|
单一职责原则(S) | 单一职责原则要求类应该只有一个设计目的 |
开闭原则(O) | 可扩展系统并提供新行为,通过添加抽象层实现,是其他原则的基础。 |
里氏替换原则(L) | 软件实体使用基类对象时适用于子类对象,反之不一定,设计时应将变化类设计为抽象类或接口。 |
接口隔离原则(I) | 分逻辑和狭义两种理解,前者将接口视为角色,后者要求接口提供客户端需要的行为,将大接口方法分至小接口。 |
依赖倒置原则(D) | 抽象不依赖于细节,针对接口编程,是实现开闭原则的主要机制, 与各种技术和框架相关。 |
组合/聚合复用原 则 | 通过组合或聚合关系复用已有对象,比继承更灵活,耦合度低。 |
最少知识原则(迪米特法则) | 软件实体应尽量少与其他实体相互作用,分狭义和广义原则,狭义降低类耦合但可能影响通信效率,广义主要控制信息相关方面,利于子系统解耦和复用。 |
- 单一职责原则(重点)
单一职责原则指一个类应该仅有一个引起它变化的原因。比如有一个类负责用户信息的处理,包括用户数据的存储、用户权限的管理等。这就违反了单一职责原则,应该将存储功能和权限管理功能分别提取到不同的类中。比如专门有一个用户数据存储类负责数据存储相关操作,有一个用户权限管理类负责权限相关的操作,这样每个类的职责就更单一明确。
- 开闭原则(重点)
开闭原则是指软件实体应对扩展开放,而对修改关闭,即尽量在不修改原有代码的情况下进行扩展。此处的“实体”可以指一个软件模块、一个由多个类组成的局部结构或一个独立的类。在 面向对象设计 中,开闭原则一般通过在原有模块中添加抽象层 (例如接口或抽象类)来实现,它也是其他面向对象设计 原则的基础,而其他原则是实现开闭原则的具体措施。
- 里氏替换原则(重点)
里氏替换原则由 Barbara Liskov 提出,其基本思想是,一个软件实体如果使用的是一个基类对象,那么一定适用于其子类对象,而且觉察不出基类对象和子类对象的区别,即把基类都替换成它的子类,程序的行为没有变化。反过来则不一定成立,如果一个软件实体使用的是一个子类对象,那么它不一定适用于基类对象。
- 依赖倒置原则(重点)
依赖倒置原则是指抽象不应该依赖于细节,细节应当依赖于抽象。换言之, 要针对接口编程,而不是针对实现编程。在程序代码中传递参数时或在组合(或聚合)关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明和方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口和抽象类中声明过的方法,而不要给出多余的方法,否则,将无法调用到在子类中增加的新方法。
实现开闭原则的关键是抽象化,并且从抽象化导出具体化实现,**如果说开闭原则是面向对象设计 的目标的话,那么依赖倒置原则就是面向对象设计的主要机制。**有了抽象层,可以使得系统具有很好的灵活性,在程序中尽量使用抽象层进行编程,而将具体类写在配置文件中, 这样,如果系统行为发生变化,则♘ 需要扩展抽象层,并修改配置文件,而无需修改原有系统的源代码,在不修改的情况下来扩展系统功能,满足开闭原则的要求。
- 组合/聚合复用原则(重点)
组合/聚合复用原则又称为合成复用原则,是在一个新的对象中通过组合关系或聚合关系来使用一些已有的对象,使之成为新对象的一部分,新对象通过委派调用已有对象的方法达到复用其已有功能的目的。简单地说,就是要尽量使用组合/聚合关系,少用继承。
通过继承来进行复用的主要问题在于继承复用会破坏系统的封装性,因为继承会将基类的实现细节暴露给子类,由于基类的内部细节通常对子类来说是透明的,所以这种复用是透明的复用,又称为白盒复用。
由于组合或聚合关系可以将已有的对象(也可称为成员对象)纳入新对象中, 使之成为新对象的一部分,新对象可以调用已有对象的功能,这样做可以使得成员对象的内部实现细节对于新对象是不可见的,因此,这种复用又称为黑盒复用。
- 接口隔离原则(重点)
接口隔离原则是指使用多个专门的接口 , 而不使用单一的总接口。每个接口应该承担一种相对独立的角色,不多不少,不干不该干的事,该干的事都要干。
接口隔离原则表达的意思则是指接口仅仅提供客户端需要的行为,客户端不需要的行为则隐藏起来,应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口。在面向对象编程语言中,如果需要实现一个接口,就需要实现该接口中定义的所有方法,因此,大的总接口使用起来不一定很方便,为了使接口的职责单一,需要将大接口中的方法根据其职责不同,分别放在不同的小接口中, 以确保每个接口使用起来都较为方便,并都承担单一角色。
- 最少知识原则(重点)
最少知识原则也称为迪米特法则,是指一个软件实体应当尽可能少地与其他实体发生相互作用。这样,当一个模块修改时,就会尽量少地影响其他的模块, 扩展会相对容易。这是对软件实体之间通信的限制,它要求限制软件实体之间通信的宽度和深度。
结构化设计(重点)
结构化设计(Structured Design , 以下简称 SD) 是一种面向数据流的方法,它以 SRS 代表的软件需求规格说明(Software Requirements Specification),SA 代表的系统分析(System Analysis)阶段所产生的数据流图和数据字典等文档为基础,是一个自顶向下、逐步求精和模块化的过程。SD 方法的基本思想是将软件设计成由相对独立且具有单一功能的模块组成的结构,分为概要设计和详细设计两个阶段,其中概要设计的主要任务是确定软件系统的结构,对系统进行模块划分,确定每个模块的功能、接口和模块之间的调用关系。详细设计的主要任务是为每个模块设计实现的细节。
软件设计模型/结构化设计——包括四个既独立又相互联系的活动——数据设计、 软件结构设计、人机界面设计(接口设计)和过程设计。
高质量的数据设计将改善程序结构和模块划分,降低过程复杂性;软件结构设计的主要目标是开发一个模块化的程序结构,并表示出模块间的控制关系;人
机界面设计描述了软件与用户之间的交互关系。
模块结构(重点)
在 SD 中表现为将系统划分为可自由组合、分解和变换的模块,模块是系统基本单位,任何处理功能都可视为模块。在 SD 方法中,系统由多个逻辑上相对独立的模块组成,在模块划分时需要遵循如下原则:
- ( 1 ) 模块的大小要适中。系统分解时需要考虑模块的规模,过大的模块可能导致系统分解不充分,其内部可能包括不同类型的功能,若要进一步划分,尽量使得各个模块的功能单一;过小的模块将导致系统的复杂度增加,模块之间的调用过于频繁,反而降低了模块的独立性。一般来说,一个模块的大小使其实现代码在 1-2 页纸之内,或者其实现代码行数在 50-200 行之间,这种规模的模块易于实现和维护。
- ( 2 ) 模块的扇入和扇出要合理。一个模块的扇出是指该模块直接调用的下级模块的个数:扇出大表示模块的复杂度高,需要控制和协调过多的下级模块。扇出过大一般是因为缺乏中间层次,应该适当增加中间层次的控制模块;扇出太小时可以把下级模块进一步分解成若干个子功能模块,或者合并到它的上级模块中去。一个模块的扇入是指直接调用该模块的上级模块的个数;扇入大表示模块的复用程度高。设计良好的软件结构通常顶层扇出比较大,中间扇出较少,底层模块则有大扇入。一般来说,系统的平均扇入和扇出系数为 3 或 4 ,不应该超过 7 , 否则会增大出错的概率。
- ( 3 ) 深度和宽度适当。深度表示软件结构中模块的层数,如果层数过多, 则应考虑是否有些模块设计过于简单,看能否适当合并。宽度是软件结构中同一个层次上的模块总数的最大值,一般来说,宽度越大系统越复杂,对宽度影响最大的因素是模块的产出。
- ( 4 ) 信息隐蔽。信息隐蔽采用封装技术隐藏程序模块实现细节,使模块接口简单,系统模块应设计成“黑盒”,只通过接口信息交互,模块间相对独立易实现、理解和维护;抽象原则抽取事物基本特性和行为,忽略细节,分层次抽象可控制开发复杂性,包括过程抽象、数据抽象和控制抽象。
耦合(重点)
耦合表示模块之间联系的程度。紧密耦合表示模块之间联系非常强,松散耦合表示模块之间联系比较弱,非耦合则表示模块之间无任何联系,是完全独立的。模块的耦合类型通常分为 7 种,根据耦合度从低到高排序如表所示。
耦合类型 | 描 述 |
---|---|
非直接耦合(低) | 两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制 和调用来实现的 |
数据耦合 | 一组模块借助参数表传递简单数据 |
标记耦合 | 一组模块通过参数表传递记录信息(数据结构) |
控制耦合 | 模块之间传递的信息中包含用于控制模块内部逻辑的信息 |
外部耦合 | 一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是 通过参数表传递该全局变量的信息 |
公共耦合 | 多个模块都访问同一个公共数据环境,公共的数据环境可以是全局数据 结构、共享的通信区、内存的公共覆盖区等 |
内容耦合(高) | 一个模块直接访问另一个模块的内部数据:一个模块不通过正常入口转 到另一个模块的内部:两个模块有一部分程序代码重叠:一个模块有多个入口 |
对于模块之间耦合的强度,主要依赖于一个模块对另一个模块的调用、一个模块向另一个模块传递的数据量、一个模块施加到另一个模块的控制的多少,以及模块之间接口的复杂程度。
内聚(重点)
内聚表示模块内部各成分之间的联系程度,是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做目标单一的一件事情。模块的内聚类型通常也可以分为 7 种,根据内聚度从高到低的排序如表所示 (特别注意功能内聚和偶然内聚)。
内聚类型 | 描 述 |
---|---|
功能内聚(高) | 完成一个单一功能,各个部分协同工作,缺一不可 |
顺序内聚 | 处理元素相关,而且必须顺序执行 |
通信内聚 | 所有处理元素集中在一个数据结构的区域上 |
过程内聚 | 处理元素相关,而且必须按特定的次序执行 |
瞬时内聚(时间内聚) | 所包含的任务必须在同一时间间隔内执行 |
逻辑内聚 | 完成逻辑上相关的一组任务 |
偶然内聚(巧合内聚)(低) | 完成一组没有关系或松散关系的任务 |
一般说来,系统中各模块的内聚越高,则模块间的耦合就越低,但这种关系并不是绝对的。耦合低使得模块间尽可能相对独立,从而各模块可以单独开发和维护;内聚高使得模块的可理解性和维护性极大增强。因此,在模块的分解中应尽量减少模块的耦合,力求增加模块的内聚,遵循 “高内聚、低耦合”的设计原则。
设计模式(次重点)
设计模式是前人经验的总结,它使人们可以方便地复用成功的设计和架构。当人们在特定的环境下遇到特定类型的问题,采用他人已使用过的一些成功的解决方案,一方面可以降低分析、设计和实现的难度,另一方面可以使系统具有更好的可复用性和灵活性。