设计工程
(前半段概念可能难懂点,后面好点)
软件设计工程概述
软件设计
软件设计是从软件需求规格说明书出发,根据需求分析阶段确定的功能设计软件系统的整体结构、划分功能模块、确定每个模块的实现算法以及编写具体的代码,形成软件的具体设计方案。
软件需求分析解决“做什么”的问题,软件设计过程则解决“怎么做”的问题
软件设计是把软件需求变换成软件表示的过程,它主要包含两个阶段:
- 概要设计(系统设计、总体设计)
- 详细设计(部件设计)
概要设计(系统设计、总体设计)
- 概要设计:是一个设计师根据用户交互过程和用户需求来形成交互框架和视觉框架的过程,完成功能分组、交互控件布置、界面整体板式设计。是在用户研究和设计之间架起桥梁。
- 概要设计的主要任务:是把用户需求转换为软件结构和数据结构
- 设计软件结构的具体任务是:将一个复杂系统按功能进行模块划分、建立模块的层次结构及调用关系、确定模块间的接口及人机界面等。
- 数据结构设计:包括数据特征的描述、确定数据的结构特性、以及数据库的设计。
- 显然,概要设计建立的是目标系统的逻辑模型,与计算机无关。
软件设计的任务
软件设计的输入是软件分析模型。
设计方法:从分析模型–>设计模型
分析数据、功能、行为,获取软件需求
软件设计包括软件体系结构设计、数据/类设计、接口设计和部件级设计。
体系结构设计:定义软件系统各主要部件之间的关系
数据/类设计:将模型转换成数据结构的定义
接口设计:软件内部,软件和操作系统间以及软件和人之间如何通信
部件级设计:系统结构部件转换成软件的过程描述
1.数据/类设计
数据设计的过程包括以下两步:
- 为在需求分析阶段所确定的数据对象选择逻辑表示,需要对不同结构进行算法分析,以便选择一个最有效的设计方案
- 确定对逻辑数据结构所必需的那些操作的程序模块,以便限制或确定各个数据设计决策的影响范围。
”清楚的数据定义是软件开发成功的关键“
2.体系结构设计
体系结构主要目标是开发模块化的程序结构,并表达出模块间的控制相关性。
体系设计融合了程序结构与数据结构,以及使得数据得以在程序中流动的界面定义。
体系结构设计者关注系统的整体设计,而不是系统中单独的组件。
选用不同的方法会采用不同的途径来接近体系的原点,但所有这些方法都应该认识到具有软件全局观念的重要性
(概念性的东西我也不懂,有人会吗- -)
3.接口设计
接口设计主要包括三个方面:
- 设计软件模块间的接口
- 设计模块和其他信息生产者和消费者(比如外部实体)之间的接口
- 设计人(用户)和计算机间的接口
4.部件级设计
部件级设计将软件体系结构的结构性元素变换为对软件部件的过程性描述
从类为基础的模型、流模型、行为模型中得到的信息是部件设计的基础
软件设计的目标
- 设计必须实现分析模型中描述的所有显式需求,必须满足用户希望的所有隐式需求
- 设计必须是可读、可理解的,使得将来易于编程、易于测试、易于维护
- 设计应从实现角度出发,给出与数据、功能、行为相关的软件全貌
衡量技术水平的标准
- 设计出来的结构应是分层结构,从而建立软件成份之间的控制。
- 设计应当模块化,从逻辑上将软件划分为完成特定功能或子功能的部件
- 设计应当既包含数据抽象,也包含过程抽象
- 设计应当建立具有独立功能特征的模块
- 设计应当建立能够降低模块与外部环境之间复杂连接的接口
- 设计应能根据软件需求分析获取的信息,建立可驱动、可重复的方法
软件设计的过程
- 制定规范
- 体系结构和接口设计
- 数据/类设计
- 部件级(过程)设计
- 编写设计文档
- 设计评审
软件设计原则
- 设计对于分析模型应该是可跟踪的:软件的模块可能被映射到多个需求上。
- 设计结构应该尽可能的模拟实际问题
- 设计应该表现出一致性
- 不要把设计当成编写代码
- 在创建设计时就应该能够评估质量
- 评审设计以减少语义性的错误
- 设计应该模块化,将软件有逻辑地划分为元素或子系统,并包含数据、体系结构、接口和构件的清晰表示
设计的指导方针
- 设计应该展现层次结构,使得软件各部分之间的控制更明智
- 设计应当模块化;软件应在逻辑上分割为实现特定的功能和子功能的部分
- 设计应当由清晰,且可分离的数据和过程表达来构成
- 设计应使得模块展现独立的功能特性
- 设计应使得界面能够降低模块之间及其与外部环境的连接复杂性
- 设计应源自于软件需求分析期间获得的信息所定的可重复软件设计方法的使用
设计基础:抽象
最高层次抽象:指的是使用待解决的问题领域内的术语描述的解决方案(靠吹)
较低层次的抽象:则更多的面向程序语言(靠看伪代码)
最低层次的抽象:则是解决方案的可直接实现的方式描述
软件设计的每一个步骤都是对相应层次解决方案的抽象的逐步求精
逐步求精(refinement)
定义:指的是通过程序细节持续细化来开发程序体系的策略
分步骤的对程序抽象进行分解,直至成为编程语言的过程
同时造就了程序的层次结构。对细节多做考虑。
求精实际上是苦心经营的过程
模块化(modularity)
定义:指的是可软件被分割为分别命名并可寻址的组件(也叫做模块)
模块化将模块综合起来又可以满足问题的需求的性质
模块化是允许智能化管理程序的唯一属性。即:使一个系统必须像”单片机“一样来实现,它也可以采用模块化设计
模块化,即把软件按照规定原则,划分为一个个较小的、相互独立的、但又相互关联的部件,实际上是系统分解和抽象的过程。
模块是数据说明、可执行语句等程序对象的集合,它是单独命名的,并且可以通过名字来访问。(例如:数据、过程、函数、子程序、宏等)
将复杂的问题分解成可以管理的片段会更使解决问题更加容易
如果模块是相互独立的,当模块变得越小,每个模块花费的工作量越低
但当模块数增加时,模块间的联系也随之增加,把这些模块联系起来的工作量也随之增加
信息隐藏
- 每个模块的实现细节对于其它模块来说应该是隐蔽的
- 块中所包含的信息(包括数据和过程)不允许其它不需要这些信息的模块使用
- 通过信息隐蔽,则可定义和实施对模块的过程细节和局部数据结构的存取限制
(感觉类似java的private关键字)
模块独立
定义:模块完成独立的功能并且与其他模块的接口简单,符合信息隐蔽和信息局部化原则,模块间关联和依赖程度尽可能小
模块独立的重要性:
- 功能被划分,并且接口被简化,所以具有有效模块化的软件更易于开发
- 由于因设计和编码修改引起的副作用受到局限,错误传播被减小,并且模块复用成为可能,所以独立的模块更易于维护和测试
模块的独立性可以由两项指标来衡量:内聚度与耦合度
内聚(cohesion):是一个模块内部各个元素彼此结合的紧密程度的度量
耦合(coupling):是模块之间的相对独立性(互相连接的紧密程度)的度量
内聚
一般模块的内聚性分为七种类型
- 巧合内聚:将几个模块中没有明确表现出独立功能的相同程序代码段独立出来,建立的模块称为巧合内聚模块
- 逻辑内聚:指完成一组逻辑相关任务的模块,调用该模块时,由传送给模块的控制型参数来确定该模块应执行哪一种功能。(java的override?)
- 时间内聚:指一个模块中的所有“构件”必须在同一时间段内执行。例如初始化模块和终止模块。
- 过程内聚:指一个模块完成多个任务,这些任务必须按指定的过程(procedural)执行。(功能理包含多个任务)
- 通信内聚:指一个模块内所有处理元素都集中在某个数据结构的一块区域中。(处理的数据都是类中的数据)
- 顺序内聚:指一个模块完成多个功能,这些功能又必须顺序执行
- 功能内聚:指一个模块中各个部分都是为完成一项具体功能而协同工作,紧密联系,不可分割的。
耦合
一般模块之间可能的耦合方式有七种类型:
- 内容耦合:如果一个模块直接访问另一个模块的内部数据;或者一个模块不通过正常入口转到另一模块内部;或者两个模块有一部分程序代码重迭;或者一个模块有多个入口,则两个模块之间就发生了内容耦合。
- 公共耦合:若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等(就像线程访问进程的公共区域一样)
- 外部耦合:指模块间通过软件之外的环境联结(如I/O将模块耦合到特定的设备、格式、通信协议上)时,称为外部耦合。
- 控制耦合:如果一个模块传送给另一个模块的参数中包含了控制信息,该控制信息用于控制接收模块中的执行逻辑,则称为控制耦合(对象A中有个flag属性,能控制对象B的某个功能是否执行)
- 标记耦合:两个模块之间通过参数表传递一个数据结构的一部分(如某一数据结构的子结构),就是标记耦合(在工具类中拿某数据结构)
- 数据耦合:两个模块之间仅通过参数表传递简单数据,则称为数据耦合。(工具类中拿简单数据)
- **非直接耦合 **:如果两个模块之间没有直接关系,即它们中的任何一个都不依赖于另一个而能独立工作,这种耦合称为非直接耦合。(不能说一模一样,只能说毫不关联)
结论
模块之间的连接越紧密,联系越多,耦合性就越高,而其模块独立性就越弱
一个模块内部各个元素之间的联系越紧密,则它的内聚性就越高
模块独立性比较强的模块应是高内聚低耦合的模块
软件体系结构设计
描述:软件体系结构关注系统的一个或多个结构,包含软件构件、这些构件的对外可见的性质以及它们之间的关系
Bass提出体系结构重要的三个关键理由:
- 方便利益相关人员的交流
- 有利于系统设计的前期决策
- 可传递的系统级抽象
典型的体系结构风格有9种:
- 数据流风格——批处理、管道和过滤器
- 调用与返回风格——主/子程序、OOD、层次结构
- 独立组件风格——通信进程、事件隐式调用
- 虚拟机风格——解释器、规则基系统
- 以数据为中心风格——数据库系统、黑板系统、超文本系统
- 过程控制风格——过程控制、模拟器
- 客户-服务器风格
- C2风格——基于消息广播且面向图形用户界面的Chiron2风格
- 异构风格——不同的风格构成
体系结构发展过程
非专业人员:软件体系结构
- 单机结构
- C/S(Client/Server)结构
- B/S(Browser/Server)结构
软件体系结构的风格
绝大多数软件体系结构风格,可以被归类为相对小数量的体系结构风格之一
每种风格描述一种系统范畴,范畴包括:
- 一些实现系统所需的功能的部件(如数据库、计算模块)
- 一组用来连接部件“通信、协调和合作”的“连接件”
- 定义部件之间怎样整合的系统约束
- 使设计者能够理解整个系统属性并分析已知属性的语义模型
数据为中心的体系结构
一些数据(比如一个文件或者数据库)保存在整个结构的中心,并且被其他部件频繁地使用、添加、删除、或者修改。
数据流风格的体系结构
这种结构适用于输入数据被一系列的计算或者处理部件变换成输出数据。
调用和返回风格的体系结构
这种风格使一个软件设计者设计出非常容易修改和扩充的体系结构
包含:主程序/子程序风格体系结构和远程过程调用风格的体系结构
在这里要了解几个概念:
- 程序结构的深度:程序结构的层次数称为结构的深度。结构的深度在一定意义上反映了程序结构的规模和复杂程度。
- 程序结构的宽度:层次结构中同一层模块的最大模块个数称为结构的宽度。
- 模块的扇入和扇出:扇出表示一个模块直接调用(或控制)的其它模块数目。扇入则定义为调用(或控制)一个给定模块的模块个数。多扇出意味着需要控制和协调许多下属模块。而多扇入的模块通常是公用模块。
面向对象风格的体系结构
- 系统部件封装数据和操作数据的方法
- 部件之间的交互和协调通过消息来传递
- 在这种结构中,定义不同的层次,每层都完成了相对外层更靠近机器指令的操作………
评估可选的体系结构
对于同一个软件需求,由于各种设计方法的原理不同,会导出不同的软件结构。
同一问题的不同软件结构:
ATAM(Architecture Trade-off Analysis Method)
ATAM(体系结构权衡分析法),对设计的分析过程按如下所述的迭代步骤进行:
- 定义应用场景(scenarios):通过use case图来从用户的角度表现系统。
- 得出需求、约束和环境描述:这是需求工程的一部分,用以确定所有客户方关心的问题都被列出。
- 描述能处理上述情境和需求的体系结构风格。
- 单独地评价系统的各项性能。针对体系结构设计的性能包括:可靠性,性能、安全性,可维护性,灵活性,可测试性,可移植性,可重用性和互操作性等。
- 针对不同的架构形式,评价第4步提到的这些性能的敏感程度。可以通过这样的方法来评价:在整个架构中做一些小的变更,分析并确定上述性能有没有很敏感的变化。那些在体系结构改动中受到较大影响的性能被称为敏感点(sensitive point)。
- 通过第5步的敏感度分析来评价第三步中提出的那些体系结构。SEI描述的方法如下:当一个架构的敏感点被确定,我们需要找到在系统中最需要权衡利弊的因素(trade-off point)。权衡因素就是指改变架构中的这项内容系统的很多性能就会发生敏感的变化。比如说,一个client-server结构的系统的表现性能和系统中server的数量是息息相关的(比如增加server的数量,一定程度上系统的表现性能就会提高)……这样的话,server的数量就是这个架构中的平衡点。
部件级设计技术
在结构化分析和设计方法时,部件往往被称为模块
在面向对象分析和设计时,部件被称为类
在基于构件的开发方法中,部件被称为构件(组件)
在部件级设计阶段,主要完成如下工作:
- 确定每一部件内部使用的数据结构
- 为每个部件确定采用的算法,选择某种适当的工具表达算法的过程,编写部件的详细过程性描述
- 在部件级设计结束时,应该把上述结果写入部件级设计说明书,并且通过复审形成正式文档,作为下一阶段(编码阶段)的工作依据
结构化程序设计方法
一种较为流行的定义是:“如果一个程序的代码块仅仅通过顺序、选择和循环这三种基本控制结构进行连结,并且每个代码块只有一个入口和一个出口,则称这个程序是结构化的”。
随着面向对象和软件复用等新的软件开发方法和技术的发展,更现实、更有效的开发途径可能是自顶向下和自底向上两种方法有机的结合。
图形表示法
- 程序流程图
- N-S图
- PAD
程序流程图
程序流程图独立于任何一种程序设计语言,比较直观、清晰、易于学习掌握
为使用流程图描述结构化程序,必须限制流程图只能使用五种基本控制结构
可构成:
N-S图
Nassi和Shneiderman 提出了一种符合结构化程序设计原则的图形描述工具,叫做盒图,也叫做N-S图
可构成:
PAD
PAD是Problem Analysis Diagram的缩写 ,由程序流程图演化而来
可构成:
判定表
当算法中包含多重嵌套的条件选择时,用程序流程图、N-S图或PAD都不易清楚地描述。然而,判定表却能清晰地表达复杂的条件组合与应做动作之间的对应关系。把多分支判断改为两分支判断。(判定表用来解决多重嵌套的条件选择)
反映程序逻辑的判定表
(想知道什么意思的可以查查)
判定表的优点是能够简洁,无二义性地描述所有的处理规则。
但判定表表示的是静态逻辑,是在某种条件取值组合情况下可能的结果,它不能表达加工的顺序,也不能表达循环结构 。
设计性语言PDL
PDL(Program Design Language)是一种用于描述功能部件的算法设计和处理细节的语言,称为设计性语言。
它是一种伪码。一般地,伪码的语法规则分为“外语法”和“内语法”
- 外语法应当符合一般程序设计语言常用语句的语法规则
- 内语法可以用英语中一些简单的句子、短语和通用的数学符号,来描述程序应执行的功能
例子
PROCEDURE spellcheck // 查找错拼的单词
BEGIN
split document into single words
//把整个文档分离成单词
lood up words in dictionary
//在字典中查这些单词
display words which are not in dictionary
//显示字典中查不到的单词
create a new dictionary
//造一新字典
END spellcheck
(和伪代码很像)
PDL特点
- 有固定的关键字外语法,提供全部结构化控制结构、数据说明和部件特征。属于外语法的关键字是有限的词汇集,它们能对PDL正文进行结构分割,使之变得易于理解。为了区别关键字,规定关键字一律大写,其它单词一律小写。
- 内语法使用自然语言来描述处理特性。内语法比较灵活,只要写清楚就可以,不必考虑语法错,以利于人们可把主要精力放在描述算法的逻辑上。
- 有数据说明机制,包括简单的(如标量和数组)与复杂的(如链表和层次结构)的数据结构。
- 有子程序定义与调用机制,用以表达各种方式的接口说明。
设计规约与设计评审
软件设计的最终目标是要取得最佳方案
“最佳”是指在所有候选方案中:
- 节省开发费用,降低资源消耗
- 缩短开发时间
- 较高的生产率
- 较高的可靠性
- 较高的可维护性
设计评审的内容
包括10个方面的指标:
- 可追溯性:即分析该软件的系统结构、子系统结构,确认该软件设计是否覆盖了所有已确定的软件需求,软件每一成分是否可追溯到某一项需求。
- 接口:即分析软件各部分之间的联系,确认该软件的内部接口与外部接口是否已经明确定义。部件是否满足高内聚和低耦合的要求。部件作用范围是否在其控制范围之内。
- 风险:即确认该软件设计在现有技术条件下和预算范围内是否能按时实现。
- 实用性:即确认该软件设计对于需求的解决方案是否实用。
- 技术清晰度:即确认该软件设计是否以一种易于翻译成代码的形式表达。
- 可维护性:从软件维护的角度出发,确认该软件设计是否考虑了方便未来的维护。
- 质量:即确认该软件设计是否表现出良好的质量特征。
- 各种选择方案:看是否考虑过其它方案,比较各种选择方案的标准是什么。
- 限制:评估对该软件的限制是否现实,是否与需求一致。
- 其它具体问题:对于文档、可测试性、设计过程等等进行评估。
设计评审
评审分正式评审和非正式评审两种
正式评审:除软件开发人员外,还邀请用户代表和领域专家参加,通常采用答辩形式 。
非正式评审:多少有些同行切磋的性质,不拘泥于时间和形式 。