随着第四次出租车作业的结束,整个OO课程最艰难的工程部分就宣告结束了,头发总算是保住了。首先感谢各位测我的dalao没有对本菜鸡儿的代码大开杀戒(诸如报20个JSF错之类的),这还是让我挺高兴的,某些OO中经常出现的很糟心的事情没有发生在我的身上(同时也为遇到了这些事情的同学默哀)。这四次OO作业的一个很大的侧重点就是对规格的训练,诸如对JSF,Overview,repOK等等的书写与实现。在大家经历了多线程电梯和IFTTT的折磨之后,对多线程的应用和处理已经日益精进,然而当大家在写出租车代码暗自得意的时候,JSF这个东西无疑是给了大家当头一棒。所以,本次博客在日常分析bug的基础之上,还增加了很多和规格有关的东西。
关于规格化设计的大致发展历史和为什么得到了人们的重视的问题,各大搜索网站基本没有给出明确的答案(我在必应搜这个的时候甚至搜到了前两天同学的博客hhh可见这东西网上很少)。将网上七零八落的资料结合起来还是能勉强得出一些结论的。国际标准化组织ISO曾经给出过软件的需求规格说明书,即SRS,但需求调查,分析工作告一段落的时候,人们需要对这些需求进行规格化描述,整理成文,这是在软件工程中相当有价值的一个文件。可能这就是规格化早期的情况,那时候的规格化主要面向于工程化开发的,具体的规格也相对较大,比如说针对某些特定的用户群体,使用特定的实现方式等。但是随着计算机科学的不断发展,规格变得越来越小,从最开始的面向大工程的规格描述,逐渐变成了我们今天所写的某一个函数的规格。规格化之所以受到人们的重视,在于其能够很好地描述程序员在进行项目开发是需要干什么,怎么干的问题。一个良好的规格,能让程序员在程序开发中保持一个清晰的思维,降低错误发生的几率,同时也能在交互的时候让用户明确地知道输入和输出的关系,什么输入能够让程序正常运行,得出正常的结果,而什么输入是非法的,不应该出现的。总之,规格的存在使得程序的开发效率,与用户的交互效果得到了很大的提升。
关于第三单元的三次作业的规格bug,所列出的表格如下:
BUG类别 |
每个出现所对应的代码行数 |
不符合JSF规范 |
普遍的BUG(Requires后面少了个空格。。。) |
Effects不完整 |
忘写run方法的线程部分的JSF了。Dispacher类130行,InputHandler类223行,Taxi类321行 |
三单元第一次作业
BUG类别 |
每个出现所对应的代码行数 |
不符合JSF规范 |
Main函数以及各个类的构造方法缺少JSF |
针对构造方法,初始状态repOK为真 |
Dispatcher类第29行,InputHandler类第31行,Taxi类第37行,LightsController类第15行 |
三单元第二次作业
BUG类别 |
每个出现所对应的代码行数 |
针对构造方法,初始状态repOK为真 |
所有repOK均未实现JSF方法 |
三单元第三次作业
在第一次作业中,我的规格BUG的主要产生问题体现在对JSF语法的认识不清晰,不透彻,于是在某些固定格式上犯错。JSF不同于自然语言,自然语言有很多种描述方法,因此有很大的歧义性,而JSF的描述比较明确,所以说规范JSF格式是非常重要的。除此之外还有线程方法忘记写其独有的JSF了,这也是对JSF格式不熟悉而造成的。在第二次作业中,一些JSF的边界性问题仍然出现,比如某些特殊函数(如Main,构造函数等需不需要写JSF等);而且repOK方法的构造出现失误,不能保证在初始化时repOK恒为真,这是对不变式在各种情况下的应用的不熟练。第三次作业中,仍然是边界性的错误。。。想当然地认为repOK方法不用实现JSF造成失分。
下面列举几个前置条件和后置条件的不好写法及其改进措施:
1.@REQUIRES:balabala... 改进@REQUIRES: balabala...(冒号后面有空格)
2.@REQUIRES: 变量a有效 改进:将变量a有效用JSF语言描述,自然语言讲不清楚。。。
3.@REQUIRES: 变量a非空 改进:a != null 尽量不用自然语言表述
4.@REQUIRES: a = 100 || a = 1 改进:a == 100 || a == 1
5.@REQUIRES: a > 0 && a < 100 改进:0 < a < 100
6.@EFFECTS: 函数返回值为0 改进:\result == 0(尽量避免用自然语言描述)
7.@EFFECTS: size = size + 1 改进:size = (\old)size + 1
8.@EFFECTS: a = 0 改进:a == 0(后置条件必为布尔表达式)
9.@EFFECTS: if(a == 0) then \result == 1 改进(a == 0) ==> (\reuslt == 1) (后置条件中不应描述算法)
10.@EFFECTS: vector.containsABCTogether() 改进vector.contains(A) && vector.contains(B) && vector.contains(C)(尽量用简单的单词来描述)
接下来给出被报的功能bug与规格bug在方法上的聚集关系,列表如下所示(第三单元第一次作业没有被查出功能性bug)
方法名 |
功能bug数 |
规格bug数 |
Taxi类的run方法 |
1 |
0 |
Taxi类的Taxi方法 |
0 |
1 |
Dispatcher类的Dispatcher方法 |
0 |
1 |
InputHandler类的InputHandler方法 |
0 |
1 |
LightsController类的LightsController方法 |
0 |
1 |
第二次作业
方法名 |
功能bug数 |
规格bug数 |
Dispatcher类的Dispatcher方法 |
1 |
0 |
Taxi类的run方法 |
2 |
0 |
Main类的main方法 |
1 |
0 |
第三次作业
最后对规格的撰写做一个总结,我在设计规格时的思路和设计方法时的思路一致,即先定方法的输入和想要方法达成的目的(有时是返回值,有时是修改变量),然后再定要修改的全局变量,然后开始规格的撰写,使用JSF的一些格式来完成规格,不到迫不得已(比如说当函数比较长导致EFFECTS不好描述的时候)不用自然语言来描述。然后开始进行函数的撰写,最后再对照JSF的三项来检查函数的实现是否与JSF的一致。其实当定好了规格之后你就可以直接开始写函数了,所以我个人觉得最先开始定规格是特别重要的,在定规格的时候顺便你也能理清方法的实现思路等等,定好了规格之后你就可以开始随意开火了,先下键盘写规格或者直接写方法都可以。最后不要忘了对照着JSF检查一下函数的实现是否与JSF有出入,然后根据出入分析决定是修改JSF还是修改函数本身。
总之,第三次博客作业到这里就结束了,这标志着OO之路基本可以说告一段落了。当然,还不能开浪,毕竟以后还有JSF的公测(我可不想被扣上20个JSF的错。。。)。
原文:https://www.cnblogs.com/lvba/p/9098183.html