3.2设计规约

课程目的

方法的规约

前置/后置条件

确定规约,非确定规约

陈诉式、操作式规约

规约的强度及其比较

如何写出好的规约

大纲

1.编程语言中的函数/方法

2.编程信息

3.设计规约

4.总结

 

3.2.1.编程语言中的函数/方法

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

参数——参数类型是否匹配,在静态类型检查阶段完成

返回值——返回值类型是否匹配,也在静态类型检查阶段完成

变量的作用域

 

一个完整的方法

包含方法的规约spec和方法的实现体implementation

 

 

3.2.2.编程信息

(1)记录编程

-类的层次结构和已实现接口的列表

-描述子类和接口,实现类

-对类的描述

-构造方法的摘要

-方法的汇总列出了我们可以调用的所有方法

-每个方法和构造方法的详细描述:

·方法签名:这里有返回值类型,方法名称和参数类型。

·有完整的描述

·参数:方法参数的描述

·以及返回值的类型的描述

 

(2)记录假设

变量的数据类型定义

Java实际上在编译时检查了这个假设,并保证在你的程序中没有地方违反了这个假设。

final关键字定义了设计决策:不可改变java会进行静态检查)

虽然代码本身就蕴含着你的设计决策,但是远远不够

 

(3)编程信息

为什么要写出假设

第一:自己记不住;第二:别人不懂。

写程序必须记住两个目标:

代码中蕴含的设计决策:给编译器读

注释形式的设计决策:给自己和别人读

(4)黑客和工程师

工程师应该是悲观主义者——测试优先

   考虑自己能够想到的所有情况

    随时记录代码中的设计决策

 

 

(2)规约(或称合约)

没规约,没法写程序;即使写出来,也不知道对错

程序与客户端之间达成的一致

Spec供需双方都确定了责任,在调用的时候双方都要遵守

为什么要有规约:

现实是:

-很多bug来自于双方之间的误解

-不写下来,那么不同开发者的理解就可能不同

-没有规约,难以定位错误

规约的优点:

-精确的规约,有助于区分责任

-客户端无需阅读调用函数的代码,只需要理解spec即可

比如

 

-规约可以隔离变化,无需通知客户端

-规约也可以提高代码效率

-规约扮演防火墙角色

- 解耦,不需了解具体实现

规约:

-输入输出的数据类型

-功能和正确性

-性能

-只讲能做什么,不讲怎么实现

 

(3)行为等价性

行为等价性:是否可以相互替换 (站在客户端视角看行为等价性).

根据规约判断是否行为等价---若两个方法符合一个规约,则它们等价,和方法内部实现过程没有关系

(4)规约结构

规约结构:

-前置条件:对于客户端的约束,在使用方法时必须满足的条件

-后置条件:对开发者的约束,方法结束时必须满足的条件

 ps:如果前置条件满足了,后置条件必须满足

 前置条件不满足,则方法可做任何事情

 

 

 

#变化方法(改变了参数的方法就叫变化的方法)中的规约

  除非在后置条件里声明过,否则方法内部不应该改变输入

  应尽量遵循此规则,尽量不设计mutating的方法

————这是程序员之间应达成的默契

#可变的方法使简单的规约变得复杂

  程序中可能有很多变量指向同一个可变对象

  开发者和客户端之间的契约无法得到保证

  所以不能只靠程序员所谓的道德,要靠严格的契约来规定

 

#可变的方法对程序的安全性造成了巨大破坏

  所以避免使用可变的全局变量

  但是为了性能原因,有时候却不得不用

 

#可变的方法降低了可变性

  可变的数据类型导致程序的修改变得异常困难

 

(5)测试和验证规约

规约是文字说明的,在方法前面进行说明

#有方法的作用

#有参数的数据类型和值规定和意义

#有返回值的意义和返回的数据类型

 

正式检验

#用数学方法来证明的它的正确性

#正式证明一个实现的所有可能的参数是否符合规约

#手动努力;部分自动化;不能完全自动确定

 

······“测试表示存在这种可能,不代表没有bug”

 

测试

在受控环境下测试执行程序

-显示错误,因此可以修复(主要目标)

-评估质量

-明确说明书,文件

 

黑盒测试

以独立的实现方式检车测试的程序是否遵循指定的

 

3.2.3设计规约

(1)规约的分类

怎么比较规约的好坏:

-规约的正确性

-规约的陈述的流畅易懂性

-规约的强度

 

确定和欠定(未确定)的规约比较

确定的规约:给定一个满足前置条件的输入,其输出是唯一的、明确的。

欠定(under-deterministic)的规约:同一个输入可以有多个输出

非确定(Non-deterministic)的规约:同一个输入,多次执行时得到的输出可能不同

-为了避免混乱,not d == under d

-欠定的规约通常有确定的实现

 

声明式规约和操作式规约

操作式规约:例如伪代码

声明式规约:没有内部实现的描述,只有-状态

#声明式规约更有价值

#为什么有操作式规约?

内部实现的细节不在规约里呈现,放在代码实现体内部注释里呈现。

 

规约的强弱

如何比较两个规约,以判断是否可以用一个规约替换另一个?

规约的 强度S2 >=S1

条件:

 -S2的前置条件比S1弱 (S2的容错能力比S1好,给了用户更宽广的使用范围)

 -S2的后置条件比S1

 #满足以上条件时就可以用S2代替S1

 

 

(2)图表式规约

某个具体实现,若满足规约,则落在其范围内;否则,在其之外。

#程序员可以在规约的范围内自由选择实现方式

#客户端无需了解具体使用了哪个实现

 

(3)设计良好的规约

规约的质量怎么判定:

#规约应该是内聚的——规约Spec描述的功能应单一、简单、易理解

#规约对返回值的描述应该是完整(informative)的——不能让客户端产生理解的歧义

#规约应该足够强大和完整

#规约也应该简单易懂——太强的Spec,在很多特殊情况下难以达到

#规约里应该用抽象数据类型——  在规约里使用抽象类型,可以给方法的实现体与客户端更大的自由度

#是否应该使用前置条件?在方法正式执行之前,是否要检 查前置条件已被满足?

不写Precondition,就要在代 码内部check;若代价太大, 在规约里加入precondition, 把责

任交给client(衡量标准:检查参数合法性的代 价多大?)

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值