面向对象第三单元个人总结

第三单元总结

1.自测过程中测试数据的准备

在本单元中,我主要通过白盒测试来准备测试数据,即通过阅读JML规格,构造边界数据进行测试,以保证程序正确性。

2.架构设计、图模型构建和维护策略

主要的框架其实都已经被规定了,简单说一下图模型的构建以及维护的策略

各种变量主要在Network里面动态维护:(以及一些中间变量,如树分支的储存)

 

为了防止MyNetwork类内方法太多,过于臃肿,我还建立了MyTool类储存一些联系较少的方法:

 

qci和qbs都是用的并查集,比起dfs时间复杂度降低了;

qlc使用dijkstra算法,但排序上我的代码性能较差。

动态维护

主要就是各个树内的节点、并查集的connect数组以及求最短路径时各两点间的最短距离

3.代码实现出现的性能问题和修复情况

3.1第一次作业

在第一次作业中,代码出现的问题主要是我没有正确理解qbs命令的jml规格含义,导致正确性出现很大问题,虽过了中测,但强测一塌糊涂,想来这是我没有充分测试、与同学交流的缘故,修复时修改代码使其重新求取正确结果——树的个数,便完成了修复。

3.2第二次作业

第二次作业性能难点来自于两条指令,qgvsqlc

但我出问题的指令依旧是qbs,原因在于每次执行指令时都要重新查询计算一次,导致性能大大降低,修复时建立hashmap以储存每个树各自节点,且可以直接得到qbs结果。

3.3第三次作业

第三次作业的性能问题主要来自send_indirect_message指令,这条指令对应着最短距离算法。

但我出问题的指令依旧是qgvs,以及einf错误类型输出顺序问题导致的错误类型输出错误。qgvs原因在于没有实现MyGroup类内各项指标的动态变化,致使每次调用指令都要再进行一次静态计算,大大增加CPU时间。修复时,调整了错误的输出顺序,并进行动态调整group的相关指标。

4.Network扩展

假设出现了几种不同的Person

  • Advertiser:持续向外发送产品广告

  • Producer:产品生产商,通过Advertiser来销售产品

  • Customer:消费者,会关注广告并选择和自己偏好匹配的产品来购买 -- 所谓购买,就是直接通过Advertiser给相应Producer发一个购买消息

  • Person:吃瓜群众,不发广告,不买东西,不卖东西

如此Network可以支持市场营销,并能查询某种商品的销售额和销售路径等 请讨论如何对Network扩展,给出相关接口方法,并选择3个核心业务功能的接口方法撰写JML规格。

  1. Advertiser Producer Customer 都继承了类Person

  2. 增加类Product,属性包括id,price,Producer

  3. Advertiser只对Customer打广告,并发送给所有的Customer

  4. Advertiser有一定数量的Products,并通过Product向相应的Producer发送购买消息

选择了设置用户偏好,购买商品,打广告,撰写了JML规格;

设置用户偏好

/*@ public normal_behavior
      @ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == Personid && people[i] instanceof Customer) &&
        (\exists int i; 0 <= i && i<= products.length;products[i].getId() == ProductId);
      @ assignable getPerson(personId).preferences;
      @ ensures (\forall Product i;\old(getPerson(PersonId).prefer(i));getPerson(PersonId).prefer(i));
      @ ensures getPerson(personId).prefer(ProductId);
      @ also
      @ public exceptional_behavior
      @ signals (PersonIdNotFoundException e) !(\exists int i; 0 <= i && i < people.length;
      @          people[i].getId() == id && people[i] instanceof Customer);
      @ signals (ProductIdNotFoundException e) !(\exists int i; 0 <= i && i < products.length;
      @          products[i].getId() == ProductId);
      @*/
      public void setPreference(int PersonId, int ProductId) throw PersonIdNotFoundException,ProductIdNotFoundException;

customer通过advertiser购买商品

/*@ public normal_behavior
      @ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == CustomerId && people[i] instanceof Customer) &&
        (\exists int i; 0 <= i && i<= people.length; people[i].getId() == AdvertiserId && people[i] instanceof Advertiser) &&
        (\exists int i; 0 <= i && i<= products.length;products[i].getId() == ProductId);
      @ ensures getPerson(CustomerId).money = \old(getPerson(customerId).mondy) - getProduct(ProductId).getPrice();
      @ ensures getPerson(AdvertiserId).getRemaining(ProductId) = \old(\getPerson(AdvertiserId).getRemaining(ProductId)) - 1;
      @ also
      @ public exceptional_behavior
      @ signals (PersonIdNotFoundException e) !(\exists int i; 0 <= i && i < people.length;
      @          people[i].getId() == id && people[i] instanceof CustomerId);
      @ signals (PersonIdNotFoundException e) !(\exists int i; 0 <= i && i < people.length;
      @          people[i].getId() == id && people[i] instanceof AdvertiserId);
      @ signals (ProductIdNotFoundException e) !(\exists int i; 0 <= i && i < products.length;
      @          products[i].getId() == ProductId);
      @*/
      public void purchase(int AdvertiserId,int CustomerId,int ProductId) throw PersonIdNotFoundException,ProductIdNotFoundException;

advertiser投放广告

/*@ public normal_behavior
      @ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == advertiserId && people[i] instanceof Advertiser) &&
        (\exists int i; 0 <= i && i<= messages.length;products[i].getId() == adMsgId && products[i] instanceof adMessage);
      @ assignable messages;
      @ ensures !containsMessage(adMsgId) && messages.length == \old(messages.length) - 1 &&
      @         (\forall int i; 0 <= i && i < \old(messages.length) && \old(messages[i].getId()) != adMsgId;
      @         (\exists int j; 0 <= j && j < messages.length; messages[j].equals(\old(messages[i]))));
      @ ensures (\forall int i; 0<= i && i < people.length; people[i] instanceof Customer ;
                (\forall int j; 0 <= j && j < \old(getPerson(i).getMessages().size());
      @          getPerson(i).getMessages().get(j+1) == \old(getPerson(i).getMessages().get(i)) &&
      @          getPerson(i).getMessages().get(0) == \old(getMessage(adMsgId)) &&
      @          \old(getPerson(i).getMessages().size() == \old(getPerson(i).getMessages().size()) + 1));
      @ also
      @ public exceptional_behavior
      @ signals (PersonIdNotFoundException e) !(\exists int i; 0 <= i && i < people.length;
      @          people[i].getId() == id && people[i] instanceof Advertiser);
      @*/
      public void advertise(int advertiserId,int adMsgId) throw PersonIdNotFoundException;

  

5.心得体会

第三单元相对来说是比较友好的单元,但是对JML的运用还是掌握的不太好,致使第一次作业完成得很差。难点主要在优化性能上,第一次尝试使用并查集来优化算法。同时,让我复习了图论有关知识,提高了算法能力。虽然一味地按照JML语言实现较为简单,但繁杂的数据结构必会造成严重的性能下降,需要灵活应用。

posted @ 2022-06-05 21:59  魔光、炫水  阅读(23)  评论(0编辑  收藏  举报