一、规格化设计的历史以及人们重视的原因

发展历史

从20世纪60年代开始,就存在着许多不同的形式规格说明语言和软件开发方法。在形式规格说明领域一些最主要的发展过程列举如下:

1969-1972 C.A.R Hoare撰写了"计算机编程的公理基础(An Axiomatic Basis for Computer Programming)"和"数据表示的正确性证明"两篇开创性的论文,并提出了规格说明的概念。

1974-1975 B.Liskow/S.N. Zilles和J. Guttag引入了"抽象数据类型"的概念。

1976      E.W. Dijkstra定义了"最弱前置条件"的概念

1977      R.Burstall和J.Goguen提出了第一个代数规格说明语言:Clear

1988      Standford的SRI开发了代数规格说明语言OBJ3

1980-1986 C.Jones定义了VDM语言,也就是维也纳开发方法。

1985-1992  牛津大学的程序研究小组开发了Z规格说明语言。与此同时BP研究室开发了称之为B方法的面向模型的规格说明语言。

1985-1993 在MIT和Digital SRC开发了代数规格说明语言Larch

从1991年开始,面向对象的形式规格说明语言开始发展,例如,Object-Z, VDM++, CafeOBJ等语言。

1996-2000年 在欧洲CoFI(Common Framework Initiative)项目资助下开发"统一"代数规格说明语言CASL(Common Algebraic Specification Language)

重视原因

我认为规格首先给了大家编程时一个统一的认识,明确了程序运行的前提和程序运行后的效果,这一点在个人编程中有助于理清思路,而在集体的工程开发过程中也有助于协作,使大家开发的方向一致。

另一方面我认为正确的规格可以方便编程者进行调试,通过断言判断前置条件是否满足以及检验后置条件是否在程序运行后满足。

二、规格Bug数量及原因分析

作业 Bug类型及细节 所在文件及行数
第九次
第十次 Effects内容为实现算法:\result写成了\return 很多文件中
第十一次 Effects不完整:在有try-catch的方法中忘记写exceptional_behavior InputHandler.java/192

规格bug原因分析:第九次没有被报规格bug,大概是测试者不太关心。第十次和第十一次作业中都是有所疏忽导致。其中第十次作业是一个笔误,几乎所有文件都写成了\return==balabala,第十一次作业中有一个方法由于后来有改动,没有添加exceptional_behavior。

三、不好的规格写法及改进

前置条件

1. 自然语言描述

     /**
* @REQUIRES: k存在
* @MODIFIES: v
* @EFFECTS: v == \old(v) + 1;
*/

不好

     /**
* @REQUIRES: k != null
* @MODIFIES: v
* @EFFECTS: v == \old(v) + 1;
*/

2. 不是布尔表达式

    /**
*
* @REQUIRES:
* this.taxiStatus = IDLE;
* @MODIFIES:
* this.credit;
* @EFFECTS:
* this.credit = \old(this.credit) + 1;
* (\all PassengerRequest r in range, r.grabbedByTaxi(this))
*
*/

不好

    /**
*
* @REQUIRES:
* this.taxiStatus == IDLE;
* @MODIFIES:
* this.credit;
* @EFFECTS:
* this.credit = \old(this.credit) + 1;
* (\all PassengerRequest r in range, r.grabbedByTaxi(this))
*
*/

3. 没有规定范围

    /**
*
* @REQUIRES:
* locX, locY, dstX, dstY;
* @MODIFIES:
* edge between (locX, locY),(dstX, dstY), ConsolePrinter;
* @EFFECTS:
* edge.existence == op;
*
*/

不好

    /**
*
* @REQUIRES:
* 0 <= locX, locY, dstX, dstY <= 79;
* @MODIFIES:
* edge between (locX, locY),(dstX, dstY), ConsolePrinter;
* @EFFECTS:
* edge.existence == op;
*
*/

4. 遗漏了某些条件,一般是传入参数外的某些条件

    /**
* @REQUIRES: mapVertex != null;
* @MODIFIES: ConsolePrinter
* @EFFECTS: \result == the opposite vertex of mapVertex
*/

不好

    /**
* @REQUIRES: mapVertex != null && mapVertex.repOK == true;
* @MODIFIES: ConsolePrinter
* @EFFECTS: \result == the opposite vertex of mapVertex
*/

5. 对于一个容器中的所有对象,均需要规定前置条件

    /**
*
* @REQUIRES:
* this.edgeMap != null
* @MODIFIES:
* None
* @EFFECTS:
* (\exist MapEdge e, edgeMap.contains(e), \min(edgeMap.flowrates) == e.flowrate && \result == e);
*
* @THREAD_EFFECTS:
* (\ all MapEdge e in this.edgeMap);
*/

不好

    /**
*
* @REQUIRES:
* (\ all MapEdge e, this.edgeMap.contains ( e), e != null)
* @MODIFIES:
* None
* @EFFECTS:
* (\exist MapEdge e, edgeMap.contains(e), \min(edgeMap.flowrates) == e.flowrate && \result == e);
*
* @THREAD_EFFECTS:
* (\ all MapEdge e in this.edgeMap);
*/

后置条件

1. 不是布尔表达式

    /**
*
* @REQUIRES:
* this.requestQueue != null
* @MODIFIES:
* None
* @EFFECTS:
* return this.requestQueue;
*
*/

不好

    /**
*
* @REQUIRES:
* this.requestQueue != null
* @MODIFIES:
* None
* @EFFECTS:
* \result == this.requestQueue;
*
*/

2. 返回容器时不够明确

    /**
*
* @REQUIRES:
* this != null
* @MODIFIES:
* None
* @EFFECTS:
* \result == (\all MapEdge e in this.edgeMap)
*
*/

不好

    /**
*
* @REQUIRES:
* this != null
* @MODIFIES:
* None
* @EFFECTS:
* \result == new Arraylist<MapEdge> r;
* (\all MapEdge e, this.edgeMap.contains(e), r.contains(e))
*
*/

3. 改变值书写不规范

    /**
*
* @REQUIRES:
* this != null, num > 0;
* @MODIFIES:
* this.credit;
* @EFFECTS:
* this.credit += num;
*
*/

不好

    /**
*
* @REQUIRES:
* this != null, num > 0;
* @MODIFIES:
* this.credit;
* @EFFECTS:
* this.credit == \old(this.credit) + num;
*
*/

4. 没有写异常情况

        /**
* @REQUIRES:
* this.list != null;
* @MODIFIES:
* None
* @EFFECTS:
* this.hasNext() ==> (\result == this.list[\old(index)+1] && index == \old(index) + 1);
*
* @THREAD_EFFECTS:
* \locked(this.list);
*/

不好

        /**
* @REQUIRES:
* this.list != null;
* @MODIFIES:
* None
* @EFFECTS:
* this.hasNext() ==> (\result == this.list[\old(index)+1] && index == \old(index) + 1);
* exceptional_behavior(NoSuchElementException)
*
* @THREAD_EFFECTS:
* \locked(this.list);
*/

5. 后置条件没写全

    /**
* @REQUIRES: key != null;
* passengerRequest != null;
* @MODIFIES: this.unprocessedRequests, ConsolePrinter;
* @EFFECTS: unprocessedRequests.contains(passengerRequest);
* @THREAD_EFFECTS: \locked(this.appendlock);
*/

不好

    /**
* @REQUIRES: key != null;
* passengerRequest != null;
* @MODIFIES: this.unprocessedRequests, ConsolePrinter;
* @EFFECTS: unprocessedRequests.contains(passengerRequest); unprocessedRequests.size == \old(unprocessedRequest).size + 1
* @THREAD_EFFECTS: \locked(this.appendlock);
*/

四、功能Bug与规格Bug的聚类关系

本人仅在第九次作业中被报了功能bug,分别是输入格式错误会导致crash(说好的测试者保证呢)以及bfs在添加流量后判断条件有误导致找出了流量最小而不是距离最近的道路(在车聚集在一堆的时候可能绕路)。

之后的jsf问题我认为均是格式或者规范问题,与功能并没有什么关系,基本上都是功能实现正确但jsf写的时候可能有所遗漏。

五、撰写规格的思路与体会

之前写作业往往是先写程序代码最后再写规格,后来有尝试先写规格再改程序代码。规格的问题往往出在改正了程序的代码,然后程序跑着没什么问题了,结果改的地方一多就忘记改规格了。虽然看群里大家对于JSF的设计都有些抱怨,但JSF在复查代码的方面的确有一定的帮助,也对我形成工程化思想有了一些小小的推动作用。

希望课程组可以逐渐完善JSF,起码现在感觉很多复杂的逻辑用JSF表达起来非常费力以至于不得不用自然语言。

OO第三次阶段性总结的更多相关文章

  1. OO第三次课程总结分析

    OO第三次课程总结分析 规格化设计发展历史 在网上找了好久也没找到合适的信息,稍稍参考了同学的博客.大致如下:最初的的软件并没有形式化方法,随着软件工程的兴起,为了便于工程间的协调管理,人们提出采用工 ...

  2. [BUAA OO]第三次博客作业

    OO第三次博客作业 1. 规格化设计的发展 我认为,规格化设计主要源自于软件设计的两次危机.第一次是由于大量存在的goto语句,让当时被广泛应用的面向过程式的编程语言臃肿不堪,在逻辑性上与工程规模上鱼 ...

  3. OO第三次博客作业——规格

    OO第三次博客作业——规格 一.调研结果: 规格的历史: 引自博文链接:http://blog.sina.com.cn/s/blog_473d5bba010001x9.html 传统科学的特点是发现世 ...

  4. OO第三单元作业总结

    OO第三单元作业总结--JML 第三单元的主题是JML规格的学习,其中的三次作业也是围绕JML规格的实现所展开的(虽然感觉作业中最难的还是如何正确适用数据结构以及如何正确地对于时间复杂度进行优化). ...

  5. 规格化设计——OO第三单元总结

    规格化设计--OO第三单元总结 一.JML语言理论基础.应用工具链 1.1 JML语言 ​ JML(java modeling language)是一种描述代码行为的语言,包括前置条件.副作用等等.J ...

  6. 【OO学习】OO第三单元作业总结

    [OO学习]OO第三单元作业总结 第三单元,我们学习了JML语言,用来进行形式化设计.本单元包括三次作业,通过给定的JML来实行了一个对路径的管理系统,最后完成了一个地铁系统,来管理不同的线路,求得关 ...

  7. OO第三单元(地铁,JML)单元总结

    OO第三单元(地铁,JML)单元总结 这是我们OO课程的第二个单元,这个单元的主要目的是让我们熟悉并了解JML来是我们具有规格化编程架构的思想.这个单元的主题一开始并不明了,从第一次作业的路径到第二次 ...

  8. OO第三单元——基于JML的社交网络总结

    OO第三单元--基于JML的社交网络总结 一.JML知识梳理 1)JML的语言基础以及基本语法 JML是用于java程序进行规格化设计的一种表示语言,是一种行为接口规格语言.其为严格的程序设计提供了一 ...

  9. OO第三单元作业——魔教规格

    OO第三单元作业--魔教规格 JML的理论基础和相关工具   JML(Java Modeling Language,Java建模语言),在Java代码种增加了一些符号,这些符号用来标志一个方法是干什么 ...

随机推荐

  1. java.util.concurrent.Future Basics

    Hereby I am starting a series of articles about future concept in programming languages (also known ...

  2. 23种设计模式之责任链模式(Chain of Responsibility)

    责任链模式是一种对象的行为型模式,避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止.责任链模式不保证每个请求都被接受, ...

  3. [NHibernate] Guid 作主键速度超慢的背后

    http://blog.csdn.net/educast/article/details/6602353 最近遇到了一个让人抓狂的性能问题.生产环境里有一张表的数据量目前达到了 70 万条.结果发现无 ...

  4. Python 装饰器使用指南

    装饰器是可调用的对象,其参数是另一个函数(被装饰的函数). 1 装饰器基础知识 首先看一下这段代码 def deco(fn): print "I am %s!" % fn.__na ...

  5. yii---where该如何使用

    简单示例yii 的where使用方法: $where = ['post_id'=>$postId]; //$list = ForumThreadPost::find()->where($w ...

  6. uploadify3.2.1 多文件上传总是只能上传一个文件

    再网上找了老半天原因,有人说是上传时调用方法参数应该加上*号(:$('#mulfile_upload').uploadify('upload','*');) 总是不行, 我怀疑下面的原因: 我就以为是 ...

  7. git 出现 refusing to merge unrelated histories 解决

    如果出现refusing to merge unrelated histories,使用以下方法即可 git pull origin master --allow-unrelated-historie ...

  8. UITableView左右滑动cell无法显示“删除”按钮的原因分析

    http://www.cocoachina.com/bbs/read.php?tid-145693.html - (void)tableView:(UITableView *)tableView co ...

  9. 使用schemasync同步数据库表结构

    安装方式 wget http://www.schemasync.org/downloads/SchemaSync-0.9.4.tar.gz tar -xf SchemaSync-0.9.4.tar.g ...

  10. CCO2017 Vera and Trail Building 构造+图论

    正解:构造+图论 解题报告: 找了半天才找到的传送门! 先简要表达下题意 一个图上,如果存在(a,b)满足a<b且存在从a到b再回到a的路径,每条道路被经过至多一次,我们称(a,b)为完美点对试 ...