zoukankan      html  css  js  c++  java
  • OO作业总结(三)

    类规格设计

     由于没能找到关于类规格设计的发展历史,所以结合程序设计思想的发展来谈谈规格化设计。

    最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数 据。简单来说,就是直接编写 0 和 1 的序列来代表程序语言。机器语言由机器直接执行,速度快,但一个很明显的缺点就是:写起来实在是太困难了;于是有了面向过程变成,相比面向机器的思想来说,面向过程是一次思想上的飞跃,将程序员从复杂的机器操作和运行的细节中解放出来,转而关注具体需要解决的问题;面向过程的语言也不再需要和具体的机器绑定,从而具备了移植 性和通用性;面向过程的语言本身也更加容易编写和维护。这些因素叠加起来,大大减轻了程序员的负担, 提升了程序员的工作效率,从而促进了软件行业的快速发展。

    但在这种设计模式下,不可避免的会产生面条式的代码,极大地限制了程序的规模——结构化设计应运而生:它是一种编程范型,采用子程序(函数就是一种子程序)、代码区块、for循环以及while循环等结构,来替换传统的goto。希望借此来改善计算机程序的明晰性、质量以及开发时间,并且避免写出面条式代码,这就是规格化设计的起源,并且一直发展至今。

    在实际的生活中,开发都是以团队为单位的,团队之间的交流主要是通过代码,所以代码要具有可读性;同时,实际的生活中代码的维护也是相当重要的,而维护代码的那些人却并不一定是代码的作者,这就更要求代码要具有很好的可维护性;另外,在我们开发程序的过程中,规格的设计更有助于避免浪费更多的时间来debug,如果一开始设计好了规格,然后严格按照这个规格来完成代码,可以很好的避免功能性bug。因此,由于以上列举出来的部分优点,这些看似优点浪费时间的类规格一直在人们心中占据重要的位置。

    bug分析

    本次课程如果烧脑的地方除了互测估计就是这个jsf的书写了,并不是说难度很大,而是要写得真正的规范感觉太难,而且很耗时间,写了这么多规格并没有很大的收获。所以这几次的规格都是写完了方法然后后面来添加的,并没有达到规格应有的左右,比如实验课上先写规格然后再写方法代码。这几次作业测我程序的同学都很nice,并没有扣我规格的bug。

    关于功能性的bug,由于这几次作业是在第七次作业的基础上进行修改,所以只要实现了指导书的要求,应该能很好的避免功能性bug。第十一次作业被同学报了一个功能bug,是关于走回头路的。我自己本地跑了一下他的测试代码(所有的车初始化在一个点,而且该点周围只有一条边),现象是根本看不出现象,可能是因为电脑太卡了吧也可能是程序本身就有问题,不过我依然觉得这种测试样例可能大部分代码跑出来效果都一样,所以自己也没去管这个bug了。 

    不好的写法和改进

    (1)以下是我出租车类中设置状态的方法:

    /**@REQUIRE: None;
     * @MODIFIES: status;
     * @EFFECTS:
     * (s == 3) ==> status == Status.STILL;
     * (s == 0) ==> status == Status.SERVE;
     * (s == 2) ==> status == Status.WAIT;
     * (s == 1) ==> status == Status.GOTORDER;
     * @ THREAD_EFFECTS:locked();
     */
    

      

    以上的规格感觉应该是合理的,就是觉得有点丑,所以稍微改了一下(可能还是很丑):

        /**@REQUIRE: None;
         * @MODIFIES: status;
         * @EFFECTS:
          (s == 3) ==> status == Status.STILL   ||
          (s == 0) ==> status == Status.SERVE   ||
          (s == 2) ==> status == Status.WAIT    ||
          (s == 1) ==> status == Status.GOTORDER;
         * @ THREAD_EFFECTS:locked();
         */  

    (2)以下是我出租车类中的设置目标点的规格:

        /**
         * @ MODIFIES: to;
         * @ EFFECTS:
         * this.to == to;
         * @ THREAD_EFFECTS:locked();
         */  

    而这个方法的实现是这样的:

        public synchronized void setTo(Point p) {
    
            to.setLocation(p.x, p.y);
        }

    很明显这个规格的REQUIRE是要写的,所以改进如下:

       /**@ REQUIRES: p != null;
         * @ MODIFIES: to;
         * @ EFFECTS:
         * this.to == to;
         * @ THREAD_EFFECTS:locked();
         */

    (3)以下是我周期为7.5s的监控线程的构造方法 ,同理其REQUIRE也有问题:

       /**
         @ MODIFIES:    TIME; taxi; from; to; num;
         @ EFFECTS:
         this.TIME == TIME; this.taxi == taxi;
         this.num == num; this.from == from;
         this.to == to;
         */
    

     改进:

       /**@REQUIRE: taxi != null; from != null; to != null; TIME >= 0;
         @ MODIFIES:    TIME; taxi; from; to; num;
         @ EFFECTS:
         this.TIME == TIME; this.taxi == taxi;
         this.num == num; this.from == from;
         this.to == to;
         */  

    (4)接下来是我调度类中的一个获取出租车信息的方法的规格:

        /**@ REQUIRES: str != {};
         @ MODIFIES:    None;
         @ EFFECTS:
            (exist int i; 0 <= i < str.length; str.charAt(i) >= '0' && str.charAt(i) <= '9')
            && (all int j; 0 <= j < i; str.charAt(j) < '0' || str.charAt(j) > '9')
            && (exist int k; i <= k < str.length; str.charAt(k) >= '0' && str.charAt(k) <= '9')
            && (k+1 >= str.length || str.charAt(k+1) < '0' || str.charAt(k+1) > '9')
            && (all int l; i <= l <= k; str.charAt(l) >= '0' && str.charAt(l) <= '9')
            ==> (
    esult == new Point(Integer.parseInt(str.substring(i, k+1), k+1)));
         */
    

      乍一看感觉很合理,但是仔细看却发现有错误:比如第一个逻辑表达式中定义的i的作用域只有第一行代码,并不能被后面的代码所识别,改进如下:

        /**@ REQUIRES: str != {};
         @ MODIFIES:    None;
         @ EFFECTS:
            (exist int i; 0 <= i < str.length; (str.charAt(i) >= '0' && str.charAt(i) <= '9'
            && (all int j; 0 <= j < i; str.charAt(j) < '0' || str.charAt(j) > '9')
            && (exist int k; i <= k < str.length; str.charAt(k) >= '0' && str.charAt(k) <= '9')
            && (k+1 >= str.length || str.charAt(k+1) < '0' || str.charAt(k+1) > '9')
            && (all int l; i <= l <= k; str.charAt(l) >= '0' && str.charAt(l) <= '9'))
            ==> (
    esult == new Point(Integer.parseInt(str.substring(i, k+1), k+1)));
         */

      改进之后就可以改变上面的不足。

    (5)接下来是我十一次作业的特殊出租车的构造方法:

        /**@REQUIRES:
         *  No >= 0 && No < 100; mi != null; taxigui != null;
         * @MODIFIES:
         *  No; mi; taxigui;
         * @EFFECTS:
         *  this.mi == mi; this.taxigui == taxigui; this.No == No;
         */
    

      这个规格和第四个规格类似,都感觉是合理的,却有一点点小问题,传进来的taxigui不能保证是合法的,所以REQUIRE得重写,改进如下:

        /**@REQUIRES:
         *  No >= 0 && No < 100 && mi != null && taxigui != null && taxigui.repOk();
         * @MODIFIES:
         *  No; mi; taxigui;
         * @EFFECTS:
         *  this.mi == mi; this.taxigui == taxigui; this.No == No;
         */

    基本思路和体会

    这几次作业的规格都是在完成代码之后添加的,所以不一定合乎要求,不过在实验课上尝试了先写规格再写代码,觉得这样的模式也还行,不过这就对设计的要求高了一些,如果一开始设计有误,会浪费更多时间。

    最后一次oo的代码作业,好像并没有什么特别的感觉,以后终于有更多时间做其他事情了,开心。

  • 相关阅读:
    Java 中字符串的格式化
    Awk学习笔记
    Spring任务调度实战之Quartz Simple Trigger
    Subclipse vs. Subversive
    使用OpenSSL生成自用证书
    httpclient处理页面跳转
    巧用TableDiff(转)
    DBCC了解页面结构
    取最新一条SQL优化
    SQL 2008 到 SQL2012的镜像
  • 原文地址:https://www.cnblogs.com/ignautics/p/9098186.html
Copyright © 2011-2022 走看看