面向对象第三次博客总结

一、规格的历史和重要性

  早期的软件开发也没有什么系统的方法可以遵循,软件设计是在某个人的头脑中完成的一个隐藏的过程。而且,除了源代码往往没有软件说明书等文档。

  从60年代后,软件开始作为一种产品被广泛使用。这一软件开发的方法基本上仍然沿用早期的个体化软件开发方式,但软件的数量急剧膨胀,软件需求日趋复杂,维护的难度越来越大,开发成本令人吃惊地高,而失败的软件开发项目却屡见不鲜。“软件危机”就这样开始了!人们改变了早期对软件的不正确看法。早期那些被认为是优秀的程序常常很难被别人看懂,通篇充满了程序技巧。现在人们普遍认为优秀的程序除了功能正确,性能优良之外,还应该容易看懂、容易使用、容易修改和扩充。

  为了类和方法能够变得规范可控,对类和方法进行规范化要求就变得有必要起来。在工程里面, 一个程序也许会有多人同时进行编写,那么由于每个人不同的代码习惯,可能产生不同的设计理念,通过规格化设计也可以同步多人的设计方法,避免产生设计上的漏洞。规格化的程序不仅更易于调试,也更容易被维护,有利于程序的长远生存和发展。这些都是规格化设计的优势所在。

二、规格bug

  

作业次数 规格BUG类型 出现方法行数 出现原因
第九次    
第十次 Main.java没写rep
 

 

OK()函数
1 所有的类,只要有变量,且可能发生变化就要有repOK,但我却忽略main
  Requires不完整 1 对Requires不甚理解
  Main.java没写Overview 1 main总是一个容易让人遗忘的特殊类
  Effects不完整 7 这七处错误在于7个写入txt文件的函数,因为不产生effect,下意识地忽视了,因该填上NONE
  不变式的判断缺少与repOK()疏漏 1 有些属性缺失很难通过不变式确立
第十一次    

三、规格改进

  1.Main的repOK()函数补充

public boolean repOK() {
    /**
    * @Effects: \result==invariant(this)
    */
    int i ,j;
    for(i=0;i<80;i++) {
        for(j=0;j<80;j++) {
            if(map[i][j]<0||map[i][j]>3)    return false;
            if(flow[i][j][0]<0)    return false;
            if(flow[i][j][1]<0)    return false;
            if(flow[i][j][2]<0)    return false;
            if(flow[i][j][0]<0)    return false;
        }
    }
        if(gui == none)    return false;
        if(clk == none)    return false; 
        
    return true;
}

 

   2.Requires补充

    //改前
    public int waittime() {
        /** 
        * @MODIFIES: NONE;
        * @EFFECTS:
        * \result == (700 - (System.currentTimeMillis() - time))
        */
        long t1;
        t1 = System.currentTimeMillis();
        //if(t1%100 >=50)    t2 = t1 - t1%100 + 100;
        //else    t2 = t1 - t1%100;
        return  700 - (int)(t1 - time)%700;    
    }
    //改后
    public int waittime() {
        /** 
         * @Requires: this.time > 0
        * @MODIFIES: NONE;
        * @EFFECTS:
        * \result == (700 - (System.currentTimeMillis() - time))
        */
        long t1;
        t1 = System.currentTimeMillis();
        //if(t1%100 >=50)    t2 = t1 - t1%100 + 100;
        //else    t2 = t1 - t1%100;
        return  700 - (int)(t1 - time)%700;    
    }

   3.Main补充Overview

/**
     * @Overview:  Main is the main function.
     **/

   4.Effects补充

    //改前
    /**
    * @MODIFIES:this.file;
    * @EFFECTS:
    */
    //改后
    /**
    * @MODIFIES:this.file;
    * @EFFECTS:write details in txt
    */
    //
    /**
    * @MODIFIES:this.file;
    * @EFFECTS:NONE
    */    

   5.不变式与repOK()的补充

/**
    * @表示对象:Request []request,Object clock,Texi[]texi,Route road,int num,int head
    * @抽象函数:AF(c) = (request_list,clock,texi_list,road,last_request_position)where
    *c.request == request_list,c.clock == clock,c.texi==texi_list,c.road==road,c.num==last_request_position,c.head == 0
    * @invariant:(\all int i;0<=i<=num;request[i]!=null&&request[i].repOK())&&(clock!=null)&&(\all int i;0<=i<=99;texi[i]!=null&&texi[i].repOK())&&
    * (road!=null&&road.repOK())
    **/
    public boolean repOK() {
        /**
        * @Effects: \result==invariant(this)
        */
        int i;
        if(clock==null)    return false;
        for(i=0;i<nums;i++) {
            if(request[i]==null||!request[i].repOK())    return false;
        }
        for(i=0;i<100;i++) {
            if(texi[i]==null||!texi[i].repOK())    return false;
        }
        if(road==null||!road.repOK())    return false;
        return true;
    }

//改后

    /**
    * @表示对象:Request []request,Object clock,Texi[]texi,Route road,int num,int head
    * @抽象函数:AF(c) = (request_list,clock,texi_list,road,last_request_position)where
    *c.request == request_list,c.clock == clock,c.texi==texi_list,c.road==road,c.num==last_request_position,c.head == 0
    * @invariant:(\all int i;0<=i<=num;request[i]!=null&&request[i].repOK())&&(clock!=null)&&(\all int i;0<=i<=99;texi[i]!=null&&texi[i].repOK())&&
    * (road!=null&&road.repOK())&&(taxigui !=null)
    **/
    public boolean repOK() {
        /**
        * @Effects: \result==invariant(this)
        */
        int i;
        if(clock==null)    return false;
        for(i=0;i<nums;i++) {
            if(request[i]==null||!request[i].repOK())    return false;
        }
        for(i=0;i<100;i++) {
            if(texi[i]==null||!texi[i].repOK())    return false;
        }
        if(road==null||!road.repOK())    return false;
        if(taxigui == null)    return false;
        return true;
    }
    //构造操作

四、列举不好的写法并改进

1.往txt写入时要确保出租车对象有意义

    public void write() {
        /** @MODIFIES:this.file;
        * @EFFECTS:
        */
}

//修改后

public void write() {
        /** @Requires:this.reoOK() == true
         * @MODIFIES:this.file;
        * @EFFECTS:
        */
}

2.确保传入参数有坐标与方向意义

public boolean can_go(int x,int y,int dir) {
        /** @MODIFIES: NONE;
        * @EFFECTS: 
}

//修改

public boolean can_go(int x,int y,int dir) {
        /** @Requires:(0<=x<=79)&&(0<=y<=79)&&(0<=dir<=3);
         * @MODIFIES: NONE;
        * @EFFECTS: 
}

3.确保time是有意义的

public int waittime() {
        /** 
        * @MODIFIES: NONE;
        * @EFFECTS:
        * \result == (700 - (System.currentTimeMillis() - time))
        */
}

//修改后

public int waittime() {
        /** 
         * @Requires: this.time > 0
        * @MODIFIES: NONE;
        * @EFFECTS:
        * \result == (700 - (System.currentTimeMillis() - time))
        */
}

 4.确保有计算距离的地图

public int getdis(Point a, Point b) {
    /**@MODIFIES:NONE;
    * @EFFECTS:
    * /result == dist from a to b;
    */
}

//改后

public int getdis(Point a, Point b) {
    /**Requires:repOK()==ture;
        * @MODIFIES:NONE;
    * @EFFECTS:
    * /result == dist from a to b;
    */    
}

5.REQUIRES的判断式分开更能看清逻辑

public void getroute(int x1,int y1,int x2,int y2,int [][]route) {
        /**
        * @REQUIRES: (0<=x1<=79 && 0<=y1<=79 && 0<=x2<=79 && 0<=y2<=79);
        * @MODIFIES:route;
        * @EFFECTS:
        * route == routine form x1 y1 to x2 y2;
        */
}

//改后

public void getroute(int x1,int y1,int x2,int y2,int [][]route) {
        /**
        * @REQUIRES: (0<=x1<=79 )&& (0<=y1<=79) && (0<=x2<=79) && (0<=y2<=79);
        * @MODIFIES:route;
        * @EFFECTS:
        * route == routine form x1 y1 to x2 y2;
        */

 

后置条件:

6.避免自然语言描写

    public void run() {
        /**
        * @MODIFIES:this;
        * @EFFECTS:
        * run a circle
        */
}

//改后

    public void run() {
        /**
        * @MODIFIES:this;
        * @EFFECTS:
        * \old(this.past_time) < 7500 ==> this.past_time == \old(this.past_time) + 500 ;
        * @THREAD_EFFECTS: \locked(clock);
        */
}

7.自增需要用到\old()

    public void run() {
        /**
        * @MODIFIES: road.count,x,y,ox,oy,status,wait,runtime;
        * @EFFECTS: 
        *run this cab a cycle;
        *runtime == \old(runtime) + 500;
        *road.count == road.count + 1;
        *(road.count == 100) ==> ((road.count == 0) && ((\all int i,i;0=<i,j<=80) ==>(flow[i][j][0]==\old(flow[i][j][2])&&flow[i][j][1]==\old(flow[i][j][3])&&flow[i][j][2]==0&&flow[i][j][3]==0)));
        * @THREAD_EFFECTS: \locked(clock);
        */
}

//改后

    public void run() {
        /**
        * @MODIFIES: road.count,x,y,ox,oy,status,wait,runtime;
        * @EFFECTS: 
        *run this cab a cycle;
        *runtime == \old(runtime) + 500;
        *road.count == \old(road.count) + 1;
        *(road.count == 100) ==> ((road.count == 0) && ((\all int i,i;0=<i,j<=80) ==>(flow[i][j][0]==\old(flow[i][j][2])&&flow[i][j][1]==\old(flow[i][j][3])&&flow[i][j][2]==0&&flow[i][j][3]==0)));
        * @THREAD_EFFECTS: \locked(clock);
        */

8.

    public void getbill(Request r) {
        /**
        * @MODIFIES: this;
        * @EFFECTS: 
        *this.carry_re == r;
        *this.ox ==r.set_x && this.oy == r.set_y;
        *this.status == 1 && this.runtime == 0 && this.wait == 0;
        *this.headpoint == new Point;
        */
}

//改后

        public void getbill(Request r) {
        /**
        * @MODIFIES: this;
        * @EFFECTS: 
        *this.carry_re == r;
        *this.ox ==r.set_x && this.oy == r.set_y;
        *this.status == 1 && this.runtime == 0 && this.wait == 0;
        *this.headpoint == next_head_point;
        */
}

9.

    public void run() {
        /** 
        * @MODIFIES: this.lights;
        * @EFFECTS:
        * (\all int i,j;0<=i,j<=79;\old(this.lights[i][j])!=0) ==> (\old(lights[i][j]) == 1 ==> lights[i][j] == 2) && (\old(lights[i][j]) == 2 ==> lights[i][j] == 1);
        */
}

//改后

    public void run() {
        /** 
        * @MODIFIES: this.lights;
        * @EFFECTS:
        * (\all int i,j;0<=i,j<=79;\old(this.lights)[i][j]!=0) ==> (\old(lights)[i][j]== 1 ==> lights[i][j] == 2) && (\old(lights)[i][j] == 2 ==> lights[i][j] == 1);
        */

10.

    public void run_1() {
        /** 
        * @MODIFIES: this;
        * @EFFECTS: 
        *(\old(this.wait) == 0) ==> ((this.x == this.ox && this.y == this.oy)==> (this.wait == 1 && this.runtime == 0));
        *(\old(this.wait) == 0) ==> (!(this.x == this.ox && this.y == this.oy)==>(this.x = next_x&& this.y = next_y));
        *(\old(this.wait) == 1) ==> (carry_re.past_time == \old(carry_re.past_time)+500 && (carry_re.past_time == 1000 ==> (wait == 2 && this.runtime == 0)));        
        *(\old(this.wait) == 2) ==> ((this.x == this.ox && this.y == this.oy)==> (this.wait == 0 && this.runtime == 0 && this.status == 0));
        *(\old(this.wait) == 2) ==> (!(this.x == this.ox && this.y == this.oy)==>(this.x = next_x&& this.y = next_y));
        */
}

//改后

    public void run_1() {
        /** 
        * @MODIFIES: this;
        * @EFFECTS: 
        *(\old(this.wait) == 0) ==> ((this.x == this.ox && this.y == this.oy)==> (this.wait == 1 && this.runtime == 0));
        *(\old(this.wait) == 0) ==> (!(this.x == this.ox && this.y == this.oy)==>(this.x = next_x&& this.y = next_y));
        *(\old(this.wait) == 1) ==> (carry_re.past_time == \old(carry_re.past_time)+500 && (carry_re.past_time == 1000 ==> (wait == 2 && this.runtime == 0)));        
        *(\old(this.wait) == 2) ==> ((this.x == this.ox && this.y == this.oy)==> (this.wait == 0 && this.runtime == 0 && this.status == 0));
        *(\old(this.wait) == 2) ==> (!(this.x == this.ox && this.y == this.oy)==>(this.x = next_x&& this.y = next_y));
               *this.detai update
        */
}            

 

 

 

五、功能BUG与规格BUG的内聚关系

作业 规格Bug数  功能Bug数  内聚关系 
 第九次  0  0 无 
第十次   5  4 无 
第十一次   0  3 无 

 

 六、感想体会

  这三次作业很多函数都是以前写好的,只能补充规格。而新的方法,我习惯先写方法体再写规格,因为在整个程序完成之前,我不确定一个函数是否还有需要再次进行修改的地方,先写规格明显不符合习惯,即使规格有着导向性作业,但并不具有细节处调节的能力。

 

posted @ 2018-05-30 09:41  shinyruo开始了  阅读(175)  评论(0编辑  收藏  举报