Alex_McAvoy

想要成为渔夫的猎手

软件设计原则

【概述】

软件设计在软件开发过程中处于核心地位,它是保证质量的关键步骤,其提供了可以用于质量评估的软件表示,是能将用户需求准确地转化为软件产品或系统的唯一方法

为提高软件开发的效率及软件产品的质量,在长期的软件开发实践中总结出一些软件设计的原则

【模块与模块化】

模块

模块是数据说明、可执行语句等程序对象的集合,是构成程序的基本构件,可以被单独命名并通过名字来访问

在面向过程的设计中,过程、函数、子程序、宏都可以作为模块,在面向对象的设计中,对象、对象中的方法也是模块

模块具有三个属性:

  • 功能:指定该模块要完成的任务
  • 逻辑:描述模块为了完成任务内部需要怎么做
  • 状态:表明使用该模块时的环境与条件

模块化

模块化就是把系统或程序划分为独立命名并且可以独立访问的模块,每个模块完成一个特定的子功能。模块集成起来可以构成一个整体,完成特定的功能,进而满足用户需求

模块独立性是良好设计的关键,其是指软件系统中每个模块只涉及软件要求的具体的子功能,与软件系统中的其他模块没有太多联系

模块独立性使模块容易组合、可以复用,有助于并行开发,并减少错误的影响,同时有助于系统的测试与维护

模块独立性有两个定性标准度量:

  • 耦合:衡量不同模块之间的互连程度,耦合强弱取决于模块间接口的复杂程度、通过接口的数据等,耦合性越强,模块独立性就越弱。
  • 内聚:衡量模块内部各元素间结合的紧密程度,内聚性越高,就意味着模块内部各个元素是为了完成一个功能而存在的。

内聚和耦合是密切相关的,模块内的高内聚,往往意味着模块间的松耦合

在模块化的过程中,要注意以下几点:

  • 模块的规模要适中:随着模块数目的增加,软件成本与模块接口成本不断增加
  • 提高模块的独立性:随着模块独立性的提高,使得模块低耦合,高内聚
  • 加强模块的保护性:当一个模块内部出现异常时,其负面影响应该尽量局限在该模块内部,从而保护其他模块不受影响,降低错误的影响范围

【抽象】

抽象是抽出事务的本质特征而暂时不考虑他们的细节,主要是为了降低问题的复杂度,以得到问题领域中较简单的概念,好让人们能够控制其过程或以宏观的角度来了解许多特定的事态

其是人们认识复杂的客观世界时所使用的一种思维工具,在软件开发过程中起着非常重要的作用

一个庞大、复杂的系统可以先用一些宏观的概念构造和理解,然后再逐层地用一些较微观的概念去解释上层的宏观概念,直到最底层的元素

在软件开发过程中,每一个过程都涉及到抽象:

  • 可行性分析:把需要解决问题抽象为一个
  • 需求分析:把需要解决的解抽象为功能
  • 总体设计:把系统抽象为结构
  • 详细设计:把结构抽象为每个模块的处理过程
  • 编码阶段:把处理过程抽象为机器能够执行的程序

【逐步求精】

在面对一个新问题时,开发人员可暂时忽略问题非本质的细节,而关注于与本质相关的宏观概念,集中精力解决主要问题,这种认识事物的方法就是逐步求精

逐步求精是抽象的逆过程,开发人员认识问题时逐步求精的过程,同时也是抽象程度逐渐降低的过程

按照逐步求精的思想,程序的体系结构是按照层次结构,逐步精化过程细节而开发出来的,可见,求精就是细化,它与抽象是互补的概念

【信息隐藏】

信息隐藏是指一个模块内包含的信息,对于不需要这些信息的模块来说,是不能访问的,即该模块相对应其他模块是隐藏的

信息隐藏的目的,是为了提高模块的独立性,加强了外部对模块内部信息进行访问的限制,使得模块的局部错误尽量不影响其他模块

通常,模块的信息隐藏可以通过接口来实现,模块通过接口与外部进行通信,而把模块的具体实现细节隐藏起来

一般来说,一个模块具有有限个接口,外部模块通过调用相应的接口来实现对目标模块的操作

【复用性设计】

软件复用就是将已有的软件成分用于构造新的软件系统

可以被复用的软件成分一般称作可复用构件,无论对可复用构件原封不动地使用还是作适当的修改后再使用,只要是用来构造新软件,则都可称作复用

软件复用不仅仅是对程序的复用,它还包括对软件生产过程中任何活动所产生的制成品的复用,例如:软件开发计划、可行性研究报告、分析模型、设计模型、源程序、测试用例等等

如果是在一个系统中多次使用一个相同的软件成分,则不称作复用,而称作共享

对一个软件进行修改,使它运行于新的软硬件平台也不称作复用,而称作软件移值

【灵活性设计】

灵活性设计,是软件在面对需求修改时的随机应变能力,可以体现在修改程序代码的工程量等方面

抽象是软件设计的关键因素。设计模式、软件架构等可以用来实现更高抽象层次的编程,以达到软件的灵活性

在设计中引入灵活性的方法如下:

  • 提高模块独立性:降低耦合并提高内聚
  • 建立抽象:创建有多态操作的接口和父类
  • 不要将代码写死:消除代码中的常数
  • 抛出异常:由操作的调用者处理异常
  • 复用设计:使用并创建可复用的代码
感谢您对我的支持,让我继续努力分享有用的技术与知识点!