类规格设计

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

最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数 据。简单来说,就是直接编写 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')
==> (\result == 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'))
==> (\result == 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的代码作业,好像并没有什么特别的感觉,以后终于有更多时间做其他事情了,开心。

OO作业总结(三)的更多相关文章

  1. OO作业第三单元总结

    目录 一.JML语言理论基础及应用工具链 二.部署JMLUnitNG,自动生成测试用例 三.架构设计 第一次作业 第二次作业 第三次作业 四.Bug分析 五.心得体会 一.JML语言理论基础及应用工具 ...

  2. 北航oo作业第三单元小结

    一.梳理JML语言的理论基础 1.jml的注释结构 jml注释语言的每一行都以@作为开始,若是块注释,则需要在注释块的首尾使用/*@ 与@*/ 2.jml的表达式体系 1.原子表达式 表达式可以看作是 ...

  3. 【作业】HansBug的前三次OO作业分析与小结

    OO课程目前已经进行了三次的作业,容我在本文中做一点微小的工作. 第一次作业 第一次作业由于难度不大,所以笔者程序实际上写的也比较随意一些.(点击就送指导书~) 类图 程序的大致结构如下: 代码分析 ...

  4. 北航OO(2020)第三单元博客作业

    一.JML理论基础及相关工具链 1.JML理论基础 该部分梳理本单元作业中涉及到的JML知识. 1.1注释结构 JML采用javadoc注释的方式来表示规格,且每行以@开头.通过使用//@annota ...

  5. OO第三次博客作业--第三单元总结

    一.JML 语言的理论基础及应用工具链 JML 是一种行为接口规格语言,提供了对方法和类型的规格定义手段.通过 JML 和其支持工具,不仅可以基于规格自动构造测试用例,并整合了 SMT Solver ...

  6. 第十五次oo作业

    作业十五 测试与正确性论证的效果差异 程序的测试需要通过输入特定数据等方式,检查程序是否和预期相同,因为测试不可能穷举,导致了不穷举的测试不可能验证程序是完全正确的,只能验证程序在测试时没有发生错误, ...

  7. oo作业总结(四)

    测试与正确性论证 测试是通过构造一系列测试数据,通过对比程序的实际运行结果和预期输出结果来判断程序是否有bug的一种手段.同时,在测试的时候是默认看不到程序的具体实现的,即进行黑盒测试,例如每次OO作 ...

  8. oo作业总结(二)

    概述 和前三次作业相比,这几次作业最大的不同是难度的飞跃.遗憾的是在这难度的变化面前,我自己却没有做好充分的准备,错误的低估了作业难度导致给自己带来了很多不必要麻烦和损失.接下来我将对它们进行说明(度 ...

  9. oo作业总结(一)

    概述 经历了三次oo作业的洗礼,让我对java语言的强大以及面向对象编程有了初步的理解(当然,我是小白).本文接下来就将对自己这三次作业的代码进行分析以及分享自己的心路历程. 基础知识点考核 针对前三 ...

  10. oo作业总结报告

    oo第一次博客 以前从未真正的写过Java代码,接触Java也只是寒假的时候简单的看了看语法,不懂该如何面向对象,但没事,心里不惧,想着什么都是可以学的(直到真正开始写工程的时候,才发现自己还是太天真 ...

随机推荐

  1. Lua和C++交互 学习记录之二:栈操作

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...

  2. 微信小程序动态更改样式

    获取列表长度(动态渲染),当长度>x时添加内联样式并绑定数据{{}},通过js动态更改{{}}

  3. 用原生js来处理跨域的数据(jsonp)

    说明总结: 1.ajax和jsonp其实本质上是不同的东西.ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提 ...

  4. C# 遍历文件夹筛选目标文件

    有近400G的数据,首先需要写程序把目标文件标准化名称(相当耗时,各种情形,间接说明在数据采集过程中标准化操作的重要性,这样会给后续处理带来很多不必要的麻烦和消耗) 网上找了个方法还不错,还有一种递归 ...

  5. Getting Started with Processing 第五章的easing问题

    分析 使用 easing easing 的感官目的是为了 draw 的时候,画的图形不是即时 mouseX 的值,而是稍有落后一点.从算法分析,就是让所画图形的 x 坐标 落后于 mouseX 的值, ...

  6. English trip V1 - B 24. I'm Interested in... 我对...感兴趣 Teacher:Julia Key: (I/We/They) do/don't (He/She/it)does/doesn't

    In this lesson you will learn to talk about people's interests. 课上内容(Lesson) interest v. 使…感兴趣(inter ...

  7. php实现队列

    <?php //双向队列的实现 class DoubleEndedQueue{ public $elements; public function __construct(){//析构函数,创建 ...

  8. 『MXNet』第八弹_数据处理API_上

    一.Gluon数据加载 下面的两个dataset处理类一般会成对出现,两个都可做预处理,但是由于后面还可能用到原始图片,.ImageFolderDataset不加预处理的话可以满足,所以建议在.Dat ...

  9. 第一阶段——站立会议总结DAY02

    1.昨天做了什么:做出了一个大概的界面(APP的个人中心界面),有用户名信息和按钮. 2.今天准备做什么:因为仅是完成在页面上显示文字,而显示个人信息的化,想要做成微信的个人中心辣个样子. ①就是文字 ...

  10. NABCD框架(作业和事件的定期提醒)及第八周学习进度条

    NABCD框架(作业和事件的定期提醒): N(need,需求): 你的创意解决了用户的什么需求? 我们的创意能够一定程度上督促我们的用户(学生)尽快完成自己近期的任务或者是作业.我们认为如果增设定时提 ...