oo第三单元总结
oo第三单元总结
架构设计
-
模型
-
维护策略
- 属性:
- 因无法预估输入指令,只维护较好维护的属性,如AgeSum等
- 关系:
- 因输入指令仅限制条数,对节点二重遍历的复杂度远高于对边的遍历,故需维护每个节点的边集Edges。
- 连通性的检测最好采用并查集,故须维护人物关系树PeopleTree
- 属性:
性能分析
- 查询集合内部属性:由于维护了边集,而不用二重遍历节点,最多只需一重循环即可得到结果。同时维护的属性也可以达到1的复杂度
- 连通分量:采用并查集实现,就算不进行路径优化复杂度也最多为n
- 最小生成树:采用Prim算法,同时由于维护每个节点的边集优化了边的查找,复杂度也大概是n的量级
- 最短路径:与最小生成树十分类似
测试
- 性能测试:只进行分析,并无直接测试
- 功能测试:生成随机指令对拍
总结
- 本单元的思维难度大幅降低,最难的也只是那几个图算法的实现,但这种设计方式却十分值得我们学习。一方面JML无二义性的解析了需求,保证了客观需求到代码需求的正确性。另一方面这种由宏观到微观的设计思想逻辑上很通顺,不会出现各种重构的问题。此外这种只关心前提,约束的特点也很好的体现了封装性,每一模块只实现每一模块的功能,写起代码来很好上手。
扩展
-
向个人投放广告
/*@public normal_behavior @requires contains(id1) && getPerson(id1) instanceof Advertiser && containsMessage(id2) && getMessage(id2) instanceof AdvertiseMessage; @assignable messages; @assinable getPerson(id1).advertisement[]; @assinable getPerson(id2).preference[]; @ensures !containsMessage(id2) && messages.length == \old(messages.length) - 1 && @(\forall int i; 0 <= i && i < \old(messages.length) && \old(messages[i].getId()) != id; @(\exists int j; 0 <= j && j < messages.length; messages[j] == (\old(messages[i]))); @ensures (\forall int i; 0 <= i && i < (\old(getPerson(id1).advertisement.length))); @ (\exists int j; 0 <= j && j < getPerson(id1).advertisement.length; @ getPerson(id1).advertisement[j] == (\old(getPerson(id1).advertisement.[i]))); @ensures (\exists int i; 0 <= i && i < getPerson(id1).advertisement.length); @ getPerson(id1).advertisement[i] == getMessage(id2)) @ensures (\exists int i; 0 <= i && i < \old(getPerson(id1).advertisement.length; @(\old(getPerson(id1).advertisement.[i])) == getMessage(id2)) ==> @ getPerson(id1).advertisement.length == @ (\old(getPerson(id1).advertisement.length)) && @ getPerson(id1).preference.length == @ (\old(getPerson(id1).preference.length)) && @ getPerson(id1).preference[i] == \old(getPerson(id1).preference[i]) + 1; @ensures (\forall int i; 0 <= i && i < \old(getPerson(id1).advertisement.length; @(\old(getPerson(id1).advertisement.[i])) != getMessage(id2)) ==> @ getPerson(id1).advertisement.length == @ (\old(getPerson(id1).advertisement.length)) + 1 && @ getPerson(id1).preference.length == @ (\old(getPerson(id1).preference.length)) + 1 && @ (\exists int i; 0 <= i && i < getPerson(id1).advertisement.length); @ getPerson(id1).advertisement[i] == getMessage(id2)) && @ getPerson(id1).preference[i] == 1; @also @public exceptional_behavior @signals (MessageIdNotFoundException e) !containsMessage(id); @signals (PersonIdNotFoundException e) !contains(id1); */ public void advertise(int id1, int id2) throws MessageIdNotFoundException, PersonIdNotFoundException
-
生产产品
/*@ public normal_behavior @ requires contains(producerId) && (getPerson(producerId) instanceof Producer); @ assignable getProducer(producerId).productList @ ensures getProdectCount(productId) @ ensures getProducer(producerId).getProductCount(productId) == @ \old(getProducer(producerId).getProductCount(productId)) + 1; @ also @ public exceptional_behavior @ signals (PersonIdNotFoundException e) !contains(producerId); @ signals (NotProducerException e) !(getPerson(producerId) instanceof Producer); @*/ public void Produce(int producerId, int productId) throws PersonIdNotFoundException, NotProducerException;
-
购买商品
/*@ public normal_behaviour @ requires message instanceof purchaseMessage; @ requires contains(advertiserId) && @ (getPerson(advertiserId) instanceof Advertiser); @ requires !getPerson(advertiserId).containsMessage(message.getId()) @ assignable getPerson(advertiserId).message[]; @ ensuers getPerson(advertiserId).message.length == \old(getPerson(advertiserId).message.length) && @ getPerson(advertiserId).containsMessage(message.getId()); @ also @ public exceptional_behavior @ signals (PersonIdNotFoundException e) !contains(advertiserId); @ signals (WrongMessageTypeException e) !(message instanceof purchaseMessage); @*/ void purchase(int advertiserId, Message message) throws PersonIdNotFoundException, WrongMessageTypeException;