HIT软件构造:设计规约

本文探讨了面向对象编程中的规约,强调了它们在团队协作和代码解耦中的关键作用。规约包括前置条件和后置条件,用于确保方法的正确使用和实现。设计规约应具备适当的强度,既不过强导致实现困难,也不过弱让客户不信任。此外,规约应使用抽象类型以增加灵活性,并在必要时使用前置条件保障方法调用的正确性。设计良好的规约原则包括内聚性、足够的强度、适当的弱度、使用抽象类型以及谨慎使用前置条件。
摘要由CSDN通过智能技术生成

目录

1.规约(Programming for communication)

1.1一个方法的规约和合同

1.2规格结构:前置条件和后置条件

1.3在规约中讨论什么? 

 1.4变值方法的规约

2.设计规约

2.1规约的强度

2.2图示规约

2.3设计好的规约原则

1.规约(Programming for communication

1.1一个方法的规约和合同

规约是团队合作的关键关键。如果没有规约,就不可能委托执行实现方法的责任;同时,它也能在程序与客户端之间达成一致:Spec给“供需双方”都确定了责任,在调用的时候双方都要遵守。
规约:扮演“防火墙”角色 
它保护客户不受单元工作细节的影响。
它保护实现者不受单元使用细节的影响。
此防火墙会导致解耦,允许独立地更改单元的代码和客户端的代码,只要这些更改涉及到规范。
 

规约是对象与其用户之间的协议
它确定了Method signature;描述了对程序功能和正确性的期望;但同时它只讲“能做什么”,不讲“怎么实现”

1.2规约结构:前置条件和后置条件

一个方法的规约由以下几个部分组成:
前置条件(Precondition) , 用关键字表示: requires
后置条件(Postcondition) ,用关键字表示: effects
预期行为(Exceptional behavior): what it does if precondition violated

前置条件:对客户端的约束,在使用方法时必须满足的条件
后置条件:对开发者的约束,方法结束时必须满足的条件
契约:如果前置条件满足了,后置条件必须满足;如果前置条件不满足,则方法可做任何事情。

静态类型声明是一种规约,可据此进行静态类型检查static checking。
方法前的注释也是一种规约,但需人工判定其是否满足。
在规约中, 参数由 @param 描述,结果由 @return@throws 描述;
在可能的情况下,将前置条件放入 @param ,将后置条件放入 @return@throws
例如:

1.3在规约中讨论什么? 

方法的规约可以讨论方法的参数返回值,但它不应该讨论方法的局部变量或方法类的私有域

 1.4变值方法的规约

除非在后置条件里声明过,否则方法内部不应该改变输入参数,几乎所有的程序员都会假设这样的事情。意外的变值会导致bug。(除非spec必须如此,否则不应修改输入参数)。
这是由于程序中可能有很多变量指向同一个可变对象(别名)、无法强迫类的实现体和客户端不保存可变变量的“别名”。

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端不满足则方法抛出异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值