第三次OO博客作业

一.规格化设计的发展历史
  规格化设计的一个重要目的是为了将模块的功能,约束表达清楚,方便用户与开发者的信息交流,从这一点来看,规格化设计的出现与结构化设计有着密不可分的关系,接下来,我将从结构化设计的角度来讨论规格化设计。
  程序设计的演变大致可以分成以下三个过程:
  1. 20世纪60年代以前,计算机刚刚投入实际使用,软件设计往往只是为了一个特定的应用而在指定的计算机上设计和编制,采用密切依赖于计算机的机器代码或汇编语言,软件的规模比较小,很少使用系统化的开发方式,此时的代码更多的是私人性质的,满足个人要求的程序;
  2. 60年代中期,大容量、高速度的计算机出现,随之出现的是代码量急剧提升,复杂度急剧增长、程序可靠性问题突出的问题。结果化程序设计随之提出,它要求程序设计时以模块为单位,每个模块专职自己的工作,而要在模块间交流,在开发者和用户,开发者和开发者之间交流,就只需要相应接口即可;
  3. 80年代,面向对象的设计开始在业界大行其道,相比于单纯的结构化设计,面向对象的设计从审视问题的角度上就有了差异,程序发生了从围绕“行为”执行到围绕“客体”执行的变化,随之而来的,就是封装性地提高,可重用性的提高,可以说,面向对象进一步实现了结构化设计,是结构化设计更进一步的实现。
  在结构化越加明确的同时,开发者与设计者,开发者与用户,开发者与开发者之间的交流,就需要“抽象”来实现,因为彼此间不需要关心对方的实现方法,而只需要知道这个模块的接口有什么要求,会改什么,能做什么就行。通过规格化抽象,我们就能将这种交流变得高效,同时也降低了维护和修改的难度。
二.三次作业中的规格错误

序号  错误类别  错误原因
1 EFFECTS不完整  以Taxi.java为例,run方法的EFFECTS只有一句话 A taxi will run here
2 不符合JSF规范 @和后面的标识符之间有空格
3 针对构造方法,初始repOK为真 repOK逻辑错误,return true写成了return false
4 MODIFIES逻辑错误 该函数既不修改对象本身的内容, 也不修改传入参数的内容,它修改的是作为返回值的一个局部变量,不应该将这个局部变量写到MODIFIES中
5 REQUIRES不完整 Taxi.java 的 run()函数没有写REQUIRES,但这个函数依赖了许多变量,没有REQUIRES 是不行的。


三.规格错误的产生原因及解决
  首先,2、3不用多加讨论,属于粗心导致的错误,剩下的三个点,恰好对应了jsf规格的三个种类。首先对于EFFECTS不完整的错误,因为run方法它实现了出租车四个状态之间的切换和它的运行规则,所以其实不是很好表述,后来我想可以抽象表示其状态的切换而忽略其它运行细节,所以有了这样的表述:
@EFFECTS:
(this.request==null && count%20!=0 && \old this.status==”waiting”) || (this.request!=null && this.location==this.destination && \old this.status==”service”) ==> this.status==”waiting”||
(count%20==0 &&\old this.status==”waiting”) || (count%20!=0 && (this.location==this.destination && \old this.status==”service” || this.location==this.source && \old this.status==”taking_order”)) ==> this.status==”still” ||
(this.request!=null && \old this.status==”waiting”) ==>this.status==”taking_order” ||
this.request!=null && \old this.status==”still” ==>this.status==”service”
  对于MODIFIES逻辑错误,这是我第一次书写是没有通透jsf表达规范导致的------对于局部变量,即便它是最终的返回值,也不应该写入MODIFIES中;
  对于REQUIRES不完整,run()方法内部用到的变量都是对象内部的属性,对于这个应不应该写到REQUIRES中,我问到的同学有不同看法,我将我认为需要限制的变量取值给予了规定。
四.类规格的不佳写法
1.自然语言vs布尔表达式(EFFECTS)
  这两个不用多说,大家都明白两者优劣,布尔表达式胜在准确,但是一来归纳难,二来写法难,特别是对于run方法,有些同学(包括我)run方法写的比较长,对于变量的修改较多,此时使用布尔表达式,怕是光一个jsf就要写几十行。此时,简单并且有极强概括性的自然语言就很好写了,若干行就能说明问题,但是此时需注意的就是布尔表达式针对变量进行总结,但是自然语言往往更加偏向于叙述程序做了什么事情,容易写成叙述算法的不合格的类规格。此处实例即为我的run方法:
  改前:@EFFECTS:A taxi will run here
  改后(针对status变量的部分):@EFFECTS:
  (this.request==null && count%20!=0 && \old this.status==”waiting”) || (this.request!=null && this.location==this.destination && \old this.status==”service”) ==> this.status==”waiting” ||
  (count%20==0 &&\old this.status==”waiting”) || (count%20!=0 && (this.location==this.destination && \old this.status==”service” || this.location==this.source && \old this.status==”taking_order”)) ==>     this.status==”still” ||
  (this.request!=null && \old this.status==”waiting”) ==>this.status==”taking_order” ||
  this.request!=null && \old this.status==”still” ==>this.status==”service”

2.自然语言vs布尔表达式(REQUIRES)
  相比于EFFECTS,REQUIRES的书写较为简单,REQUIRES只需要对变量做一个范围的规范即可,但是这两天也遇到了使用自然语言书写REQUIRES的同学,自然语言中,“合适的”(proper)这个词可以说是个万金油的词汇,什么方法也可以说,请给我一个proper的参数……但是这确实不妥,每个参数都应该有确定的取值范围(也即使用布尔表达式更为妥当)。
3.自然语言的表达
  如果选择自然语言表达,怎么也应该表达地清楚明了吧……近两次测试中我碰到了若干完全读不通的EFFECTS。我觉得EFFECTS要么使用布尔表达式,要么就用“流利”的英文来表达,对于无法使用布尔表达式表示的关系或者操作可以使用自然语言来代替。
五.思路以及体会
  一开始听到要写jsf我是很拒绝的,但是迫于扣分压力又不得不写(废话)。在经历了若干bug的洗礼,我也找到了一点自己写规格的思路吧。
  REQUIRES和MODIFIES其实不用说太多,对每一个函数仔细评估一下就能知道它需要的条件和要改变的变量。对于EFFECTS,我们应首先从MODIFIES下手,对于需要修改的变量,追踪它的变化轨迹和可能的值,就能写出它的布尔表达式了,而变量的变化过程其实比较像有限状态机,从某一步到下一步都有相应的触发条件,而这个条件和变化结果就是我们要写的内容了。

猜你喜欢

转载自www.cnblogs.com/wishes/p/9096749.html