面向对象第三单元个人总结
OO第三单元个人总结
一、如何利用JML规格来准备测试数据
1、首先保证代码语义与JML语言表达的语义的一致性,在完成代码后认真核对。
2、构造特殊数据,测试前置条件不满足时抛出异常的情况。
3、构造符合前置条件的数据,满足后置条件和约束条件,针对运行结果进行自我判断,或是进行对拍测试。
4、构造边界数据,或是构造超多数据,如超多条qgvs等等,来测试运行时间,若是运行时间过长,则需要进行优化。
5、借用室友搭建的评测机,进行对拍测试,发现自己的bug、发现自己运行速度过慢的问题。
二、图模型构建和维护策略
1、图模型构建:
主要的图结构是Person类中的图结构,以各个Person为节点,以value为权值,在构建的MyRelation类中,以Perspn的id表示Person将有关联的Person相连。
2、维护策略:
isCircle中,运用了课程组提供的并查集的方法,提升了运行速度,从而没有产生超时的问题。
queryLeastConnection中,需要求最小生成树,最小生成树的算法选用了Prim算法,保证了该方法的运行速度较快。
sendIndirectMessage中,运用了堆优化的迪杰斯特拉算法来求最短路径,提高运行速度。
整个MyNetwork类中,person、groups、emoji等均采用Hashmap来进行存取,减少各方法中不必要的循环,提高运行速度。
MyGroup中的getValueSum做了优化,维护了一个valuesum的变量,在每一次的addPerson和delPerson中运算,而不是在getValueSum中进行暴力的循环运算。(这也是我在改动前在互测中被hack的原因)
三、性能问题和修复情况
queryGroupValueSum因为没有维护而超时,在互测中被hack多次。
修复情况:已在前文提到,即在MyGroup中的getValueSum做了优化,维护了一个valuesum的变量,在每一次的addPerson和delPerson中运算,而不是在getValueSum中进行暴力的循环运算,大大提高了运行速度。
除此之外无其他性能问题。
公测互测情况:
个人bug:
queryGroupValueSum超时;
第九次作业的强测中,因个人粗心大意,在delPerson将循环的变量写错而出现错误。
他人bug:
因addToGroup中没有判断getGroup(id2).getSize()<1111而出错。
四、Network扩展
新增Advertiser、Producer、Customer、AdvertisementMessage、Product、BuyMessage类。
Advertiser:广告商 Producer:生产商 Customer:消费者
AdvertisementMessage:广告商发送的广告信息 Product:生产商生产的产品 BuyMessage:消费者发送的购买消息
NetWork中新增方法:sendAdvertisementMessage(int AdvertiserId,int AdvertisementMessageId) 广告商发送广告信息、
addAdvertisementMessage(int ProducerId,int AdvertiserId,int AdvertisementMessageid) 生产商发送广告信息给广告商、
addProduct(Product product) 生产商生产产品、
BuyProduct(int Customerid,int Productid) 消费者购买产品、
querySalesVolume(int ProductId) 查询某一产品的销售额、
querySalesPath(int ProducerId,int CustomerId,int ProductId) 查询某一产品的销售路径
JML:
addAdvertisementMessage(int ProducerId,int AdvertiserId,int AdvertisementMessageid) :
/*@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == AdvertiserId && people[i] instanceof Advertiser && people[i].containsAdvertisementMessage(AdvertisementMessageId));
@ assignable people[*].messages
@ ensures (\forall int i; 0 <= i && i < people.length; (getPerson(AdvertiserId).isLinked(people[i])) ==> (people[i].messages.length == \old(people[i].messages.length) + 1 && people[i].messages[0] == \old(getPerson(AdvertiserId).getAdvertisementMessage(AdvertisementMessageId)) && (\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(AdvertiserId).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() != AdvertiserId || (people[i].getId() == AdvertiserId && !people[i] instanceof Advertiser));
@ signals (AdvertisementMessageIdNotFoundException e) (\exists int i; 0 <= i && i < people.length && people[i].getId() == AdvertiserId && people[i] instanceof Advertiser; !people[i].containsAdvertisementMessage(AdvertisementMessageId));
@*/
public void sendAdvertisementMessage(int AdvertiserId, int AdvertisementMessageId) throws PersonIdNotFoundException, AdvertisementMessageIdNotFoundException;
addProduct(Product product) :
/*@ public normal_behavior
@ requires !(\exists int i; 0 <= i && i < products.length;products[i].equals(product));
@ assignable products
@ ensures products.length == \old(products.length) + 1;
@ ensures (\forall int i; 0 <= i && i < \old(products.length);
@ (\exists int j; 0 <= j && j < products.length; products[j] == (\old(products[i]))));
@ ensures (\exists int i; 0 <= i && i < products.length; products[i] == product);
@ also
@ public exceptional_behavior
@ signals (EqualProductIdException e) (\exists int i; 0 <= i && i < products.length;
@ products[i].equals(product));
@*/
public void addProduct(/*@ non_null @*/Product product) throws EqualProductIdException;
querySalesVolume(int ProductId):
/*@ public normal_behavior
@ requires containsProductId(ProductId);
@ ensures \result == getProduct(Productid).getSalesVolume();
@ also
@ public exceptional_behavior
@ signals (ProductIdNotFoundException e) !containsProduct(ProductId);
@*/
public int querySalesVolume(int ProductId) throws ProductIdNotFoundException;
五、学习体会
本单元主要学习了解了JML规格的使用与理解,它能够正确地表达程序的运行逻辑的,但是在编写和阅读时十分具有困难性,在今后的学习中具体是否能够经常使用还是不太确定的。本单元的作业在阅读与理解JML上困难性较低,虽然需要花费较多时间,但一句一句的阅读并不难理解,作业的难点却集中到了求最小生成树算法、求最短路径算法的运用与优化方面,训练算法固然有好处,但这是否有些本末倒置了,用算法的选择与优化来决定强测与互测是否能顺利通过、是否被hack这是我没有想到的,难道不应该是把注意力集中到JML的理解与运用上吗。经过三次作业,我也充分学习了最小生成树算法、最短路径算法及其优化,提高了我的算法水平。