OO第三次博客作业
一、规格化设计的发展历史
在上个世纪50年代,美国大学里开始出现授予计算机专业的学位。由于这个时候的程序都还只是小规模的程序,软件的开发可以简单粗暴一点。但是到了60年代,随着计算机的发展和软件的广泛使用,软件需求日益复杂,维护的难度也随之增大,出现所谓的“软件危机”。Dijkstra提出了goto语句的危害,成为了当时讨论的热点,由此产生了结构化程序设计方法。程序的模块化设计,必不可少的是模块之间的交互,这时候模块的规格化就很重要。经过规格化的程序,不仅具有很高的可读性,而且使得数据更加安全,可以有效提高程序的可维护性,降低程序维护的成本。
二、规格bug
|
规格bug数量 |
功能bug数量 |
是否相关 |
第九次作业 |
1 |
0 |
否 |
第十次作业 |
0 |
4 |
否 |
第十一次作业 |
0 |
0 |
否 |
第九次作业由于遇到的测试者非常nice,虽然一些方法的EFFECTS写得都比较简略,但是仍只被报了一个incomplete(在这里再次感谢一下那位同学)。
下面是第十次作业的bug分析:
bug内容 |
出现位置 |
代码行数 |
出租车右转时间过长 |
move() |
345 |
出租车回头 |
waiting() |
175 |
红绿灯改变间隔时间不固定 |
run() |
46 |
关闭道路后出租车原地停留 |
serving() |
195 |
三、规格bug产生的原因
1.对JSF规范的学习不够深刻,很多时候都会有那种“只能意会,不能言传”的感觉。
2.先写的代码,再补的规格,难免会有错漏。(这也从侧面反映出写规格的重要性?)
3.使用自然语言较多,更多的是把它当作注释来写。
4.对于逻辑部分的把握能力还是不够强。
四、不好的写法以及改进
1.@REQUIRES为None
改进前:
public Light(TaxiGUI gui) { /** * @REQUIRES: None; * @MODIFIES: this; * @EFFECTS: this.gui == gui; */ this.gui = gui; }
改进后:
public Light(TaxiGUI gui) { /** * @REQUIRES: gui != null; * @MODIFIES: this; * @EFFECTS: this.gui == gui; */ this.gui = gui; }
2.没有仔细规定@REQUIRES里参数的范围
改进前:
public void change_status(int i) { /** * @REQUIRES: i>0; * @MODIFIES: status; * @EFFECTS: Change the status of this taxi according to i; */ this.status = i; }
改进后:
public void change_status(int i) { /** * @REQUIRES: 0<=i<=3; * @MODIFIES: status; * @EFFECTS: Change the status of this taxi according to i; */ this.status = i; }
3.使用自然语言
改进前:
public Taxi(int index, TaxiGUI gui,Light light) { /** * @REQUIRES: 0<=index<=99, gui != null, light != null; * @MODIFIES: this; * @EFFECTS: Initialize the attributes of this class; */ this.index = index; this.status = 2; this.credit = 0; this.x = new Random().nextInt(80); this.y = new Random().nextInt(80); this.face = new Random().nextInt(4); this.gui = gui; this.light = light; gui.SetTaxiStatus(index, new Point(x,y), status); }
改进后:
public Taxi(int index, TaxiGUI gui,Light light) { /** * @REQUIRES: 0<=index<=99, gui != null, light != null; * @MODIFIES: this; * @EFFECTS: this.index == index, this.status == 2, this.credit == 0, this.x == Random().nextInt(80), * this.y == Random().nextInt(80), this.face = Random().nextInt(4), this.gui == gui, this.light == light; * set the taxi in map. */ this.index = index; this.status = 2; this.credit = 0; this.x = new Random().nextInt(80); this.y = new Random().nextInt(80); this.face = new Random().nextInt(4); this.gui = gui; this.light = light; gui.SetTaxiStatus(index, new Point(x,y), status); }
4.@EFFECTS描述不规范
改进前:
public void credit_increase(int n) { /** * @REQUIRES: n == 1 || n == 3; * @MODIFIES: credit; * @EFFECTS: increase the credit; */ credit += n; }
改进后:
public void credit_increase(int n) { /** * @REQUIRES: n == 1 || n == 3; * @MODIFIES: credit; * @EFFECTS: credit == \old(credit) + n; */ credit += n; }
5.对于用synchronized修饰的方法,未给出THREAD_REQUIRES和THREAD_EFFECTS
改进前:
public synchronized int[][] get_lights() { /** * @REQUIRES: None; * @MODIFIES: None; * @EFFECTS: \result == this.light; */ return this.lights; }
改进后:
public synchronized int[][] get_lights() { /** * @REQUIRES: None; * @MODIFIES: None; * @EFFECTS: \result == this.light; * @THREAD_REQUIRES: \locked(\this); * @THREAD_EFFECTS: \locked(); */ return this.lights; }
五、一些感受
因为第一次写JSF是在完成了出租车大部分代码以后才开始补充的,所以对于写这个无感,觉得是在为了写而写。但是在互测的时候,拿到一份规格写得好的代码会让你觉得读懂别人的程序变得轻松,也更容易形成一个框架,所以在我看来,认真写规格,是对自己的程序一种负责任的态度。但是在课程的设计上,可以通过大量报规格bug来给自己加分的制度就显得很鸡肋,完全偏离了课程设计者的原意,真正的成为了面向运气编程。这几次作业我虽然没有被大量报规格bug,但是我知道我的规格写得还不是很好。希望能在不断的练习中让自己的规格越来越规范,提高自己的水平。