zoukankan      html  css  js  c++  java
  • OO游记之五月篇

    一、规格化设计

      让我们从程序设计的演变分析来看下规格设计

      1950年代,第一次分离,主程序和子程序的分离

      程序结构模型是树状模型,子程序可先于主程序编写。通过使用库函数来简化编程,实现最初的代码重用。产生基本的软件开发过程:分析—设计—编码—测试,使大型软件系统的开发成为可能

      1975—1980年代,第二次分离,规格说明和体的分离

      说明是类型定义和操作描述,体是操作的具体实现。(具体的例子就是C++,Java等面向对象语言的类说明与类实现的分离。)解决方案设计只关注说明,实现时引用或者设计体。体的更改、置换不影响规格说明,保证了可移植性。支持多机系统,但要同样环境。此时产生了划时代的面向对象技术。

      1995—2000年代,第三次分离,对象使用和对象实现的分离

      基于构件开发:标准化的软件构件如同硬件IC,可插拔,使用者只用外特性,不计内部实现。

      Web Services:软件就是服务。分布式,跨平台,松耦合。

      从个人的角度来看,规格化的设计是很有必要的,按照标准的JSF去写代码,可以保证代码的质量,提高代码的复用性。在团队工作中,代码不只是给自己看的,为了让自己代码的使用方法很快被别人了解,代码规格就十分重要了。

    二、规格BUG分析

    第九次作业

    第十次作业

    编号 规格BUG类别 所在方法 方法代码行数
    1 针对构造方法,初始状态repOK为真 Request.repOK() 12
    2 Modifies不完整 Taxi() 10
    3 Requires逻辑错误 RequestQueue.size() 1
    4 Requires逻辑错误 TaxiGroup.statusInquire() 1

    1.我写了两个不同参数的Requeset的构造器,其中一个构造器并未对PrintStream属性进行初始化,导致repOK检查时返回false

    2.Taxi构造器方法对出租车的所有属性进行了初始化设置,但我在Modifies中少写了几个属性

    3.(这个属于手残的错误)粘贴上个方法的Requires下来的时候忘了修改了

    4.此方法传入的参数的为出租车的编号,理应在0~99的范围内,否则可能发生数组越界错误,我忽视了这一点,没有在Requires中声明

    第十一次作业

    编号 规格BUG类别  所在方法  方法代码行数
    JSF不符合规范  TaxiGroup.run()  29
    JSF不符合规范   Scheduler.run() 100 
    JSF不符合规范   InputHandler.run() 75 
    Modifies不完整   Request.set_add() 73 
    Modifies不完整   LightMap.run() 20 
    Requires不完整  lightBlockJudge() 15 
    Requires不完整   RequestQueue.remove()
    Modifies不完整  Map.mapInit() 54 
    Modifies逻辑错误  Map.pointbfs() 42 

    1.我在run方法中进行了线程控制,synchronized了两个对象,而没有书写多线程控制规格

    2.依然是上个原因,进行synchronized控制而没有书写多线程控制规格

    3.依然是上个原因,进行synchronized控制而没有书写多线程控制规格

    4.在方法中对HashSet进行了修改,但没有在Modifies中声明

    5.在方法中对lightMap进行了修改,但没有在Modifies中声明

    6.本次作业中新添加了此方法,忘了写规格(很是尴尬)

    7.方法为从队列中移除下标为传入参数的元素,但在Requires中只写了index<queue.size,没有对负数进行限制,应为0<=index<queue.size,避免产生越界错误

    8.在方法中对distance进行了修改,但没有在Modifies中声明

    9.在方法中只是对局部变量view进行了修改,不应写在Modifies声明中

    规格BUG产生的原因

      首先,当然是自己的问题,对于大量的方法补充JSF,各种粗心大意导致被扣分,除了下标为负没有考虑到,其他的均是很低级的错误;其次,第一次写规格是在第九次作业,而这次作业是承袭第七次作业,因此大家都是后来对很多方法补充规格,这样就违反了本应有的顺序;最后,对于规格化的书写教学部分感觉不是很详细,后来下发的JSF样例包含的情况有限,导致大家对规格的理解不是那么深刻,写出很多不标准的规格。

    三、前置条件和后置条件改进

    前置条件

    1.未限制数据范围

    1    /**
    2      * @REQUIRES: None;
    3      * @MODIFIES: None;
    4      * @EFFECTS: 
    esult == (taxi_group[id].status_get());
    5      */
    6     public Status statusInquire(int id) {
    7         return taxi_group[id].status_get();
    8     }    

     改进方法

    1    /**
    2      * @REQUIRES: 0<=id<=99;
    3      * @MODIFIES: None;
    4      * @EFFECTS: 
    esult == (taxi_group[id].status_get());
    5      */
    6     public Status statusInquire(int id) {
    7         return taxi_group[id].status_get();
    8     }        

    2.构造方法未进行限制

    1   /**
    2      * @REQUIRES: None;
    3      * @MODIFIES: this.rq;
    4      * @EFFECTS: this.rq == rq;
    5      */
    6     public InputHandler(RequestQueue rq) {
    7         this.rq = rq;
    8     }

    改进方法

    1   /**
    2      * @REQUIRES: rq != null;
    3      * @MODIFIES: this.rq;
    4      * @EFFECTS: this.rq == rq;
    5      */
    6     public InputHandler(RequestQueue rq) {
    7         this.rq = rq;
    8     }

    3.未进行类型判断

     1     /**
     2      * @REQUIRES: r != null;
     3      * @MODIFIES: None;
     4      * @EFFECTS: (r.src in map && r.dst in map) ==> 
    esult true;
     5      *              !(r.src in map && r.dst in map) ==> 
    esult false;
     6      */
     7     public boolean formatCheck(Request r) {
     8         if(r.srcxGet()>=80 || r.srcyGet()>=80) return false;
     9         if(r.dstxGet()>=80 || r.dstyGet()>=80) return false;
    10         if(r.dstGet()==r.srcGet()) return false;
    11         return true;
    12     }

    改进方法

     1     /**
     2      * @REQUIRES: r != null && r instanceof Request;
     3      * @MODIFIES: None;
     4      * @EFFECTS: (r.src in map && r.dst in map) ==> 
    esult true;
     5      *              !(r.src in map && r.dst in map) ==> 
    esult false;
     6      */
     7     public boolean formatCheck(Request r) {
     8         if(r.srcxGet()>=80 || r.srcyGet()>=80) return false;
     9         if(r.dstxGet()>=80 || r.dstyGet()>=80) return false;
    10         if(r.dstGet()==r.srcGet()) return false;
    11         return true;
    12     }

    4.类型描述不完整

     1     /**
     2      * @REQUIRES: rq != null && rq instance of RequestQueue && taxi_group != null && taxi_group instanceof Taxi[];
     3      * @MODIFIES: rq,this.tg;
     4      * @EFFECTS: this.rq == rq;
     5      *           this.tg == taxi_group;
     6      */
     7     public Scheduler(RequestQueue rq, Taxi[] taxi_group) {
     8         this.rq = rq;
     9         this.tg = taxi_group;
    10     }

    改进方法

     1     /**
     2      * @REQUIRES: rq != null && rq instance of RequestQueue && taxi_group != null && all int i; 0<=i<=taxi_group.length; taxi_group[i] instanceof Taxi;
     3      * @MODIFIES: rq,this.tg;
     4      * @EFFECTS: this.rq == rq;
     5      *           this.tg == taxi_group;
     6      */
     7     public Scheduler(RequestQueue rq, Taxi[] taxi_group) {
     8         this.rq = rq;
     9         this.tg = taxi_group;
    10     }

    5.未进行范围限制

     1     /**
     2      * @REQUIRES: None;
     3      * @MODIFIES: None;
     4      * @EFFECTS: 
    esult == (flowmap.get(Key(x1,y1,x2,y2))==null ? 0 :flowmap.get(Key(x1,y1,x2,y2)));
     5      * @THREAD_REQUIRES: locked(this);
     6      * @THREAD_EFFECTS: locked();
     7      */
     8     public static int GetFlow(int x1,int y1,int x2,int y2){
     9         synchronized (flowmap) {
    10             return flowmap.get(Key(x1,y1,x2,y2))==null ? 0 :flowmap.get(Key(x1,y1,x2,y2));
    11         }
    12     }

    改进方法

     1     /**
     2      * @REQUIRES: 0<=x1<=79 && 0<=y1<=79 && 0<=x2<=79 && 0<=y2<=79;
     3      * @MODIFIES: None;
     4      * @EFFECTS: 
    esult == (flowmap.get(Key(x1,y1,x2,y2))==null ? 0 :flowmap.get(Key(x1,y1,x2,y2)));
     5      * @THREAD_REQUIRES: locked(this);
     6      * @THREAD_EFFECTS: locked();
     7      */
     8     public static int GetFlow(int x1,int y1,int x2,int y2){//查询流量信息
     9         synchronized (flowmap) {
    10             return flowmap.get(Key(x1,y1,x2,y2))==null ? 0 :flowmap.get(Key(x1,y1,x2,y2));
    11         }
    12     }

    后置条件

    1.尽量避免使用自然语言

    1   /**
    2      * @REQUIRES: None;
    3      * @MODIFIES: gap, lightTime;
    4      * @EFFECTS: true ==> (Initialize the LightMap's information);
    5      */
    6     public LightMap() {
    7         gap = 500 + new Random().nextInt(501);
    8         lightTime = gap;
    9     }

    改进方法

     1   /**
     2      * @REQUIRES: None;
     3      * @MODIFIES: gap, lightTime;
     4      * @EFFECTS: gap = 500 + new Random().nextInt(501);
     5                 lightTime = gap;
     6      */
     7     public LightMap() {
     8         gap = 500 + new Random().nextInt(501);
     9         lightTime = gap;
    10     }

    2.缺少多线程规格

    1     /**
    2      * @EFFECTS: 
    esult == queue.size;
    3      */
    4     public synchronized int size() {
    5         return this.queue.size();
    6     }

    改进方法

    1     /**
    2      * @EFFECTS: 
    esult == queue.size;
    3      * @THREAD_REQUIRES: locked(this);
    4      * @THREAD_EFFECTS: locked();
    5      */
    6     public synchronized int size() {
    7         return this.queue.size();
    8     }

    3.不符合布尔表达式规范

     1     /**
     2      * @REQUIRES: None;
     3      * @MODIFIES: rq,this.tg;
     4      * @EFFECTS: this.rq = rq;
     5      *           this.tg = taxi_group;
     6      */
     7     public Scheduler(RequestQueue rq, Taxi[] taxi_group) {
     8         this.rq = rq;
     9         this.tg = taxi_group;
    10     }

    改进方法

     1     /**
     2      * @REQUIRES: None;
     3      * @MODIFIES: rq,this.tg;
     4      * @EFFECTS: this.rq == rq;
     5      *           this.tg == taxi_group;
     6      */
     7     public Scheduler(RequestQueue rq, Taxi[] taxi_group) {
     8         this.rq = rq;
     9         this.tg = taxi_group;
    10     }

    4.尽量避免使用自然语言

     1     /**
     2      * @REQUIRES: None;
     3      * @MODIFIES: this.id,this.pos,this.posx,this.posy,this.pre,this.status,this.waittime,this.taxiTime,this.blockFlag;
     4      * @EFFECTS: true ==> (Initialize taxi);
     5      */
     6     public Taxi(int id) {
     7         this.id = id;
     8         Random rand = new Random();
     9         this.pos = rand.nextInt(6400);
    10         pre = pos;
    11         xy_set();
    12         this.status = Status.WAITING;
    13         this.waittime = 0;
    14         taxiTime = 500;
    15         blockFlag = false;
    16         Main.taxigui.SetTaxiStatus(id, new Point(posx,posy), 2);
    17     }

    改进方法

     1 /**
     2      * @REQUIRES: None;
     3      * @MODIFIES: this.id,this.pos,this.posx,this.posy,this.pre,this.status,this.waittime,this.taxiTime,this.blockFlag;
     4      * @EFFECTS: this.id == id;
     5         rand == new Random();
     6         this.pos == rand.nextInt(6400);
     7         pre == pos;
     8         this.status == Status.WAITING;
     9         this.waittime == 0;
    10         taxiTime == 500;
    11         blockFlag == false;
    12      */
    13     public Taxi(int id) {
    14         this.id = id;
    15         Random rand = new Random();
    16         this.pos = rand.nextInt(6400);
    17         pre = pos;
    18         xy_set();
    19         this.status = Status.WAITING;
    20         this.waittime = 0;
    21         taxiTime = 500;
    22         blockFlag = false;
    23         Main.taxigui.SetTaxiStatus(id, new Point(posx,posy), 2);
    24     }

    5.忽略函数中调用了其他函数

    1     /**
    2      * @REQUIRES: map.contains(pos);
    3      * @MODIFIES: this.posx,this.posy;
    4      * @EFFECTS: this.pos == pos;
    5      */
    6     public void pos_set(int pos) {
    7         this.pos = pos;
    8         xy_set();
    9     }

    改进方法

     1     /**
     2      * @REQUIRES: map.contains(pos);
     3      * @MODIFIES: this.posx,this.posy;
     4      * @EFFECTS: this.pos == pos;
     5      *              posy == pos%80;
     6      *              posx == (pos-posy)/80;
     7      */
     8     public void pos_set(int pos) {
     9         this.pos = pos;
    10         xy_set();
    11     }

    四、聚集关系分析

      方法名  错误原因 功能BUG数  规格BUG数
    作业9 Taxi.work() 忘了使用addFlow()增加流量 1 0
    作业10 Taxi.work() 在STOP状态对流量处理不当 1 0
    TaxiGroup.run() 上一个问题的连带问题 1 0
    作业11 LightMap.lightMapInit() 没有过滤空格和制表符 1 0

      通过结果来看似乎功能bug和规格bug并没有什么关系,因为其实是先完成了作业的功能要求才添加的规格,而规格的bug是由于在写规格过程中对函数没有细致分析造成的。所以本质上来说还是由于对规格的理解不当造成的.

    五、设计规格和撰写规格的基本思路和体会

      很惭愧,我的代码规格都是写好函数之后才补上去的,所以谈不上设计,只能写一点撰写的方法了。

      对于Requires部分,要对函数传入的参数,函数中用到的一些全局变量进行严格约束,从类型到范围都要考虑全面。Modifies部分要对函数中修改的变量列出来,不重不漏。Effects部分就比较麻烦了,要使用布尔表达式对result的情况进行撰写,需要对函数的作用进行良好的抽象化表达,尽量避免使用自然语言,才能写出一份良好的规格。

    六、碎碎念

      这三次作业其实写的并不是很累,基本都是到周二才开始动手写,从结果来看,功能上的bug有自己实现方法有问题的,也有手残的,然而JSF被扣的分基本上都是因为手残,得承认自己有不足,但是这门课面向运气的测试依然让人很不爽。得承认JSF对于工程化有重要作用,不过在这么课中,JSF用来被扣分还是有待商榷的~

  • 相关阅读:
    【深度学习系列1】 深度学习在腾讯的平台化和应用实践
    js复制button在ie下的解决方式
    兔子--Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK
    UART串口协议基础1
    高校站点群建设方案简单介绍
    oracle10G之前介质下载地址【珍藏版】
    程序猿打新总结 6月份 新股申购秘籍
    斯坦福IOS开发第五课(第一部分)
    O2O领域添新军,正品网加快布局的战略考量
    如风一样,飞翔------Day37
  • 原文地址:https://www.cnblogs.com/blackpineapple/p/9108149.html
Copyright © 2011-2022 走看看