软件构造(五)

 

 

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

方法中输入参数和返回参数的匹配在静态类型检查阶段完成

“方法”是程序的“积木”,可以被独立开发、测试、复用

使用“方法”的客户端,无需了解方法内部具体如何工作—“抽象”

final关键字定义了设计决策:“不可改变”

为什么要写出“假设”?第一:自己记不住;第二:别人不懂

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

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

二、编程中的规约

2.1作用

没规约,没法分派任务,无法写程序;即使写出来,也不知道对错;契约,是程序与客户端之间达成的一致;Spec给“供需双方”都确定了责任,在调用的时候双方都要遵守

在现实中:(1)很多bug来自于双方之间的误解不写下来(2)那么不同开发者的理解就可能不同(3)没有规约,难以定位错误

2.2好处:精确的规约,有助于区分责任;客户端无需阅读被调用函数的代码,只需理解spec即可

2.3 Specification:(1)规约可以隔离“变化”,无需通知客户端(2)规约也可以提高编码效率(3)扮演“防火墙”角色:客户端不需要知道实现,实现者不需要知道如何被使用,解耦,不需了解具体实现。

 

 

2.4应包括(1)输入/输出的数据类型(2)功能和正确性(3)性能

应满足只讲“能做什么”,不讲“怎么实现”

三、规约前后置条件

站在客户端视角看行为等价性:根据规约判断是否行为等价,若两个函数符合同一个规约,则它们等价

(1)前置条件:对客户端的约束,在使用方法时必须满足的条件;

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

(3)契约:如果前置条件满足了,后置条件必须满足

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

(5)除非在后置条件里声明过,否则方法内部不应该改变输入参数,程序员之间应达成的默契:除非spec必须如此,否则不应修改输入参数,mutable对象会使规约复杂化

(6)在规约里限定住“不可变”,不依赖双方的“道德”

四、设计规约

4.1(1)规约的确定性(描述的输出是否确定) (2)规约的陈述性(只是描述了输出,还是描述了如何计算输出) (3)规约的强度

4.2规约的强度:更强大规约=更放松的前置条件+更严格的后置条件。越强的规约代表着编写者的自由度越低责任越重,而客户的责任越轻。

4.3某个具体实现,若满足规约,则落在其范围内;否则,在其之外。不可比较的规约圈相交。

4.4客户端不喜欢太强的前置条件,不满足前置条件的输入会导致失败。

惯用做法是:不限定太强的前置条件,而是在抛出异常:输入不合法

4.5是否使用前置条件取决于(1) check的代价;(2) 方法的使用范围

--如果只在类的内部使用该方法(private),那么可以使用前置条件(方法内部不需要判断输入是否满足,认为client会保证前置条件),在使用该方法的各个位置进行check——责任交给内部client

--如果在其他地方使用该方法(public),那么可以不使用/放松前置条件(在方法内部检查输入是否满足),若client端不满足则方法抛出异常。

 

心得感想:对于规约,就像将约定俗成或是说揣测化为书面的明文合同,是一个很好的约束程序员以及客户端的方式,并且,规约对于大型项目之中迅速掌握函数功能以及区分函数也有很大作用。

posted @ 2022-06-07 16:34  llhm  阅读(118)  评论(0)    收藏  举报