【软件构造课程笔记】设计规约

本文探讨了编程中的函数与方法概念,强调规约在程序交流中的关键作用,包括文档编写、规约分类、图形化表达及设计原则。学习如何创建强弱适中的规约,确保内聚性、返回值信息明确,以及合理使用前置和后置条件来提升代码可读性和可维护性。
摘要由CSDN通过智能技术生成

系列文章目录

第五章:设计规约



一、编程语言中的函数与方法

1.方法

方法是程序的积木,可以被独立开发,测试,复用,使用方法的客户端,无需了解方法内部具体是如何工作的–“抽象”

下图给出一个方法的例子,我们可以看到,可以分为方法的规约与方法的实现体两个部分。

在这里插入图片描述

二、 规约:程序的交流

1. 程序文档(举例)

在这里插入图片描述
在上面我们给出了java API documentation
其中包含了许多信息:

  1. 类的继承关系class hierarchy 与实现的接口 interfaces
  2. 直接的子类direct subclasses,对于接口interface来说,是interface的实现类。
  3. 类的描述
  4. 构造器摘要
  5. 我们可以调用的所有方法列表
  6. 对于构造器和方法的细节描述
    (1). 方法的返回类型,名称,参数,已经抛出异常
    (2). 整体的描述
    (3).对参数的描述
    (4). 对返回值的描述
    在这里插入图片描述

2. 规约

规约其实描述了程序与客户端之间达成的协议。 在调用的过程中,双方都要遵守。

规约的好处:
方便开发者消除误解,理解代码与定位错误。

  1. 精确的规约可以有助于区分责任
  2. 客户无需阅读调用函数的代码,即其中的具体实现,只需要了解规约,知道如何使用即可
  3. 规约可以隔离变化:当修改程序后无需通知客户端,客户还可按照之前的方式继续调用
  4. 防火墙:防止恶意篡改程序
  5. 解耦:无需了解具体的实现

3. 行为等价性

在这里插入图片描述

4. 规约的结构:前置条件和后置条件

前置条件(requires):对客户端的约束,在使用方法的时必须满足的条件。
后置条件(effects):对开发者的约束,方法结束时必须满足的条件。
契约:当前置条件满足,后置条件必须被满足。
对于java来说:

  1. 静态类型的声明是一种规约,可以根据此进行静态类型的检查。
  2. 方法前的注释也是一种规约,但是需要我们人工去判断是否满足。
    (1). 对于前置条件可以用@param来进行描述
    (2). 对于后置条件可以用@return @throws来进行描述
    例如:
    在这里插入图片描述

需要强调的是在规约中只可以提及参数与返回值,而不可以去透露任何本地变量与私有属性的信息。否则就会出现内存泄漏的情况。

三、 设计规约

1. 规约的分类

(1). 规约的强弱

规约的强度S2>=S1:
S2的前置条件更弱,后置条件更强
可以用S2代替S1
在这里插入图片描述
而在下面的这几种情况中,它们的强弱无法比较。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2). 规约的确定与不确定

确定的规约指:给定一个满足precondition的输入,他的输出是惟一的,明确的。
不确定的规约指:同一输入可以用多个输出
在这里插入图片描述

(3). 规约的操作式与声明式

操作式规约:伪代码,给出方法的具体实现流程。
声明式规约:没有内部实现的描述,只有始末状态。

一般情况下不应该使用操作式的规约,操作式的规约是为了解释maintainer的实现。

2.图形化规约

在这里插入图片描述
如上图所示:
每一个在上图中的点都代表着一个方法是实现。
程序员可以在规约的范围内自由选择实现的方式。
客户端无需了解具体使用了哪一个实现。
更强的规约,表达着更小的区域。

结合在上一讲中对规约强弱的区分:
在这里插入图片描述

3.设计一个好的规约

(1). 内聚性coherent

spec描述的功能应该单一,简单,容易理解。
在这里插入图片描述

(2). 返回值应该信息丰富

不能让客户端产生歧义。

(3). spec应该足够强

太弱的规约,客户不够放心。

(4). spec应该足够弱

太强的spec,在很多特殊情况下无法实现,给开发者增加了难度。

(5). 应该使用抽象类型

在规约中使用抽象类型,可以给方法的实现体和客户端更大的自由。
在java中,使用抽象类型指的是使用interface类型。

(6). 前置和后置条件

在正式执行前,要检查前置条件是否被满足。
不写前置条件,就要在代码内部实现check;
如果实现代价太大,在规约中加入前置条件,把责任交给客户端。

归纳:
是否使用前置条件取决于:

  1. check 的代价
  2. 方法的使用范围:
    如果只在类的内部使用该方法(private),那么可以不设置前置条件,在使用该方法的各个位置进行check。
    如果在其他地方使用该方法(public),那么必须设置前置条件,若客户端不满足则抛出异常。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值