OO第三次博客作业

规格化设计的历史

1950的第一次分离:主程序和子程序的分离

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

1975—1980的第二次分离:规格说明(Spec)和体(body)的分离

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

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

基于构件开发:

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

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

 

规格化设计为什么得到人们的重视?

  ·对多人开发而言,好的规格设计大大增强代码可读性,便于在程序员之间共享。利于分工协作,从而提高开发效率。

  ·对长期、非一次性项目而言,规格设计能够减小“遗忘成本”,降低开发人员变动的代价,帮助后来的设计者更好理解函数(方法)作用而忽视具体实现细节,利于后期维护。

 

作业规格bug以及功能bug

规格类别

Bug产生原因

产生行数

JSF规范

 Requires采用自然语言叙述,不是布尔表达式

12

Overview

漏写

13

repOK

漏写

15行

 

功能bug类别

Bug产生原因

方法名

出租车编号输出有误

索引没减1

LoadFile类的LoadTaxi()方法

WFS选择流量最少路径

漏写

Taxi类的RandomRun()方法

普通出租车走关闭道路

普通出租车类的部分未修改

Taxi类的MinPathRun()方法

• 功能bug与规格bug在方法上聚集关系

从上面的表格可以看出,这两者并没有多大的关联度,主要还是由于先编码debug再补充规格描述的作业完成顺序。

前置条件和后置条件的不好写法及相应改进写法

(1) 前置条件为null的情况

/**
     * @REQUIRES: request;
     * @MODIFIES: this;
     * @EFFECTS: this.req == request;
     */

===================================================

/**
     * @REQUIRES: request != null;
     * @MODIFIES: this;
     * @EFFECTS: this.req == request;
     */

(2)前置条件范围约束

/**
     * @REQUIRES: None;
     * @MODIFIES: this;
     * @EFFECTS: this.taxi == Taxilist[num];
     */

===================================================

/**
     * @REQUIRES:  0<=num<100;
     * @MODIFIES: this;
     * @EFFECTS: this.taxi == Taxilist[num];
     */

(3)后置条件不规范

/**
     * @REQUIRES: 0<=n<30;
     * @MODIFIED: this;
     * @EFFECTS:    initialize the Taxi's properties;       
     */

=========================================

/**
     * @REQUIRES: 0<=n<30;
     * @MODIFIED: this;
     * @EFFECTS:  this.taxi == Taxilist[n];
     */        

(4)后置条件不完整

/**
   * @REQUIRES: none; * @MODIFIED: this; * @EFFECTS: * (ele.size==0) ==> \result==true; * (\exist int i; 0<=i<els.size; (els[i].num>100 || els[i].num<1) || * (els[i].dir!=1 && els[i].dir!=-1 && els[i].dir!=80 && els[i].dir!=-80) ) || * (els[i].step<0) )) * ==> (\result==false);
*/

======================================================================================================

/**
 * @REQUIRES: none;
  * @MODIFIED: this;
  * @EFFECTS:
  * (ele.size==0) ==> \result==true;
  * (\exist int i; 0<=i<els.size; (els[i].num>100 || els[i].num<1) ||
  *       (els[i].status<0|| els[i].status>3) ) ||
  *       (els[i].credit<0) ||
  *       (els[i].dir!=1 && els[i].dir!=-1 && els[i].dir!=80 && els[i].dir!=-80) ) ||
  *          (els[i].step<0)  ))
  *       ==> (\result==false);
  */

 

(5)后置条件列举不完善

  /**
     * @REQUIRES: none;
     * @MODIFIES: this;
     * @EFFECTS: \result == \old(t)+1000;
     */

=======================

    /**
     * @REQUIRES: none;
     * @MODIFIES: this;
     * @EFFECTS: \result == \old(t)+1000 && this.s==0;
     */

 

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

由于是写先了代码再根据代码来撰写规格的顺序,这几次作业的完成可能已经背离了课程训练目标的初心所在。回过头总结来看,基本思路应该是:根据方法要实现的功能设计相应的规格描述,比如基本的Require、Modified和Effects,这样以来就大致构造出这个方法的框架了,从而在后续的编码过程中,看到规格描述的时候就可以知道这是一个具有什么功能的方法,在调用的时候需要注意什么,调用过程中会有什么参量发生变化,调用之后又会产生什么结果等等。JSF的要求可能实现起来有些繁琐,但是如果使用得当,个人认为可以在一定程度上规范自己的设计流程以及编码行为。

 

posted on 2018-05-30 16:34  ElleWater  阅读(175)  评论(0)    收藏  举报