Designing Specification 设计规约

一、Functions & methods in programming languages

规约实例:

二、Specification: Programming for communication

1.Documenting in programming

Documenting Assumptions :代码中变量的数据类型定义; final关键字定义了设计决策:“不可改变”;代码本身就蕴含着你的设计决策,但是远远不够。
代码中蕴含的“设计决策”:给编译器读
注释形式的“设计决策”:给自己和别人读
2.Specification and Contract(of a method)
没规约,没法分派任务,无法写程序;即使写出来,也不知道对错。
规约是 程序与客户端之间达成的一致, 明确双方的责任 定义正确实现的含义。
Spec给“供需双方”都确定了责任,在调用的时候双方都要遵守。
Why specifications?
Reality: 很多bug来自于双方之间的误解;不写下来,那么不同开发者的理解就可能不同;没有规约,难以定位错误。
Advantages: 精确的规约,有助于区分责任;客户端无需阅读被调用函数的代码,只需理解spec即可。

 

3.Behavioral equivalence

The notion of equivalence is in the eye of the client (站在客户端视角看行为等价性) .

根据规约判断是否行为等价。

总结:

4.Specification structure: pre-condition and post-condition

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

后置条件:对开发者的约束,方法结束时必须满足的条件
契约:如果前置条件满足了,后置条件必须满足。前置条件不满足,则方法可做任何事情。
当前置条件被违反时,说明客户端有bug,尽管实现者没有义务提醒,但可通过快速失败使bug更容易被找到和修复。
静态类型声明是一种规约,可据此进行静态类型检查static checking。方法前的注释也是一种规约,但需人工判定其是否满足。
Parameters are described by @param clauses and results are described by @return and @throws clauses.
Put the preconditions into @param where possible, and postconditions into @return and @throws.
Specifications for mutating methods:除非在后置条件里声明过,否则方法内部 不应该改变输入参数。应进料量遵循此规则,尽量不设计 mutating的spec,否则就容易引发bugs。程序员之间应达成的默契:除非spec必须如此,否则不应修改输入参数 mutable对象会使规约复杂化。
三、 Designing specifications
1. Classifying specifications
规约的确定性(描述的输出是否确定);规约的陈述性(只是描述了输出,还是描述了如何计算输出);规约的强度。
spec变强:更放松的前置条件+更严格的后置条件
Rules:
Weaken the precondition: placing fewer demands on a client will never upset them. 更少的要求
Strengthen the post-condition, which means making more promises.                         更多的承诺
2. Diagramming specifications
更强的后置条件意味着实现的自由度更低了 ➔在图中的面积更小
更弱的前置条件意味着实现时要处理更多的可能输入,实现的自由度低了➔面积更小
3. Designing good specifications
一个好的“方法”设计,并不是你的代码写的多么好,而是你对该方法的spec设计的如何。
– 一方面:client用着舒服
– 另一方面:开发者编着舒服
Spec描述的功能应单一、简单、易理解;不能让客户端产生理解的歧义。
太弱的spec,client不放心、不敢用 (因为没有给出足够的承诺)。开发者应尽可能考虑各种特殊情况,在post-condition给出处理措施。
太强的spec,在很多特殊情况下难以达到,给开发者增加了实现的难度(client当然非常高兴)。
在规约里使用抽象类型,可以给方法的实现体与客户端更大的自由度。
客户端不喜欢太强的precondition,不满足precondition的输入会导致失败。
惯用做法是: 不限定太强的precondition,而是在postcondition中抛出异常:输入不合法。
尽可能在错误的根源处fail,避免其大规模扩散。
▪ 归纳:是否使用前置条件取决于(1) check的代价;(2) 方法的使用范围
– 如果只在类的内部使用该方法(private),那么可以使用前置条件(方法内部不需要判断输入是否满足,认为client会保证前置条件),在使用该方法的各个位置进行check——责任交给内部client;
– 如果在其他地方使用该方法(public),那么可以不使用/放松前置条件(在方法内部检查输入是否满足),若client端不满足则方法抛出异常。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值