OO第三次博客作业
OO第三次博客作业
规格化设计发展历史
二十世纪60年代以前,程序设计使用的主要是机器语言、汇编语言等,由于它们是针对特定型号计算机的语言,在不同计算机之间的可移植性差,而且不同计算机一般具有不同的指令系统,使得这类语言可读性极差。
二十世纪60年代中后期,软件的数量增多,规模增大,由于缺乏科学规范的系统规划与测试、评估标准,导致大批成本高昂的软件系统由于含有错误无法使用,甚至带来巨大损失。此时人们意识到程序的设计应易于保证正确性,也便于验证正确性,面向过程的程序设计方法开始出现。
80年代初开始,面向对象的程序设计开始出现。将任务抽象为对象以及对象的行为,面向具体的应用功能。对于每个封装的功能模块,只关心它的接口及能实现的功能,即方法的规格抽象。
进行规格抽象,有助于更直观的了解程序功能模块的输入限制、可以实现的功能等等。规格抽象中不关心具体的算法,降低了程序的阅读难度,提高了程序的易读性。从方法规格对模块进行检查,便于保证和验证程序的正确性。
规格bug
有幸没有被报规格bug,感谢测试的各位同学手下留情
自己在写程序的时候也是先写好了代码,再补全了规格,所以导致某些规格与代码不对应的情况存在。很多EFFECTS由于不能很好地抽象成规格,很多使用了自然语言代替,即使是抽象出来的,也写得不够全面、不规范。
前置和后置条件写法分析
前置:
- 闲逛状态选路方法
public Point getRandomWay(ArrayList<Point> p) {
/**
* @REQUIRES: None;
* @MODIFIES: None;
* @EFFECTS: return a random way that is available and has the lowest flow;
*/
原以为在使用方法的时候限制了p!=null,就不需要在规格中说明了,改:
public Point getRandomWay(ArrayList<Point> p) {
/**
* @REQUIRES: p!=null;
* @MODIFIES: None;
* @EFFECTS: (\exist int i;0<=i<p.size();the road between p.get(i) and the recent location of taxi has the lowest flow)==>\result == p.get(i);
*/
- 获取最小流量方法
public int getLowest(ArrayList<Integer> a) {
/**
* @REQUIRES: !a.isEmpty();
* @MODIFIES: None;
* @EFFECTS: /result == (\min a);
*/
前置条件不完善,缺少a!=null的限制,改:
public int getLowest(ArrayList<Integer> a) {
/**
* @REQUIRES: a!=null && !a.isEmpty();
* @MODIFIES: None;
* @EFFECTS: /result == (\min a);
*/
- 消除请求红框方法
public void endRequest() {
/**
* @REQUIRES: !guigv.srclist.isEmpty();
* @MODIFIES: guigv.srclist;
* EFFECTS: remove the red square of the finisied request;
*/
同上,改:
public void endRequest() {
/**
* @REQUIRES: guigv.srclist != null && !guigv.srclist.isEmpty();
* @MODIFIES: guigv.srclist;
* EFFECTS: remove the red square of the finisied request;
*/
- 服务状态运行方法
public void movebfs(Point src, Point dst) {
/**
* @REQUIRES: !src.equals(dst) && this.status != 2 && this.status!=3;
* @MODIFIES: this,guigv.flowmap;
* EFFECTS: move the taxi througe the route that was given by the bfs;
*/
缺少对于src和dst范围的限制,改:
public void movebfs(Point src, Point dst) {
/**
* @REQUIRES: 0<=src.x<80 && 0<=src.y<80 && !src.equals(dst) && this.status != 2 && this.status!=3;
* @MODIFIES: this,guigv.flowmap;
* EFFECTS: move the taxi througe the route that was given by the bfs;
*/
- 判断两个方向是否是反向的方法
public boolean isOpposite(Direction d1, Direction d2) {
/**
* @REQUIRES: None;
* @MODIFIES: None;
* @EFFECTS: if the two directions are opposite, return true;else return false;
*/
同1,没有限制在程序过程中限制的条件,改:
public boolean isOpposite(Direction d1, Direction d2) {
/**
* @REQUIRES: d1!=null && d2!=null;
* @MODIFIES: None;
* @EFFECTS: if the two directions are opposite, return true;else return false;
*/
后置:
- 闲逛状态选路方法
public Point getRandomWay(ArrayList<Point> p) {
/**
* @REQUIRES: None;
* @MODIFIES: None;
* @EFFECTS: return a random way that is available and has the lowest flow;
*/
原EFFECTS为纯自然语言,改:
public Point getRandomWay(ArrayList<Point> p) {
/**
* @REQUIRES: p!=null;
* @MODIFIES: None;
* @EFFECTS: (\exist int i;0<=i<p.size();the road between p.get(i) and the recent location of taxi has the lowest flow)==>\result == p.get(i);
*/
- 判断两个方向是否为反向的方法
public boolean isOpposite(Direction d1, Direction d2) {
/**
* @REQUIRES: None;
* @MODIFIES: None;
* @EFFECTS: if the two directions are opposite, return true;else return false;
*/
同上,EFFECTS完全使用自然语言,改:
public boolean isOpposite(Direction d1, Direction d2) {
/**
* @REQUIRES: None;
* @MODIFIES: None;
* @EFFECTS: (the two directions are opposite)==>\result == true;
* (the two directions are not opposite)==>\result == false;
*/
- 根据状态查找出租车的方法
public ArrayList<Integer> findTaxi(int status){
/**
* @REQUIRES: 0 <= status <= 3;
* @MODIFIES: None;
* @EFFECTS: return a list that contains all taxis of which the taxistatus is status;
*/
同上,改:
public ArrayList<Integer> findTaxi(int status){
/**
* @REQUIRES: 0 <= status <= 3;
* @MODIFIES: None;
* @EFFECTS: (\exist ArrayList<Integer> a;a!=null;(\all guitaxi gt;guigv.taxilist.contains(gt);(gt.status == status)==>a.contains(gt)))==>\result == a;
*/
- 获取出租车周围未关闭道路的方法
public ArrayList<Point> getAcessWay(){
/**
* @REQUIRES: None;
* @MODIFIES: None;
* @EFFECTS: return a list fo acessible ways around the taxi;
*/
同上,改:
public ArrayList<Point> getAcessWay(){
/**
* @REQUIRES: None;
* @MODIFIES: None;
* @EFFECTS: (\exist ArrayList<Point> a;a!=null;(\all Point p;a.contains(p);guigv.m.graph[this.x*80+this.y][p.x*80+p.y]==1))==>\result==a;
*/
- 移动出租车的方法
public void move(Point p) {
/**
* @REQUIRES: p!=null;
* @MODIFIES: this;
* @EFFECTS: set the properties of taxi;
*/
同上,改:
public void move(Point p) {
/**
* @REQUIRES: p!=null;
* @MODIFIES: this;
* @EFFECTS: this.x==p.x && this.y==p.y ;
* (guigv.m.graph[this.x*80+this.y][p.x*80+p.y]==1)==>(guigv.flowmap[this.x*80+this.y][p.x*80+p.y]==\old(guigv).flowmap[this.x*80+this.y][p.x*80+p.y] + 1);
*/
功能bug和规格bug在方法上的聚集关系
由于作业中都是先写了代码,然后再补JSF,所以功能bug和规格bug之间没有必然的联系。
如果是按照规格写代码,则规格bug很有可能导致程序功能错误,出现功能bug的同时也很有可能规格中具有相关的bug
思路和体会
写作业的时候也没什么设计规格的思路,就是把代码逻辑翻译成了规格,现在想想倒是可以先把自己要写的方法的功能明确,根据功能和对输入的要求,设计规格。
这几次作业也没有按照正确的顺序来先写规格再写代码,只觉得这个东西有些麻烦,还没有体会到其中的好处吧。