软件工程导论—总体设计

Mitch Kapor曾经就软件设计发表过宣言:“什么是设计计是你站在两个世界——技术世界和人类的目标世界,而你尝试将这两个世界结合在一起……”。

文章目录

      • 1. 设计过程
        • 1.1. 软件设计简述
        • 1.2. 设计过程
      • 2. 设计原理
        • 2.1. 模块化
        • 2.2. 抽象
        • 2.3. 逐步求精
        • 2.4. 信息隐藏和局部化
        • 2.5. 模块独立
          • 2.5.1. 耦合
          • 2.5.2. 内聚
      • 3. 启发规则
      • 4. 描绘软件结构的图形工具
        • 4.1. 层次图和HIPO图
        • 4.2. 结构图
      • 5. 面向数据流的设计方法
        • 5.1. 概述
        • 5.2. 变换分析
        • 5.3. 事务分析
        • 5.4. 设计优化

1. 设计过程

1.1. 软件设计简述

软件设计阶段从不同的角度有不同的划分方法,下面举三个典型的设计阶段划分的例子:

  1. 从工程管理的角度,可以将软件设计分为概要设计阶段和详细设计阶段;
  2. 从技术的角度,传统的结构化方法将软件设计划分为体系结构设计、数据设计、接口设计和过程设计4部分;
  3. 面向对象软件设计方法,则将软件设计划分为体系结构设计、类设计/数据设计、接口设计和构件级设计4部分。

总体设计可以站在全局高度上,花较少成本,从较抽象的层次上分析对比多种可能的系统实现方案和软件结构,从中选出最佳方案和最合理的软件结构,从而用较低成本开发出较高质量的软件系统。

1.2. 设计过程

典型的总体设计过程由两个主要阶段组成:

1、系统设计阶段,确定系统的具体实现方案

  • 设想供选择的方案
    根据需求分析阶段得出的数据流图考虑各种可能的实现方案,力求从中选出最佳方案.
  • 选取合理的方案
    从前一步得到的一系列供选择的方案中选取若干个合理的方案。对每个合理的方案分析员都应该准备下列4份资料:(1)系统流程图;(2)组成系统的物理元素清单;(3)成本/效益分析;(4)实现这个系统的进度计划。
  • 推荐最佳方案
    分析员应该综合分析对比各种合理方案的利弊,推荐一个最佳的方案,并且为推荐的方案制定详细的实现计划。

2、结构设计阶段,确定软件结构

  • 功能分解
    首先进行结构设计,然后进行过程设计。结构设计确定程序由哪些模块组成,以及这些模块之间的关系,属于总体设计阶段的任务;过程设计确定每个模块的处理过程,属于详细设计阶段的任务。
  • 设计软件结构
    通常程序中的一个模块完成一个适当的子功能,应该把模块组织成良好的层次系统,可以用层次图或结构图来描绘软件结构。如果数据流图已经细化到适当的层次,则可以直接从数据流图映射出软件结构,这就是面向数据流的设计方法。
  • 设计数据库
    对于需要使用数据库的那些应用系统,软件工程师应该在需求分析阶段所确定的系统数据需求的基础上,进一步设计数据库。
  • 制定测试计划
    在软件开发的早期阶段考虑测试问题,能促使软件设计人员在设计时注意提高软件的可测试性。
  • 书写文档
    应该用正式的文档记录总体设计的结果,在这个阶段应该完成的文档通常有下述五种:(1) 系统说明 ;(2) 用户手册;(3) 测试计划;(4) 详细的实现计划;(5) 数据库设计结果
  • 审查和复审
    最后应该对总体设计的结果进行严格的技术审查和管理复审。

2. 设计原理

2.1. 模块化

模块是由边界元素限定的相邻程序元素的序列,有一个总体标识符代表它。

所谓模块化,就是把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,把这些模块集成起来构成一个整体,可以完成指定的功能满足用户的需求。

之所以提倡模块化,是因为它可以使一个复杂的大型程序,能被人的智力所管理;相反,如果一个大型程序仅由一个模块组成,它将很难被人所理解。总的来说,模块化有以下四个作用:

  1. 采用模块化原理可以使软件结构清晰,不仅容易设计也容易阅读和理解;
  2. 模块化使软件容易测试和调试,因而有助于提高软件的可靠性;
  3. 模块化能够提高软件的可修改性;
  4. 模块化有助于软件开发工程的组织管理。

以上四个作用都有助于减少软件开发的工作量,进而降低软件开发成本

设问题 P P P的复杂程度为 C ( P ) C(P) C(P),解决问题 P P P所需的工作量为 E ( P ) E(P) E(P) ,如果有 C ( P 1 ) > C ( P 2 ) C(P_1)>C(P_2) C(P1?)>C(P2?),则显然有 E ( P 1 ) > E ( P 2 ) E(P_1)>E(P_2) E(P1?)>E(P2?)
根据人类解决一般问题的经验: C ( P 1 + P 2 ) > C ( P 1 ) + C ( P 2 ) C(P_1+P_2)>C(P_1)+C(P_2) C(P1?+P2?)>C(P1?)+C(P2?)可得: E ( P 1 + P 2 ) > E ( P 1 ) + E ( P 2 ) E(P_1+P_2)>E(P_1)+E(P_2) E(P1?+P2?)>E(P1?)+E(P2?)这个公式说明了模块化对于减少工作量有着积极的作用。

在长期实践的过程中,开发者们总结出了模块化和软件成本之间的关系,如下图所示:

  • 特征耦合(stamp coupling)
    当把整个数据结构作为参数传递而被调用的模块只需要使用其中一部分数据元素时,就出现了特征耦合。被调用的模块可使用的数据多于它确实需要的数据,这将导致对数据的访问失去控制,从而给计算机犯罪提供了机会,当把指针作为参数进行传递时,应该仔细检查该耦合。
  • 耦合是影响软件复杂程度的一个重要因素,在实际设计中,应该采取下述设计原则:(1)尽量使用数据耦合;(2)少用控制耦合和特征耦合;(3)限制公共环境耦合的范围;(4)完全不用内容耦合。

    2.5.2. 内聚

    内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐藏和局部化概念的自然扩展。简单地说,理想内聚的模块只做一件事情。设计时应该力求做到高内聚,通常中等程度的内聚也是可以采用的,而且效果和高内聚相差不多;但是,低内聚不要使用。

    内聚和耦合是密切相关的,模块内的高内聚往往意味着模块间的松耦合。实践表明内聚更重要,应该把更多注意力集中到提高模块的内聚程度上。

    内聚程度分为以下几个度量等级:

    1. 偶然内聚(coincidental cohesion)
      如果一个模块完成一组任务,这些任务彼此间即使有关系,关系也是很松散的,就叫做偶然内聚。
      在偶然内聚这个等级,模块内各元素之间没有实质性联系,很可能在一种应用场合需要修改这个模块,在另一种应用场合又不允许这种修改,从而陷入困境。这导致程序的可理解性差,可维护性产生退化,模块也是不可重用的。

    力争降低模块接口的复杂程度
    模块接口复杂是软件发生错误的一个主要原因。应该仔细设计模块接口,使得信息传递简单并且和模块的功能一致。
    例如解一元二次方程的函数,其中数组TBL传送方程的系数、数组X送回求得的根,这样是不够合理的,应该写成:
  • 设计单入口单出口的模块
    警告软件工程师不要使模块间出现内容耦合。当从顶部进入模块并且从底部退出来时,软件是比较容易理解的,因此也是比较容易维护的。
  • 模块功能应该可以预测
    模块的功能应该能够预测,但也要防止模块功能过分局限。功能可预测是指如果一个模块可以当做一个黑盒子,只要输入的数据相同就产生同样的输出,那就可以说这个模块的功能是可以预测的。
  • 4. 描绘软件结构的图形工具

    4.1. 层次图和HIPO图

    层次图(H图)

    层次图用来描绘软件的层次结构。很适于在自顶向下设计软件的过程中使用。

    层次图和层次方框图的区别:

    层次图 层次方框图
    作用 描绘软件结构 描绘数据结构
    矩形框 模块 数据元素
    连线 调用关系 组成关系

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

    上一篇 2020年4月7日
    下一篇 2020年4月7日

    相关推荐