一、关于规格
关于规格的必要性,这一点我还是很同意吴老师在课上所讲的内容的。在比较大规模的代码设计中,尤其是多人协作的项目,良好的规格设计的确能减少很多不必要的麻烦。
二、我出现的规格bug
第九次:
REQUIRES不需要内容的时候没有写None而是空着了。
第十次:
无
第十一次:
EFFECTS内容不全。bug的位置是Taxi类的出租车移动的方法。
三、出现规格bug的原因
第一次写jsf的时候由于理解不够加上时间紧,部分方法的jsf写的有些匆忙。至于出租车的移动这类方法,由于能力有限,没能抽象出一个比较好的EFFECTS,考虑不全。
四、规格不好的写法
前置条件:
1.符号规范问题
/**@ REQUIRES: 0<=srcx<80,0<=srcy<80,0<=dstx<80,0<=dsty<80; @ MODIFIES: reqPath; @ EFFECTS: 计算路径存入reqPath; @ */
这里改为&&应该更好。
/**@ REQUIRES: 0<=srcx<80&&0<=srcy<80&&0<=dstx<80&&0<=dsty<80; @ MODIFIES: reqPath; @ EFFECTS: 计算路径存入reqPath; @ */
2.判断不为空
public synchronized void taxi(Taxi taxi){ /**@ REQUIRES: None; @ MODIFIES: f,w; @ EFFECTS:抢单的车辆信息; @ */ }
加入判断不等于空的条件。
public synchronized void taxi(Taxi taxi){ /**@ REQUIRES: taxi!=NULL; @ MODIFIES: f,w; @ EFFECTS:抢单的车辆信息; @ */ }
3.增加限制
private void go(int dstx,int dsty){ /**@ REQUIRES: 0<=dstx<80; 0<=dsty<80; @ MODIFIES: None @ EFFECTS: pre_x==old(x) && pre_y==old(y) && x==dstx && y==dsty; @ */ }
增加了对目标点和当前点为相邻点的限制。
private void go(int dstx,int dsty){ /**@ REQUIRES: 0<=dstx<80 && 0<=dsty<80 && ((dsx==this.x && (dsty==this.y+1||dsty==this.y-1))||(dsy==this.y && dstx==this.x+1||dstx==this.x-1))); @ MODIFIES: None @ EFFECTS: pre_x==old(x) && pre_y==old(y) && x==dstx && y==dsty; @ */ }
4.参数范围
public void setTime(long time){ /**@ REQUIRES: 0<=i<80; 0<=j<80; @ MODIFIES: lightTime; @ EFFECTS: lightTime[i][j]==time; @ */ }
增加对Time的限制。
public void setTime(long time){ /**@ REQUIRES: 0<=i<80&& 0<=j<80&&Time>=500&&Time<=1000; @ MODIFIES: lightTime; @ EFFECTS: lightTime[i][j]==time; @ */ }
5.自然语言问题
public boolean decode(String str) { /**@ REQUIRES: str符合请求格式规定; @ MODIFIES: srcx,srcy,dstx,dsty; @ EFFECTS:获取出发点和目的地; @ */ }
这里完全可以改为:
public boolean decode(String str) { /**@ REQUIRES: str.matches("\[CR,\([0-9]+,[0-9]+\),\([0-9]+,[0-9]+\)\]"); @ MODIFIES: srcx,srcy,dstx,dsty; @ EFFECTS:获取出发点和目的地; @ */ }
后置条件:
1.部分方法忽略了THREAD_EFFECTS
private void go(int dstx,int dsty){ /**@ REQUIRES: 0<=dstx<80; 0<=dsty<80; @ MODIFIES: None @ EFFECTS: pre_x==old(x) && pre_y==old(y) && x==dstx && y==dsty; @ */ }
加入THREAD_EFFECTS。
private void go(int dstx,int dsty){ /**@ REQUIRES: 0<=dstx<80; 0<=dsty<80; @ MODIFIES: None @ EFFECTS: pre_x==old(x) && pre_y==old(y) && x==dstx && y==dsty; @ THREAD_EFFECTS :locked (guigv.lightmap); @ */ }
2.自然语言问题
public synchronized void pop(int i){ /**@ REQUIRES: i<queue.size(); @ MODIFIES: queue; @ EFFECTS: 删除queue中下标为i的元素; @ */ }
完全可以改为:
public synchronized void pop(int i){ /**@ REQUIRES: i<queue.size(); @ MODIFIES: queue; @ EFFECTS: !queue.contains(old(queue).get(i)); @ */ }
3.小疏漏
public void setTime(long time){ /**@ REQUIRES: 0<=i<80; 0<=j<80; @ MODIFIES: lightTime; @ EFFECTS: lightTime[i][j]==time; @ */ }
lightTime的类型已由int[][]变为int,忘了更改。
public void setTime(long time){ /**@ REQUIRES: 0<=i<80; 0<=j<80; @ MODIFIES: lightTime; @ EFFECTS: lightTime==time; @ */ }
五、聚集关系
方法 | 功能bug数 | 规格bug数 |
readmap | 1 | 0 |
loadlight | 1 | 0 |
dstGo | 0 | 1 |
request | 0 | 1 |
randomGo | 2 | 0 |
go | 6 | 0 |
pickup | 0 | 1 |
相关性不算特别大,不过go()方法真的惨……主要还是由于一开始写崩了。(┬_┬)
六、心得体会
在这一单元的训练中,虽然自我感觉训练的不是特别好,但是还是基本领悟到了程序规格设计的一些思想要点,我想今后的代码应该是会更规范、更不容易出错的。对于我们的jsf,我明显的感受就是身边的同学们都发出了很多的抱怨,不过还是能体会到老师们设计课程的用心,同时在与助教的交流中,感受到助教们也对大家的态度十分包容。OO不仅是一门课,同时也是一种经历,一段独一无二的经历。或许其中有很多的不如意,但大家收获的不仅是结果,还有很多有意义的过程。
从这一部分的学习中,我逐渐感受到自己在一些方面还是有不少的缺陷,很多时候对于代码思路的抽象能力不够强,另外就是有的时候对一些关键点缺乏理解等等。发现了问题就要改正,希望今后能逐渐克服缺点,不断进步。