【软件构造】设计规约(Java)

目录

一、简介

二、规约

1、Documenting in programming

2、Specification and Contract (of a method)

2.1必要性

2.2好处/作用

2.3内容/要求

3、Behavioral equivalence(行为等价性)

4、规格结构:前置条件和后置条件

三、设计规约

1、Classifying Spec

1.1规约的强度

1.2确定性

1.3陈述性

2、Diagramming Spec

3、设计良好的规约

3.1规约应是内聚的

3.2规约应是信息丰富的

3.3规约应足够强

3.4规约应足够弱

3.5规约应使用抽象类型

3.6先决条件or后决条件?


一、简介

        规约(spec):spec是软件构造中一种常用的手段,它规定了每个方法的作用,是在编程之前对各部分模块的总体设计。有了spec,才能分派任务,确定“供需双方”的责任,在调用时双方都要遵守,从而使程序与客户端之间达成一致。并定义正确实现的含义。一个软件在设计阶段就应该完成规约的设计,并且根据规约设计出测试程序,这会大大减少软件的生产周期。

        编程语言中的程序和方法:“方法”是程序的“积木”,可以被独立开发、测试、复用;使用“方法”的客户端,无需了解方法内部具体如何工作,即抽象的概念。

二、规约

1、Documenting in programming

        变量:写出数据类型定义记录关于它的一个假设,例如此变量将始终引用整数;使用final关键字,变量在初始赋值后永远不会更改,它定义了设计决策:“不可改变”。

        函数/方法:代码本身就蕴含着你的设计决策,但是远远不够。

        写出假设:有效防止第一自己记不住、别人看不懂。

        编写程序牢记两个目标:代码中蕴含给编译器的的“设计决策”、注释形式给自己和别人读的“设计决策”。

2、Specification and Contract (of a method)

2.1必要性

        很多bug来自于双发之间的误解,不将规定写下,那么不同开发者的理解就可能不同,出现错误时难以定位。有了规约可以分派任务,确定“供需双方”的责任,在调用时双方都要遵守,从而使程序与客户端之间达成一致。并定义正确实现的含义。

2.2好处/作用

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

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

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

       · 规约        扮演“防火墙”角色

2.3内容/要求

        ·输入/输出的数据类型

        ·功能和正确性

        ·性能

        ·只讲“能做什么”,不讲“怎么实现”

3、Behavioral equivalence(行为等价性)

        要确定行为等效性,问题是我们是否可以用一个实现替代另一个实现。站在客户端视角看,两个函数行为不同但对用户来说是否等价。

        单纯的看实现代码,并不足以判定不同的implmentation是否是“行为等价的” ;需要根据代码的spec(开发者与client之间形成的contract)判定行为等价性;在编写代码之前,就需要弄清楚spec如何协商形成、如何撰写。

4、规格结构:前置条件和后置条件

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

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

        契约:如果前置条件满足了,后置条件必须满足。前置条件不满足,则方法可做任何事情!

        Java中的spec:除非在后置条件里声明过,否则方法内部不应该改变输入参数;应尽量遵循此规则,尽量不设计mutating的spec,否则就容易引发bugs;程序员之间应达成的默契:除非spec必须如此,否则不应修改输入参数;尽量避免使用mutable的对象。

三、设计规约

1、Classifying Spec

1.1规约的强度

        Spec变强是指:更放松的前置条件+更严格的后置条件。越强的规约,意味着implementor的自由度和责任越重,而client的责任越轻。

1.2确定性

        确定的规约:给定一个满足precondition的输入,其输出是唯一的、明确的

        欠定的规约:同一个输入,多次执行时得到的输出可能不同。欠定的规约通常有确定的实现。

1.3陈述性

        操作式规约:如伪代码

        声明式规约:没有内部实现的描述,只有“初—终”状态。声明式规约更有价值。

2、Diagramming Spec

        某个具体实现,若满足规约则落在其范围内,否则,在其之外。程序员可以在规约的范围内自由选择实现方式,客户端无需了解具体使用了哪个实现。更强的规约,表达为更小的区域。

3、设计良好的规约

        一个好的“方法”设计,并不是你的代码写的多么好,而是你对该方法的spec设计得如何:一方面client用着舒服;另一方面开发者编着舒服。

3.1规约应是内聚的

        Spec描述的功能应单一、简单、易理解。

3.2规约应是信息丰富的

        不能让客户端产生理解的歧义

3.3规约应足够强

        太弱的spec,client不放心、不敢用 (因为没有给出足够的承诺)。开发者应尽可能考虑各种特殊情况,在post-condition给出处理措施。

3.4规约应足够弱

        太强的spec,虽然client会很高兴,在很多特殊情况下难以达到,但给开发者增加了实现的难度。

3.5规约应使用抽象类型

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

3.6先决条件or后决条件?


        客户端不喜欢太强的precondition,不满足precondition的输入会导致失败。惯用做法是:不限定太强的precondition,而是在postcondition中抛出异常:输入不合法。尽可能在错误的根源处fail,避免其大规模扩散。

        衡量标准:检查参数合法性的代价多大?

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

                ·如果只在类的内部使用该方法(private),那么可以不使用前置条件,在使用 该方法的各         个位置进行check——责任交给内部client;

                ·如果在其他地方使用该方法(public),那么必须要使用前置条件,若client端不满足则方         法抛出异常。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值