OO第三阶段总结

一、规格化设计

规格就是对一个方法/类/程序的外部可感知行为的抽象化表示,忽略实现的具体细节,使得设计与实现有效的分离开来。规格化设计的实现依赖于抽象化(Abstraction),包括过程抽象,数据抽象等等。使用规格化设计带来的好处就是减少了程序的复杂度,使得程序员可以专注于处理少数重要的部分,而不是钻牛角尖似的纠结于程序细节问题,提高编程的效率和安全性。

使用规格化编程可以大大提高编程质量。首先,提高了程序的可读性,类的每一个方法都明确的给出了方法的功能与对数据的影响,使得代码的使用者可以不必阅读繁琐的代码信息,只需要通过阅读方法规格就可以详细的了解方法的所有信息,这在团队合作中非常有效。其次,规格化编程可以提高程序的安全性。在具体实现一个方法之前,先用规格化对方法进行描述,相当于一个自我的逻辑纠错过程,避免了许多逻辑上的安全性漏洞,而且有了方法规格之后,程序的编写就变得更加行云流水了。

二、规格BUG

有幸这几次作业都没有被报规格上的BUG,也没有逐个深究其他人规格上的BUG,但是,通过与其他人的讨论以及对自己和被测者规格的检查,可以发现一些大家在规格上的共性的问题。

一个是偷懒。最明显的就是以下这种:

/**
*@REQUIRES: None;
*@MODIFIES: None;
*@EFFECTS: None;
*/

而这段注释下面跟着的是一段十分冗长的代码,总不能什么事都不干吧。明显就是偷懒行为。

第二个就是纯自然语言描述,并没有使用规定的JSF语言。纯自然语言固有的问题就是容易产生逻辑上的漏洞也就是歧义,如果规格使用纯自然语言描述的话,自己读的很顺畅,但可能partner来阅读这段规格就“丈二和尚摸不着头脑”,给整个团队带来麻烦,所以,规格的描述应该尽量减少纯自然语言的使用,只有那些十分复杂,用JSF语言描述不了的方法,才使用自然语言,但问题来了,一个规格化设计的程序不应该出现及其复杂的代码,这就陷入了先有蛋还是先有鸡的逻辑怪圈了。

三、规格的改进

例1

/**
* @REQUIRES:None;
* @MODIFIES: None;
* @EFFECTS:
* \result == (与(X,Y)相连的顶点个数大于2);
*/

这是一段判断一个路口可不可以设置红绿灯的规格,可以发现后置条件直接使用自然语言描述,其实是不必要的,可以使用JSF语言来进行描述,修改后如下:

*@EFFECTS:
*int i == ((x,y+1).connects(x,y)) + ((x,y-1).connects(x,y)) +  
*((x+1,y).connects(x,y)) + ((x-1,y).connects(x,y));
*\result == (i >= 3);

例2

/**
* @REQUIRES:(dst!=null && 0<=root<6400);
* @MODIFIES: None;
* @EFFECTS:
* \result == path;
*/

这是一段获取最短路径的规格,在后置条件里很突兀的出现了一个变量path,很明显没有对path进行描述,更改后如下:

*@EFFECTS: 
(\result!=null) ==> (\result[0] == start) &&(\result[\result.length1]==end)
&& (\all int i; 0<=i<\result.length-1; this.connects(\result[i],
\result[i+1])) && (\all List<Node> p; p[0]==start && p[p.length-1]==end &&
\all int j; 0<=j<p.length-1; this.connects(p[j], p[j+1]) && p.length
>=\result.length)
*/

直接对result进行描述,在逻辑上清晰了许多。

例3

/**
* @REQUIRES:(path!=null);
* @MODIFIES:map;
* @EFFEETS:
* (path对应文件存在) ==> (map[][]各元素置为读入的数字);
*/

这是摘取字读取地图文件的规格,明显前置条件描述并不全面,缺少了对地图文件内容的限制,修改后如下:

/**
*@REQUIRES:(new File(path)).isFile && (new File(path)).line == 80 && (new File(path)).column == 80 && (new File(path)).words.isDigit;

通过路径获取到的文件的行数列数都应该是80,而且所有的字符都应该是数字。

四、功能BUG与规格BUG千丝万缕的联系

经过这几次作业的练习,确实发现了规格对编程的助力,但许多方法的实现仍沿用了老的思路,规格也算是蒙混过关吧,写完方法之后才写的规格,这导致了许多问题,反思这些问题,总能在规格上找到影子。

整理了这张表,记录下这些联系。

方法名 规格BUG 功能BUG
public void readFile(String filepath) 使用自然语言描述后置条件 读取新的地图文件时会报错
private int[][] branch() 规格描述不全面,忽略了功能细节 根据流量选择道路时出现了问题

五、感想与体会

这三次作业的练习,获益良多,认识到了抽象化在程序设计中的重要意义,也体会到了应用规格后在编写程序方面的助力,但明显感觉到的问题就是,规格化设计虽好,但给每个类写上规格,就会使编程效率大大降低,算是喜忧参半吧,可能这也是规格化设计应用的局限之处,但对个人编程以及团队编程来说,给一些对项目实现极其重要的方法写上规格,确实能大大提高项目的可靠性,这对以后的编程给出了很好的思路。

posted @ 2018-05-28 20:07  Nipo  阅读(158)  评论(0编辑  收藏  举报