本篇blog的内容来源于对MIT课程中的readings 6 - Specifitions阅读后的一些总结和个人的理解
网址:http://web.mit.edu/6.031/www/fa18/classes/06-specifications/
这篇reading详细介绍了java程序编写中的specifications的相关,通篇读下来觉得酣畅淋漓,写的十分精彩。
总结
Specification是一个相当严谨的概念。如果上课没有仔细听课,或者看书的时候没有认真,很容易把specification直接理解成“就是给每个方法写一个大致的描述”。实际上,specification比这要复杂得多。
以下是我在阅读过程中,对重点内容的一些总结。
Specification的作用
简单来说,Specification就是在程序中方法的层层调用之间添加一层约定,已达到解耦和的目的。
稍微详细一点讲:我们在编程的时候会写很多方法,很多类,这些方法与类层层调用,互相影响。程序越大,这个调用关系就越复杂,代码就越发臃肿和难以理解,程序的维护就变得相当困难,更是给所有尝试理解代码的人灵魂上的折磨。而Specification用来在不同方法之间划清界限,写下约定条件,对敲代码的人来说是一种目标与约束,对阅读代码的人来说则是提示。
specification的组成
粗略的了解specification,大概需要掌握四个方面的内容:
- Precondition(前置条件)与Postcondition(后置条件)
- 测试用例的设计
- Checked Exception 与 Unchecked Exception的区别
- 使用Exception时的取舍
Precondition与Postcondition
如果说没有specification的代码是一大堆便便,那么加入了specification,用pre和post condition限制了之后的代码就是用许多塑料袋把便便按功能封装起来,这样,Client,也就是调用者,只能够看到塑料袋,条理自然要清晰明确很多。
二者区别何在:
方法要有输入与输出,Precondition用于限制输入,Postcondition用于限制输出。
更进一步
Precondition规定了这个方法所接受的合法输入,也就是在client调用这个方法时,要想使方法能够产生正确的结果,client所需要满足的条件(其实就是输入的变量的条件)
Postcondition只会在Precondition被满足时才有意义。Postcondition规定了在Precondition被满足的情况下,调用当前方法所产生的影响。
分工明确,方法的调用者以满足precondition为目标,方法的编写者则默认precondition已经被满足,以满足postcondition为目标。
specification只给出了满足precondition条件下,postcondition必须被满足。如果precondition没有被满足,那么方法就可以为所欲为。
举个例子,某个方法要求输入一个大于0的整数。如果输入的整数小于0,我们的方法可以:
- throw一个异常出去
- 返回一个null值
- 在控制台输出信息
- 唱,跳,rap,篮球
- 中止程序执行
- 播放歌曲
- ~~爆炸~~
除非spec里提到了输入值小于0时方法应该怎么做,否则方法可以为所欲为
关于NULL
null为什么要存在?
为了给程序员找麻烦
readings里面只介绍了如何避免null带来的麻烦,却没有说明null存在的合理性,无需多言,大家都懂。
妙的是,readings说“null values are implicitly disallowed in parameters and retur values ... Avoid null”
在编程中应该时刻注意null的处理
- 基本数据类型不能够被声明为null
测试用例的设计
如何保证给出的pre 和post condition是正确的?针对二者设计测试用例
测试用例可以分为两类:
- black box
- glass box
二者都必须遵循specification
black box很好理解,就是针对preconditon与postcondition,充分考虑各种边界条件来设计测试用例即可。
但是glass box存在的理由是什么?我们设计测试用例是绝对不能踏出specificatioin一步的,虽然specification隐藏了方法的内部实现,但是并不是说对方法内部设计测试用例就会跨越这条界限。
方法之间也许存在相互依赖。?留一个疑问在这里,我仍然不能很好的理解glass box的意义
Checked Exception 与 Unchecked Exception
二者的区别在于,checked Exception必须要被try catch语句包围,或者要在外围方法中添加throws语句即意味着:这个exception必须显式地被处理掉。
checked exception一般用于处理意料之中的特殊情况,比如说错误的输入,这是完全有可能的。那么在这里exception其实就是一个很方便的 fail fast的工具,是用来立刻对特殊情况产生响应的。
unchecked exception则不需要被try catch 包围,也就是说,不用去管。
unchecked exception用于处理错误情况,一般会有两种可能
- 这个问题解决不了,程序没有任何希望了,只能直接报错
- ??这里为什么会出问题?这是完全意料之外的,没法预先设置处理方案,只能直接报错
理解
specification的作用说来说去,还是解耦和。把功能包装起来,把问题产生的范围缩小,不同的人可以专心于不同的工作,不需要为各种不确定的条件所烦恼。