软件工程概论(六)设计模块

I. Design principles

What?!!

设计原则是指把系统功能和行为分解成模块的指导方针。它从两种角度明确了我们应该使用的标准,系统分解,以及确定在模块中将要提供哪些信息。
模块化(modularity)、接口(interface)、信息隐藏(information hiding)、增量式开发(incremental development)、抽象(abstraction)和通用性(generality)。

Modularity

模块化,也称关注点分离,是一种把系统中各不相关的部分进行分离的原则,以便于各部分能够独立研究。
关注点可以是功能、数据、特征、任务、性质或想要定义或详细理解的需求以及设计的任何部分。
如果该原则应用得当。每个模块都有自己唯一的目的,并且相对独立于其它模块。每个模块的理解和开发将会更简单。模块独立也使得故障的定位和系统的修改更加简单。

Component independence!!

Why component independence?

Coupling耦合度
两个模块之间有大量依赖关系时,这两个模块是紧密耦合。
松散耦合的模块之间具有某种程度的依赖性,但是他们之间的相互连接比较弱。
非耦合模块之间没有任何相互连接,他们之间是完全独立的。

模块之间的依赖方式有很多种:
一个模块引用另一个模块
一个模块传递给另一个模块数据量
某个模块控制其它模块(行为如是否调用某个进程等)

1、content coupling内容耦合
一个模块实际上修改了另一个模块

2、 common coupling公共耦合
通过对设计进行组织,使其从公共数据存储区来访问数据,但是依赖关系依然存在,因为对公共数据的改变意味着要通过反向追踪所有访问过该数据的模块来评估该改变的影响。

3、 control coupling控制耦合
当某个模块通过传递参数或返回代码来控制另一个模块的活动时,就称这两个模块是控制耦合。
优点:每个模块只完成一个功能或进程,模块间传递的控制信息减到最少,接口也简化成固定的、可识别的参数和返回值集合。

4、stamp coupling标记耦合
如果使用一个复杂的数据结构来从一个模块到另一个模块传递信息,并且传递的是该数据结构本身,那么两个模块之间就是标记耦合。(数据格式和组织方式必须匹配)

5、data coupling数据耦合
如果传送的只是数据值,不是结构数据,那么模块之间就是通过数据耦合。

Cohesion内聚度
内聚指的是模块内部元素(如数据、功能、内部模块)的黏合程度。

1、coincidental
内聚度最低的是巧合内聚,只是由于方便或偶然的原因,不相关的功能、进程或数据处于同一个模块中。

2、 logical
当一个模块中的各个部分只通过代码的逻辑结构相关联时,称这个模块具有逻辑内聚。
根据接收的不同参数执行不同的操作。尽管这些不同的操作体现了一定的内聚他们之间会共享一些程序状态和代码结构,但这种代码结构的内聚相对于数据、功能或目标的内聚是比较弱的。引入新操作时,就比较难以理解和维护。

3、 temporal
设计被划分为几个用来表示不同执行状态的模块,初始化、读进输入、计算、打印输出和清除,这样的内聚是时态内聚。
在这种模块中数据和功能仅仅因为在一个任务中同时被使用而形成联系。这样的设计会造成代码重复,因为多个模块对关键数据结构的操作都比较类似。

4、 procedural
通常,必须按照某个确定的顺序执行一系列功能,如果模块中的功能组合在一起只是为了确保这个顺序,那么该模块就是过程内聚。
同时态内聚相比,有一个优点,其功能总是涉及相关的活动和相关的目标。
这样一种内聚只会出现在模块本身运用的上下文环境中,如果不知道模块的上下文环境,则很难理解为什么这么工作,也很难修改。

5、communicational
将某些功能关联起来,因为他们是操作或生成一个数据集的,围绕数据集构造的模块是通信内聚

6、functional
理想的情况是功能内聚,满足两个条件。在一个模块中包含了所有必需的元素,并且每一个处理元素对于执行单个功能来说都是必需的。某个功能内聚的模块不仅执行设计的功能,而且只执行该功能,不执行其它任何功能。

7、informational
在功能内聚的基础上,将其调整为数据抽象化和基于对象的设计,就是信息内聚。

Interface

接口为系统其余部分定义了该软件单元提供的服务,以及如何获取这些服务。

一个对象的接口是该对象所有公共操作以及这些操作签名的集合,指定了操作名称、参数和可能的返回值。
更全面的讲,依据服务或假设,接口还必须定义该单元所必须的信息,以确保该单元能够正确工作。

接口是这样一种设计结构,它对开发人员封装和隐藏了软件单元的设计和实现细节。
软件接口单元的规格说明描述了软件单元外部可见的性质。接口规格说明的描述只涉及软件单元边界的实体,该单元的访问函数、参数、返回值和异常。一个接口的规格说明需要向其它系统开发人员传达正确应用该单元的所有信息,这些信息不应该局限于单元的访问函数和它的签名,还应包括以下几点:
1、目标:为每个访问函数的功能建立充分详细的文档,以帮助其它开发人员找出最符合他们需求的函数
2、前置条件:列出所有假设,以帮助开发人员了解在何种情况下该单元才能正常工作
3、协议:包括访问函数的调用顺序、两个构件交换消息的模式。比如,一个调用模块访问共享资源之前需要被授权允许。
4、后置条件:将可见的影响称为后置条件。为每个访问函数的后置条件编写文档,包括返回值、引发的异常以及公共变量的变化,这样,调用它的代码才能对函数的输出作出适当的反应。
5、质量属性:这里描述的质量属性(如性能、可靠性)是对开发人员和用户可见的。只有可见才能评价是否起作用。

理想上接口精确描述了所有可接受的集合,但过于严格也容易将可接受的操作排除在外。

Information Hiding

信息隐藏的目标是使得软件系统更加易于维护。它以系统分解为特征。每个软件单元都封装了一个将来可以改变的独立的设计决策,然后我们根据外部可见的性质,在接口和接口规格说明的帮助下描述了各个软件单元。
信息隐藏的一个好处是使得软件具有低耦合度。每个单元的接口列出了该单元提供的访问函数和需要使用的其它访问函数的集合。这个特征使得软件易于理解、维护和定位。

Incremental development

首先,指定单元之间的使用关系它为各个软件单元和它依赖的单元之间建立关联。将系统的这种使用关系表述成使用图,图中节点代表软件单元,有向边从使用其它单元的软件单元出发,指向被使用的单元。使用图可以帮助我们逐步确定更大的系统子集,对此我们可以增量的进行实现和测试。
扇入指代使用某个软件单元的软件单元数量,扇出指代某个软件单元使用其它软件单元的数量。设计一个系统的最终目标之一是创建一个有着高扇入、低扇出的软件单元。
使用夹层法消除循环。

Abstract

抽象是一种忽略一些细节来关注其它细节的模型或表示。目标不同,忽略的细节也不同。
对于一个特定的模型,一个好的抽象的关键是决定哪些细节是不相关的,进而可以被忽略。抽象的性质取决于开始时我们建立这个模型的初衷,我们想交互哪些信息,或者我们想展示哪个分析过程。

Generality

在开发软件单元时,使它尽可能的能够称为通用的软件,来加强它在将来某个系统中能够被使用的可能性。
我们通过增加软件单元使用的上下文环境的数量来开发更加通用的软件单元,下面是几条实现规则:
将特定的上下文环境信息参数化:通过把软件单元所操作的数据参数化,我们可以开发出更加通用的软件
去除前置条件:使得软件在那些我们之前假设不可能发生的条件下工作
简化后置条件:把一个复杂的软件单元分解成若干个具有不同后置条件的单元,再将他们集中起来解决原来需要解决的问题,或者当只需要其中一部分后置条件时单独使用。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值