oo第三单元作业总结

一、梳理JML相关内容

JML是一种形式化的、面向JAVA的行为接口规格语言。JML允许在规格中混合使用Java语法成分和JML引入的语法成分、拥有坚实的理论基础、使用Javadoc的注释方式、且已经拥有了相应的工具链,可以自动识别和分析处理JML规格。JML的相关工具链包括OpenJML、JMLUnit等,OpenJML可以对JML的正确性进行静态检验,以及对方法的正确性进行验证;JMLUnit可以生成简单的、针对边界条件的测试样例来对方法进行检测。

JML的形式化意味着可以消除歧义、可以被程序读取、可以自动分析和推导。这样,不仅写代码的人可以准确读懂需求,测试人员可以从测试上透视功能。

但JML语言所表示的规格仅仅是确保正确性,在实现时应仔细理解再去实现,往往都能找到比规格语言更优的实现方法。

 

二、部署SMT Solver验证代码

SMT Solver是一种测试代码的工具,功能与JUnit相似,即通过SAT(布尔表达式可满足性理论)验证代码是否能够得到预期结果。

 

三、部署JMLUnitNG/JMLUnit测试代码

配置完成JUnit后,结合第一次作业写了一个小小的测试代码:

  1 import com.oocourse.spec1.exceptions.EqualPersonIdException;
  2 import com.oocourse.spec1.exceptions.EqualRelationException;
  3 import com.oocourse.spec1.exceptions.PersonIdNotFoundException;
  4 import com.oocourse.spec1.exceptions.RelationNotFoundException;
  5 import org.junit.Assert;
  6 import org.junit.BeforeClass;
  7 import org.junit.Test;
  8 
  9 import java.math.BigInteger;
 10 
 11 public class TaskOneTest {
 12     private static MyNetwork network = new MyNetwork();
 13     private static MyPerson myPerson = new MyPerson(1,"test",BigInteger.TWO,100);
 14 
 15     @BeforeClass
 16     public static void before() throws EqualPersonIdException {
 17         network.addPerson(new MyPerson(1,"a",BigInteger.ONE,1));
 18         network.addPerson(new MyPerson(2,"b",BigInteger.ZERO,2));
 19         network.addPerson(new MyPerson(6,"c",BigInteger.ZERO,3));
 20         network.addPerson(new MyPerson(7,"d",BigInteger.ZERO,4));
 21         network.addPerson(new MyPerson(8,"e",BigInteger.ZERO,5));
 22         network.addPerson(new MyPerson(9,"f",BigInteger.ZERO,6));
 23     }
 24 
 25     @Test
 26     public void getId(){
 27         Assert.assertEquals(myPerson.getId(),1);
 28     }
 29 
 30     @Test
 31     public void getName(){
 32         Assert.assertEquals(myPerson.getName(),"test");
 33     }
 34 
 35     @Test
 36     public void getCharacter(){
 37         Assert.assertEquals(myPerson.getCharacter(),BigInteger.TWO);
 38     }
 39 
 40     @Test
 41     public void getAge(){
 42         Assert.assertEquals(myPerson.getAge(),100);
 43     }
 44 
 45     @Test
 46     public void isLinked(){
 47         Assert.assertTrue(myPerson.isLinked(myPerson));
 48     }
 49 
 50     @Test
 51     public void getAcquaintanceSum(){
 52         Assert.assertEquals(myPerson.getAcquaintanceSum(),0);
 53     }
 54 
 55     @Test
 56     public void queryValueInMyPerson(){
 57         Assert.assertEquals(myPerson.queryValue(myPerson),0);
 58     }
 59 
 60     @Test(expected = EqualPersonIdException.class)
 61     public void addPerson() throws EqualPersonIdException {
 62         network.addPerson(new MyPerson(1,"a",BigInteger.ONE,1));
 63     }
 64 
 65     @Test(expected = PersonIdNotFoundException.class)
 66     public void addRelationNoId() throws PersonIdNotFoundException, EqualRelationException {
 67         network.addRelation(3, 2, 3);
 68     }
 69 
 70     @Test(expected = EqualRelationException.class)
 71     public void addRelationEqualRelation() throws PersonIdNotFoundException, EqualRelationException {
 72         network.addRelation(1,2,100);
 73         network.addRelation(2,1,10);
 74     }
 75 
 76     @Test(expected = PersonIdNotFoundException.class)
 77     public void queryValue() throws PersonIdNotFoundException, RelationNotFoundException, EqualRelationException {
 78         network.addRelation(6,7,100);
 79         int ans = network.queryValue(6,7);
 80         Assert.assertEquals(ans,100);
 81         int sameId = network.queryValue(1,1);
 82         Assert.assertEquals(sameId,0);
 83         network.queryValue(2,3);
 84     }
 85 
 86     @Test(expected = PersonIdNotFoundException.class)
 87     public void queryConflict() throws PersonIdNotFoundException {
 88         BigInteger ans = network.queryConflict(1,2);
 89         Assert.assertEquals(ans,BigInteger.ONE);
 90         network.queryConflict(2,3);
 91     }
 92 
 93     @Test(expected = PersonIdNotFoundException.class)
 94     public void queryAcquaintanceSum() throws PersonIdNotFoundException, EqualRelationException {
 95        network.addRelation(8,9,1);
 96         int ansA = network.queryAcquaintanceSum(8);
 97         int ansB = network.queryAcquaintanceSum(9);
 98         Assert.assertEquals(ansA,1);
 99         Assert.assertEquals(ansB,1);
100         network.queryAcquaintanceSum(3);
101     }
102 
103     @Test(expected = PersonIdNotFoundException.class)
104     public void compareAge() throws PersonIdNotFoundException {
105         int ans = network.compareAge(1,2);
106         Assert.assertEquals(ans,-1);
107         int sameId = network.compareAge(1,1);
108         Assert.assertEquals(sameId,0);
109         network.compareAge(1,3);
110     }
111 
112     @Test(expected = PersonIdNotFoundException.class)
113     public void compareName() throws PersonIdNotFoundException {
114         int ans = network.compareName(1,2);
115         Assert.assertEquals(ans,-1);
116         int sameId = network.compareName(1,1);
117         Assert.assertEquals(sameId,0);
118         network.compareName(1,3);
119     }
120 
121     @Test
122     public void queryPeopleSum(){
123         int ans = network.queryPeopleSum();
124         Assert.assertEquals(ans,6);
125     }
126 
127     @Test(expected = PersonIdNotFoundException.class)
128     public void queryNameRank() throws PersonIdNotFoundException {
129         int ans = network.queryNameRank(2);
130         Assert.assertEquals(ans,2);
131         network.queryNameRank(3);
132     }
133 
134     @Test(expected = PersonIdNotFoundException.class)
135     public void isCircle() throws PersonIdNotFoundException, EqualRelationException {
136         network.addRelation(1,2,100);
137         boolean ans = network.isCircle(1,2);
138         Assert.assertTrue(ans);
139         network.isCircle(3,2);
140     }
141 }

 

四、作业架构梳理

三次作业的都采取了对着JML写代码的方法,往往在写的过程中才能理解JML规格是在干嘛。事实上,正确的顺序是先理解JML规格,再根据规格选择合适的容器和算法完成代码。因此三次作业的完成都不太理想。

第一次作业的难度不高,因此在算法上不必纠结太多。第二次作业出现了两个需要二重循环遍历才能得出结果的函数,直接按照JML写造成了强测的扑街,这也证明了架构的重要性:不能把各个函数分开看,而应该在整个类的层次上多加考虑。第三次作业出现了最短路径算法、边双连算法,直接照搬规格是走不通的,只能复习数据结构并写出代码。但是简单的实现算法在强测中再次扑街,应该多加思考优化算法。

 

五、分析bug修复情况

第一次的bug主要在于wrong answer,由于不能完全理解JML出现错误。

第二次bug主要在于CTLE,由于多次调用o(n^2)级别的代码导致运算量过大。通过优化架构,在输入时就遍历并存储,解决了问题。

第三次bug在于RTE,由于对几个函数的算法照搬JML,导致运行超时。应该结合整个类别,设计架构、优化算法。

 

六、心得体会

1、JML是规范代码的重要工具,对规格化编程有重要作用。

2、不同的算法对代码效率有很大影响,通过优化算法可以使程序获得脱胎换骨的变化。

3、即使规定了规格,代码架构仍然很重要!!!

你可能感兴趣的:(oo第三单元作业总结)