OO第三单元总结
OO第三单元总结
自测过程
本单元我采用了黑盒测试,编写了对拍脚本并与几位同学。测试数据的生成参考jml规格,随机生成人物关系和查询指令。数据生成还可以调整各种指令的出现概率、最大出现次数,做到有针对性的进行测试。而且测试脚本分享给多人一起使用,加强了测试强度和效率。
架构设计
我实现了MyGraph类来对图进行建模,并在这个类中实现寻找最短路径和最小生成树。
最小生成树采用了Kruskal算法,实现如下
最短路径采用了Dijkstra算法,并且利用了堆优化。
性能问题和修复情况
在对拍过程中,没有发现bug。但是在第二次的互测中存在一个TLE的问题,这反映出了我对测试情况考虑的并不周全。
Network扩展
Advertiser、Producer和Customer都继承Person类;Producer增加一个属性来维护其生产的产品的id,Advertiser增加一个属性来维护其向外发送广告的产品的id,Customer增加一个属性来维护其偏好的产品的id。
查询销售额
/*
@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == id && people[i] instanceof Producer);
@ requires (\exists int i; 0 <= i && i < getPerson(id).products.length; getPerson(id).products[i].getId() == productId);
@ \results == getProduct(productId).cost * (\sum int i; 0 <= i && i < people.length && getPerson(id).isLinked(people[i]) && (\exists int j; 0 <= j && j < people[i].products.length; prople[i].products[j].equals(getPerson(id).getProduct(productId))); 1);
@ also
@ public exceptional_behavior
@ signals (PersonIdNotFoundException e) !(\exists int i; 0 <= i && i < people.length; people[i].getId() == id && people[i] instanceof Producer)
@ public exceptional_behavior
@ signals (ProductNotFoundException e) !(\exists int i; 0 <= i && i < getPerson(id).products.length; getPerson(id).products[i].getId() == productId);
*/
public /*@ pure @*/ int querySalaryValue(int id, int productId) throws PersonIdNotFoundException, ProductIdNotFoundException;
设置消费者偏好
/*
@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == personId) &&
@ (\exists int i; 0 <= i && i < products.length; products[i].getId() == productId)
@ assignable getPerson(personId).products;
@ ensures (\forall Product i; \old(getPerson(personId).hasProduct(i));
@ getPerson(personId).hasProduct(i));
@ ensures getPerson(personId).hasProduct(productId);
@ also
@ public exceptional_behavior
@ signals (PersonIdNotFoundException e) !(\exists int i; 0 <= i && i < people.length; people[i].getId() == id && people[i] instanceof Producer)
@ signals (ProductNotFoundException e) !(\exists int i; 0 <= i && i < products.length; products[i].getId() == productId);
*/
public void setPreference(int personId, int productId) throws PersonIdNotFoundException, ProductIdNotFoundException;
发送广告
/*
@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == id && people[i] instanceof Advertiser && people[i].containsAdvertisement(advertisementId));
@ assignable people[*].messages
@ ensures (\forall int i; 0 <= i && i < people.length; (getPerson(id).isLinked(people[i])) ==> (people[i].messages.length == \old(people[i].messages.length) + 1 && people[i].messages[0] == \old(getPerson(id).getAdvertisement(advertisementId)) && (\forall int j; 1 <= j && j < people[i].messages.length; people[i].messages[j] == \old(people[i].messages[j - 1]))));
@ ensures (\forall int i; 0 <= i && i < people.length; !(getPerson(id).isLinked(people[i])) ==> (people[i].messages.length == \old(people[i].messages.length && (\forall int j; 0 <= j && j < people[i].messages.length; people[i].messages[j] == \old(people[i].messages[j]))));
@ also
@ public exceptional_behavior
@ signals (PersonIdNotFoundException e) (\forall int i; 0 <= i && i < people.length; people[i].getId() != id || (people[i].getId() == id && !people[i] instanceof Advertiser));
@ signals (AdvertisementIdNotFoundException e) (\exists int i; 0 <= i && i < people.length && people[i].getId() == id && people[i] instanceof Advertiser; !people[i].containsAdvertisement(advertisementId));
*/
public void sendAdvertisement(int id, int advertisementId) throws PersonIdNotFoundException, AdvertisementIdNotFoundException;
学习体会
通过本单元的学习,我学习了契约式编程。这种方式明确了责任与义务,便于进行单元测试,也利于形式化验证程序的正确性。在我们的小作业中,这种契约并没有很明显地展现出它的重要性,但是我体会到,在多人协作的工程中,这样的契约是十分重要的。如果不划分好个方法的责任与义务,那么不管是架构设计、形式验证还是单元测试都是很难进行的。虽然本单元的总体难度不大,但我从中学到了很多面向对象的编程思想。