目录
1.规约(Programming for communication)
1.规约(Programming for communication)
1.1一个方法的规约和合同
规约是团队合作的关键关键。如果没有规约,就不可能委托执行实现方法的责任;同时,它也能在程序与客户端之间达成一致:Spec给“供需双方”都确定了责任,在调用的时候双方都要遵守。
规约:扮演“防火墙”角色
–它保护客户不受单元工作细节的影响。
–它保护实现者不受单元使用细节的影响。
–此防火墙会导致解耦,允许独立地更改单元的代码和客户端的代码,只要这些更改涉及到规范。
规约是对象与其用户之间的协议
它确定了Method signature;描述了对程序功能和正确性的期望;但同时它只讲“能做什么”,不讲“怎么实现”
1.2规约结构:前置条件和后置条件
一个方法的规约由以下几个部分组成:
– 前置条件(Precondition) , 用关键字表示: requires
– 后置条件(Postcondition) ,用关键字表示: effects
– 预期行为(Exceptional behavior): what it does if precondition violated
后置条件:对开发者的约束,方法结束时必须满足的条件
契约:如果前置条件满足了,后置条件必须满足;如果前置条件不满足,则方法可做任何事情。
在可能的情况下,将前置条件放入 @param ,将后置条件放入 @return 和 @throws 。
例如:
1.3在规约中讨论什么?
方法的规约可以讨论方法的参数和返回值,但它不应该讨论方法的局部变量或方法类的私有域。
1.4变值方法的规约
这是由于程序中可能有很多变量指向同一个可变对象(别名)、无法强迫类的实现体和客户端不保存可变变量的“别名”。
2.设计规约
2.1规约的强度
规范S2的强度大于或等于规范S1(可以用S2替换规约S1),如果:
–S2的前提条件弱于或等于S1
–对于满足S1前置条件的状态,S2的后置条件大于或等于S1。
更弱前提条件:对客户提出更少的要求,永远不会困扰他们。
更强后置条件,这意味着要做出更多的承诺
2.2图示规约
–这个空间中的每个点都代表一个方法实现。
–规约定义了所有可能实现空间中的一个区域。
–某个具体实现,若满足规约,则落在其范围内;否则,在其之外。
–程序员可以在规约的范围内自由选择实现方式
–客户端无需了解具体使用了哪个实现
2.3设计好的规约原则
(1).规约应是内聚的
Spec描述的功能应单一、简单、易理解,例如:
该规约做了两件事,所以要分离开形成两个方法,这样可以使它们更简单(易于理解),在其他上下文中更有用(易于更改)。
(2).规约应是足够强的
在一般情况下,该规范应该给客户一个足够强大的保证——它需要满足他们的基本要求。
太弱的spec,client不放心、不敢用 (因为没有给出足够的承诺)。开发者应尽可能考虑各种特殊情况,在post-condition给出处理措施。
(3).规约应是适当弱的
太强的spec,在很多特殊情况下难以达到,给开发者增加了实现的难度。例如:
这不是一个好的规约:
–它缺少重要的细节:文件是打开来读取还是写?它是已经存在的还是已经被创造出来的?
–它太强了,因为它没有办法保证打开一个文件(它运行的过程可能缺乏打开文件的权限,或者可能是文件系统存在一些超出程序控制范围的问题)
相反,规范应该说明一些更弱的东西:它试图打开一个文件,如果它成功了,该文件就具有某些属性。
(4).规约应使用抽象类型
在规约里使用抽象类型,可以给方法的实现体与客户端更大的自由度
在Java中,这通常意味着使用接口类型,如 Map 或 Reader ,而不是特定的实现类型,如 HashMap 或 FileReader 。
例如:
(5).是否使用前置条件?
是否使用前置条件取决于:(1) check的代价;(2) 方法的使用范围。
– 如果只在类的内部使用该方法(private),那么可以不使用前置条件,在使用该方法的各个位置进行check——责任交给内部client;
– 如果在其他地方使用该方法(public),那么必须要使用前置条件,若client端不满足则方法抛出异常。