面向对象第三次博客作业
一、 规格发展历史
在20世纪50年代,软件伴随着第一台电子计算机的问世诞生了。以写软件为职业的人也开始出现,他们多是经
过训练的数学家和电子工程师。1960年代美国大学里开始出现授予计算机专业的学位,教人们写软件。在计算机系统发展的初期,由于目的的单一性,软件的通用性是很有限的。大多数软件是由使用该软件的个人或机构研制的,软件往往带有强烈的个人色彩。早期的软件开发也没有什么系统的方法可以遵循,软件设计是在某个人的头脑中完成的一个隐藏的过程。而且,除了源代码往往没有软件说明书等文档。
从60年代中期到70年代中期是计算机系统发展的第二个时期,在这一时期软件开始作为一种产品被广泛使用,出现了“软件作坊”专职应别人的需求写软件。这一软件开发的方法基本上仍然沿用早期的个体化软件开发方式,但软件的数量急剧膨胀,软件需求日趋复杂,维护的难度越来越大,开发成本令人吃惊地高,而失败的软件开发项目却屡见不鲜。“软件危机”就这样开始了!“软件危机”使得人们开始对软件及其特性进行更深一步的研究,人们改变了早期对软件的不正确看法。早期那些被认为是优秀的程序常常很难被别人看懂,通篇充满了程序技巧。现在人们普遍认为优秀的程序除了功能正确,性能优良之外,还应该容易看懂、容易使用、容易修改和扩充。
1968年北大西洋公约组织的计算机科学家在联邦德国召开的国际学术会议上第一次提出了“软件危机”(software crisis)这个名词。 概括来说,软件危机包含两方面问题:一、如何开发软件,以满足不断增长,日趋复杂的需求;
二、如何维护数量不断膨胀的软件产品。
1968年秋季,NATO(北约)的科技委员会召集了近50名一流的编程人员、计算机科学家和工业界巨头,讨论和制定摆脱“软件危机”的对策。在那次会议上第一次提出了软件工程(software engineering)这个概念。
软件工程是一门研究如何用系统化、规范化、数量化等工程原则和方法去进行软件的开发和维护的学科。通过不断努力,人们逐渐解决了软件危机,并认识到规格化设计的重要性,在此期间,一些重要的文档格式的标准被确定下来,包括变量、符号的命名规则以及源代码的规范式。后来随着发展,这些规范逐渐形成了软件开发中的规格化设计,并且由于其高效性与高可靠性,越来越受到软件开发人员的重视。
二、 bug统计
功能bug |
规格bug |
是否有联系 |
|
第9次作业 |
1 |
1 |
无 |
第10次作业 |
1 |
2 |
无 |
第11次作业 |
0 |
0 |
无 |
规格bug:
第9次作业:没有好好看ppt,所有的后置条件都写了赋值表达式。
第10次作业:修改第9次的作业的时候漏掉一个方法,有一个方法忘写规格。
功能bug:
第9次作业:被报了一个由多线调度引起的边界bug,不想多做解释,没有意义。
第10次作业:为了解决第9次作业的边界bug,引起了另一个边界bug。
第11次作业直接删掉了第10次作业的解决方案,边界bug就放那吧。
分析自己规格bug产生的原因:
没有认真看ppt,没有认真检查。
三、 规格举例
1、不好的写法:可以使用布尔表达式,但是使用了自然语言。
Scheduler(RequestQueue requestQueue,Taxi[] taxiQueue)
/**
* @REQUIRES: requestQueue != null && taxiQueue != null && (\all Taxi taxi; taxiQueue; taxi != null) && taxiQueue.length == 100;
* @MODIFIES: this.requestQueue; this.taxiQueue;
* @EFFECTS: initialize the member variable;
*/
{
this.requestQueue = requestQueue;
this.taxiQueue = taxiQueue;
}
修改以后:
/**
* @REQUIRES: requestQueue != null && taxiQueue != null && (\all Taxi taxi; taxiQueue; taxi != null) && taxiQueue.length == 100;
* @MODIFIES: this.requestQueue; this.taxiQueue;
* @EFFECTS: this.requestQueue = requestQueue && this.taxiQueue = taxiQueue;
*/
2、不好的写法:直接将代码赋值到EFFECTS中,而不是采用规格固有的语法格式。
public synchronized Request getRequest(int num)
/**
* @REQUIRES: this != null && 0 <= num < requestQueue.size && requestQueue != null;
* @MODIFIES: None;
* @EFFECTS: \result == requestQueue.get(num);
* @THREAD_REQUIRES: None;
* @THREAD_EFFECTS: \lock();
*/
{
return requestQueue.get(num);
}
修改以后:
/**
* @REQUIRES: this != null && 0 <= num < requestQueue.size && requestQueue != null;
* @MODIFIES: None;
* @EFFECTS: requestQueue.contains(\result) && requestQueue.indexof(\result) == num;
* @THREAD_REQUIRES: None;
* @THREAD_EFFECTS: \lock();
*/
3、不好的写法:没有列出所有变化。
public synchronized void setRequest(Request request)
/**
* @REQUIRES: this != null && requestQueue != null;
* @MODIFIES: requestQueue;
* @EFFECTS: requestQueue.contains(request);
* @THREAD_REQUIRES: None;
* @THREAD_EFFECTS: \lock();
*/
{
requestQueue.add(request);
}
修改以后:
/**
* @REQUIRES: this != null && requestQueue != null;
* @MODIFIES: requestQueue;
* @EFFECTS: requestQueue.contains(request) && requestQueue.size = \old(requestQueue).size + 1;
* @THREAD_REQUIRES: None;
* @THREAD_EFFECTS: \lock();
*/
4、不好的写法:描述了过程,而不是结果。
public synchronized static void clearFlow(Long time)
/**
* @REQUIRES: None;
* @MODIFIES: this.map;
* @EFFECTS: (\all Coordinate coordinate; coordinate.clearFlow(time));
*/
{
for(int i = 0;i < 80;i ++)
for(int j = 0;j < 80;j ++)
map[i][j].clearFlow(time);
}
修改以后:
/**
* @REQUIRES: None;
* @MODIFIES: this.map;
* @EFFECTS: (\all Coordinate coordinate; (\all Long flowTime in coordinate.flow; flowTime + 500 > time));
*/
5、不好的写法:描述了过程。
public static synchronized void close() throws IOException
/**
* @REQUIRES: recordLog != null && this.recordLog != null;
* @MODIFIES: None;
* @EFFECTS: close fileout stream;
*/
{
recordLog.close();
}
修改以后:
/**
* @REQUIRES: recordLog != null && this.recordLog != null;
* @MODIFIES: None;
* @EFFECTS: recordLog.status == close;
*/
四、 心得体会
周二开始写作业感觉良好,根本不担心改需求。改需求是可以考验代码的可扩展性和健壮性,但是再好设计也是需要时间来修改,并且需要重新测试,而之前做的所有测试就都白费了。这门课已经占用了大量的课余时间,并且通过改需求进一步压榨课余时间,别的课程就显得那么不重要嘛?还是必须每天两三点睡觉来应付所有的课程?
对于规格,规格的意义目前为止并没有体现出来,规格本是用来规划代码的,先写代码再补规格根本毫无意义,并且将规格作为测试点更是偏离了规格的初衷。
就我第11次测试拿到的代码来说,这份代码在第10次测试中被报了4个规格问题,两个格式问题,没有一个功能问题。而我测出三个功能性问题均是前几次作业的,也就是说第10次作业就存在。确实扣规格的分太容易了,毕竟人类不是计算机,写不出完美的布尔表达式,总会存在考虑不周的情况。可以轻轻松松扣他十几个规格问题,何必费心去读代码去测试。