oo第四次总结
论证与测试
第十三次作业的时候,我们开始使用Junit对代码进行测试,主要是测试代码的覆盖率,以及分支的覆盖率。
下面是测试的结果:
可以看出一些逻辑较为复杂的地方如果要使用junit去覆盖的话难度太大了,尤其是对于这种模拟代码,需要特判的地方太多了,比如一条很简单的语句:
if(floor>=1 && floor<=10 && (dir==1 || dir==-1))return true;
在junit中覆盖语句的话需要分别对dir,floor都进行覆盖,至少需要赋值5次,对于嵌套了更多分支的代码,这样的语句覆盖会更加繁琐和困难,所以对于个人项目来说个人还是推荐使用正确性论证。
对于测试,个人认为使用大规模随机数据的测试一般情况下就可以保证大体上的正确了,对于大部分项目,个人认为并不需要对于每个方法测试所有情况,以来对于大型项目来说工程量太大,而且效果可能并不如意,因为对于大项目来说,最重要的应该是对于框架的构建,而这一点更应该通过论证来实现,而每个方法中的小bug,再通过数据测试来保证其局部正确性。
调研OCL
OCL是一种描述UML建模细节的对象约束语言,它是UML标准的一部分。OCL是一种声明式语言,大部分表达式执行后会返回一个布尔值 。
UML类图中的所有值都可以被约束,而表达这些约束的方法就是 OCL。在UML2标准中,OCL不仅用来写约束,还能够用来对UML图中的任何元素写表达式。在JSF中就是对每个方法中的过程写表达式,然后每个OCL表达式都能指出系统中的一个值或者对象。因为 OCL表达式能够求出一个系统中的任何值或者值的集合,因此它具有了和SQL同样的能力,也就是说OCL也是一种查询语言。这一点是JSF所不具有的。
下面给出OCL的示例:
1 The age of a person is not negative. 2 A person is younger than its parents. 3 After a birthday, a person becomes one year older. 4 A Person has 2 parents at max. 5 After somebody got a child, his/her child-set is not empty, and it is larger than before. 6 Only an adult can be owner of a car. 7 The first registration of a car can not be before it is built. 8 Every Person that has a car has at least one car which is younger than the Person. 9 Nobody can be his/her own parent. 10 There's at least one Person which owns a car. 11 12 context Person inv: self.age >=0 13 context Person inv: self.parents->forAll(p|p.age>self.age) 14 context Person::hasBirthday() post: self.age=self.age@pre+1 15 context Person inv: self.parents->size()<=2 16 context Person::getsChild() post: self.childs->notEmpty() and self.childs->size() > self.childs@pre->size() 17 context Person inv: self.age<18 implies self.cars->isEmpty() 18 context Auto inv: self.registration>=self.constructionYear 19 context Person inv: self.cars->notEmpty() implies self.cars->exists( c | Calendar.YEAR - c.constructionYear < self.age) 20 context Person inv: self.parents->excludes(self) 21 context Person inv: Person.allInstances()->exists(p | p.cars->size() > 0)
可以看出,OCL和jsf在约束上非常类似,但是形式上更加自由,并没有强制以方法为最小单位,写起来轻松不少。
我们可以给出一个例子,如果一个变量在一个方法中和这个方法内的分支语句中的约束范围不一样,那么jsf中的requires写起来就麻烦了,而且可读性差,所以个人更加推荐OCL。
画图
uml类图
时序图
状态图
学期总结
总的来说,这学期的oo是由浅入深的,前三次编程作业主要考察基础编程能力,4~6次作业考察多线程,7~9次作业考察代码的规格化,是否方便扩展,最后几次教我们代码测试和一些使用方法,并且改进之前的错误,内容深度层层递进。
而我个人的程序,从第一次的一个方法一百四十多行,到第十四次重构的方法最长只有20行,代码越来越简短,耦合度越来越低,进步还是比较明显的。
同时也锻炼了抗压能力,每周从周五晚上开始到下一周周五上午结束是一个循环,这个学期就是在一轮一轮循环中度过的,在整个循环的不同阶段,情绪会受到不同外界因素的影响,例如ddl导致的焦虑、树上莫名挂满bug的愤懑、对需求的不解,有时会微微失控,但是经过自我调节还是可以回归平稳,对自我情绪的把控力提高也是一项进步。
个人建议下一届的考期没什么事情做,可以烤漆布置一个大作业,让同学梦独立完成。代码行数应该有5000行以上。