软件设计工程

一、软件设计简介

定义:为软件系统的架构,组件,接口和其它特性的定义过程及该过程的结果,解决“如何做”How的问题。

软件设计方法包括:

  • 结构化设计SD
  • 面向对象的设计OOD

软件设计包括以下活动:

  • 软件架构设计(概要设计,顶层设计)
    • 体系结构设计
    • 数据设计
    • 接口设计
  • 软件详细设计(组件设计,过程设计)
  • 不包括:创新设计

 软件质量可以用质量属性来描述。FURPS质量属性:

  1. Functionality: 功能性
  2. Usability: 可用性
  3. Reliability: 可靠性
  4. Performance: 性能
  5. Serviceability: 可维护性

二、设计技术

抽象:

侧重于解决特定问题的细节,忽略不相关的底层细节。

设计开始时应提高软件的抽象层次,按抽象级别从高到低进行软件设计。

细化:

与抽象相对的概念,从软件定义到实现,每进展一步都可以看成是对软件设计方案的抽象化过程的一次细化。

自顶向下,逐步细化:

  • 最高的抽象层次:用问题所处环境的语言描述
  • 较低的抽象层次:用面向问题的术语面向现实的术语描述
  • 最低的抽象层次:用某种程序设计语言描述

设计模式:

  1. 创建型模式
  2. 结构型模式
  3. 行为型模式

模块化:

  • 理论依据:分解问题后的复杂性/工作量的总和<原问题复杂性/工作量
  • 模块分解并不是越小越好:随着模块数增加,单个模块的规模减小了,但是模块之间的关系复杂程度会增加,设计模块间接口的工作量也将增大。

如何衡量模块化设计水平?模块化设计标准:

  1. 模块化分解性:分解子问题的系统机制
  2. 模块化组合性:现有组件可以组装成系统
  3. 模块化可理解性:一个模块可以作为一个独立单元来使用
  4. 模块化连续性:系统需求的小变化只引起单个模块变化
  5. 模块化保护:模块内的异常情况只影响自身模块

信息隐藏:

模块内的信息不可以被不需要这些信息的其它模块访问。

功能独立:

  • 只解决特定的子功能
  • 接口得到简化

功能独立的两个定性衡量标准:

  1. 内聚性:模块的功能相对强度
  2. 耦合性:模块之间的相互依赖程度

独立性强的模块:高内聚,低耦合

耦合的7种类型:

    1. 非直接耦合:两个模块没有直接联系,完全是通过主模块的控制和调用实现的
    2. 数据耦合:仅通过模块参数交换信息,且交换的都是简单数据
    3. 标记耦合:通过参数表,传递一个数据结构的一部分
    4. 控制耦合:一个模块传递给另一个模块的参数中,包含了控制信息,用于控制接受模块的执行情况
    5. 外部耦合:模块通过除软件以外的环境(如I/O)连接
    6. 公共耦合:一组模块访问一个公共数据环境
    7. 内容耦合:一个模块对另一个模块的内容(数据,代码段)进行了直接引用或修改,两个模块共享一部分代码

内聚的7种类型:

    1. 巧合内聚:又称偶然内聚,语句段十分松散,无联系
    2. 逻辑内聚:把几种功能组合在一起,由传入模块的控制参数来决定执行哪一种功能
    3. 时间内聚:一个模块包括了需要在同一时间段执行的多个任务
    4. 过程内聚:一个模块内的各个部分按照特定的次序执行
    5. 通信内聚:一个模块中的各个部分使用同一个输入数据或产生同一个输出数据
    6. 顺序内聚:必须按照先后顺序执行,后一个部分与前一个部分密切相关
    7. 功能内聚:模块完成一个功能

重构:

不改变组件功能的条件下,简化组件设计。

三、设计模型

  • 体系结构设计:强调系统的:可理解性,可维护性,可扩展性
    • 模式
    • 风格
    • 框架(如MVC Struts)
  • 数据设计
  • 接口设计
  • 组件设计

 体系结构设计:

将模式(即,针对特定问题的解决方案)划分成三类:

  • 体系结构模式:软件系统的基本结构组织形式或方案
  • 设计模式(23种):构件相互通信的结构
  • 惯用法:与编程语言相关的低级模式

架构风格分类:

  • 数据中心架构:
  • 数据流架构
  • 调用和返回架构:
    • 可分为主程序/子程序架构(所以程序组件都在同一台计算机上),远程过程调用架构(主程序或子程序的各组件分布在多台计算机上)两类
    • 需要理解:深度宽度扇入扇出:

  • 面向对象架构:封装了数据和对数据的操作
  • 层次架构:每一层为上一层提供服务,并作为下一层的客户。每一层最多只影响两层,只需提供接口,允许各层用不同方法实现。

另一种分类方法:

  • 单主机结构
  • 分布式结构
    • 多处理器体系结构
    • 客户机/服务器体系结构(B/S C/S架构)
    • 分布式对象体系结构
    • 代理

两层C/S架构:

  • 瘦客户机模型:除数据表示以外的操作都在服务器执行。客户机只负责数据表示。
  • 胖客户机模型:服务器只负责管理数据,客户机实现应用逻辑和与系统交互。

 三层C/S架构:

增加了应用服务器。

将系统分为:数据层应用逻辑层表示层

B/S架构(是三层体系架构):

浏览器——web服务器——数据库服务器

相对灵活,但响应速度和动态交互性不如C/S

接口设计中的重要部分:

用户界面设计:三个准则:

  1. 用户控制系统
  2. 减少学习和记忆负担
  3. 保持界面的一致性

数据设计:

组件级别的数据设计,即设计供软件组件直接访问的数据结构。

低层的数据设计应推迟到后期进行。

注意信息的隐藏和耦合。

组件设计:

接近代码层次的软件抽象描述。

  • 结构化设计:基于过程
  • 面向对象设计:基于类

部署设计:

包含了整个解决方案的逻辑架构和服务质量(QoS)需求。

项目审批发生在部署设计阶段,估计软件部署的成本,提交审批。

是一种高层架构,描述了逻辑环境到物理环境的映射。

四、结构化设计方法SD(Structured Design)

 结构化设计中,软件的结构元素是模块,因此也称为模块设计

接口设计:

  • 内部接口:模块之间的接口。
  • 外部接口:软件和硬件的接口,软件和其它软件的接口,软件和用户的交互界面。

SD数据设计的概括:将ER图转换为数据库表。

软件的结构分为:模块结构+数据结构。一般采用功能划分的方法进行软件结构设计,对整个问题进行分割,每一部分用一个或几个模块来完成。

模块的表示:

  • 用矩形框表示,已定义的模块用双纵边矩形框表示。

模块的分类(实际系统中的模块属于以下任意一种,或某几种的组合):

  1. 传入模块
  2. 传出模块
  3. 变换模块
  4. 协调模块

模块的结构:

  1. 树状结构:
    • 只有一个顶层(第0层)模块
    • 上层模块调用下层模块,同一层模块之间互不调用
    • 实际系统中建议使用树状结构,最底层可能存在公共模块,使得整个系统不是严格的树状结构,属正常情况
  2. 网状结构:
    • 无法区分层次
    • 任意模块可相互调用
    • 系统结构复杂,难以处理
    • 实际系统中不建议使用网状结构

用结构图表示模块结构:

菱形表示条件调用,圆弧表示循环调用。

 理解深度,宽度(下图宽度为7),扇入,扇出:

数据结构:

基于数据流的设计方法是:过程驱动的设计方法。

数据流的类型:(一般都是以变换型为主,事务型为辅)

  • 变换型数据流:工作过程大致分为3步:取得数据,变换数据,给出数据

变换型系统结构图如下:

  • 事务型数据流:接受一项事务,分派适当的处理单元并给出结果。选择分派任务的部分称为事务(处理)中心分派部件。调度模块如果不复杂,可以归入事务中心模块。

事务型系统结果图(简化):

变换型映射方法:将具有变换流特点的数据流图映射成软件结构

自顶向下,设计下层模块的顺序是任意的。但一般先设计输入模块的下层模块。

一层一层往下分解。

事务型映射方法:将具有事务流特点的数据流图映射成软件结构

变换型和事务型混合结构的例子:

模块的完善化:

模块完全相似,可能只是在数据类型上不一致。可以完全合并。

局部相似时,则不能将两者合并为一。一般的处理方法是将相似的部分分离出去。

模块的作用范围和控制范围:

模块的控制范围是指它本身和所有的从属模块。

模块的作用范围是指收模块内一个判定影响的范围。

模块的作用范围应该在模块的控制范围以内

扇入和扇出:

适当的扇出数为2~5,最好不要超过9。扇出数过小会使结构图的深度增加,扇出数过大会使结构图的宽度增加。

一个好的软件模块设计,通常是:上层扇出较高,中层扇出较少,底层公用模块的扇入较高。

数据库设计:

数据库分为多种,其中关系数据库最成熟。多对多关系的映射需要引入关联表。

结构化程序设计用到的工具:

  • 程序流程图
  • N-S图(盒图)
  • PAD图:采用PAD描述出来的程序一定是结构化程序,多少根竖线对应多少层
  • 判定表:多重嵌套的条件选择
  • 伪代码

五、面向对象的设计方法OOD(Object-Oriented Design)

 OOA和OOD,分析和设计联系紧密,没有明显界限。

整个设计阶段的核心任务:创建包含操作的设计类图

分析类设计类:导出实体类,增加边界类,控制类

在OOD中,类和接口是程序的基本组成单元。

继承(子类对象继承父类的所有特征,又可以覆盖父类的方法)依赖性:

  1. 多态继承:
    • 根据为请求服务的对象不同可以得到不同的行为。若在运行时对类进行实例化,称为动态绑定;若方法的调用是在编译时确定的,称为静态绑定。
    • 多态不是伴随着继承产生。如果子类中不覆盖父类中的任何方法,就不会产生多态。
    1. 编译时继承依赖性:一般来说,所有的继承都会引入编译时依赖性。并且,依赖性是可传递的。
    2. 运行时继承依赖性
    3. 交互依赖性:通过消息连接产生的
  2. 无多态继承:
    • 子类不覆盖父类的方法。
    • 有时不是十分有用,但便于理解和管理。
  3. 扩展继承和约束继承:
    • 扩展继承:子类继承了父类的属性,并提供额外属性来增强类的定义。
    • 约束继承:子类对从父类继承来的方法和功能进行了约束和限制。

面向接口编程,而不是面向实现编程:接口依赖性又分为使用依赖性和实现依赖性。

在包之间增加新包,可以消除循环依赖性。

构件:比类更高级,包含一个或一组类,或者其它部署单元,完成一个或多个功能的特定服务。隐藏了具体的实现,只用接口对外提供服务。

从软件复用的角度,构件是指开发过程中可以复用的软件元素。具有独立性,不可拆分。

构件被实现为大粒度的单元,只能由一个实例。

OOD:系统划分为子系统。

封闭体系结构:每一层只能访问与其相邻的下一层。

开放体系结构:每一层可以访问比其下一层更低的层次。

典型的面向对象系统的分层结构:数据库层,业务逻辑层,用户界面层

面向对象的设计顺序:业务逻辑层(问题域部分)M——人机交互部分V——C任务管理部分——数据管理部分

数据管理部分:关联关系的映射:

原文地址:https://www.cnblogs.com/justKidrauhl/p/10100154.html