ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BUAAOO-第三单元总结

2021-05-29 12:02:08  阅读:175  来源: 互联网

标签:总结 network ageVar int person BUAAOO new getPerson 单元


BUAAOO-第三单元总结

实现规格所采取的设计策略

在第一次作业中,开始没有经验,采取了直接对规格进行“翻译”的策略,对数据保存直接使用了定长数组,后发现这样操作代码可读性不高且性能较差,于使重新改写为使用HashMap保存。

第二次作业中,虽然使用容器实现了数据存储,但是算法方面由于直接按照规格描述进行实现,导致了大量的CTLE。于使此后,阅读完规格后我能对方法有彻底理解后再根据自己的理解去实现。

再有以上经验后,认为实现规格应采取如下步骤:

  1. 完整阅读规格

  2. 选择正确的数据结构,容器

  3. 正确处理异常

  4. 选择合适的算法实现方法

基于JML规格来设计测试的方法和策略

  1. 再次阅读JML规格,检查在方法被实现前,异常是否被正确,处理检查方法是否满足规格的ensure

  2. 使用Junit,针对每一个具一定不确定因素的方法编写测试样例进行测试

  3. 对程序整体进行大数据集测试

本单元看似简单,但在测试方面我做的并不理想,在三次作业中均出现了非常低级的BUG

第一次:

原因是在阅读JML时并未彻底理解其含义,直接按照规格进行书写,导致进行了逻辑完全错误的一个判断

第二次:

低估了自己犯低级错误的的概率(当然本次作业主要问题在CTLE上)

第三次:

 

自作聪明在判断异常之前就删除了message,造成了大量WA

三次作业出现的bug基本都是在阅读JML规格时丧失理性造成的,事实证明在阅读JML时候一定要保证独立思考的能力,当然锅也不能全部甩到这里,归根结底还是自己懒得测试且高估了自己写简单代码不出错的能力

(Junit暴力测试?)

    @org.junit.jupiter.api.Test
   void sendIndirectMessage() throws EqualPersonIdException, PersonIdNotFoundException, EqualRelationException, MessageIdNotFoundException, EmojiIdNotFoundException, EqualMessageIdException, RelationNotFoundException, EqualEmojiIdException {
       Network network = new MyNetwork();
       network.addPerson(new MyPerson(1, "A", 10));
       network.addPerson(new MyPerson(3, "N", 10));
       network.addPerson(new MyPerson(6, "F", 10));
       network.addRelation(1, 3, 10);
       network.addRelation(3, 6, 15);
       network.addRelation(1, 6, 26);
       network.storeEmojiId(1);
       network.storeEmojiId(3);
       network.storeEmojiId(5);
       network.storeEmojiId(7);
       network.storeEmojiId(9);
       network.storeEmojiId(91);
       network.addMessage(new MyMessage(1, 10, network.getPerson(1), network.getPerson(6)));
       network.addMessage(new MyEmojiMessage(2, 1, network.getPerson(1), network.getPerson(6)));
       network.addMessage(new MyEmojiMessage(3, 1, network.getPerson(1), network.getPerson(6)));
       network.addMessage(new MyEmojiMessage(4, 1, network.getPerson(1), network.getPerson(6)));
       network.addMessage(new MyEmojiMessage(5, 3, network.getPerson(1), network.getPerson(6)));
       network.addMessage(new MyEmojiMessage(6, 9, network.getPerson(1), network.getPerson(6)));
       network.addMessage(new MyEmojiMessage(7, 91, network.getPerson(1), network.getPerson(6)));
       network.addMessage(new MyEmojiMessage(8, 91, network.getPerson(1), network.getPerson(6)));
       for (int i = 0; i < 8; i++) {
           network.sendMessage(i + 1);
      }
       assertEquals(4, network.deleteColdEmoji(1));
       assertEquals(true,network.containsEmojiId(91));
       network.deleteColdEmoji(3);
       assertEquals(false,network.containsEmojiId(91));
  }

容器选择和使用的经验

  1. 避免直接使用定长数组。

  2. 根据需求进行容器的选择,如果对象是通过ID来进行大部分操作,那么使用HashMap进行存储,如果对象如Person.messages,需要从头取出,从尾放入等操作,则使用ArrayList进行存储。适当的情景下也可使用Hashset来做集合的不重复性。

  3. 不确定要用什么的情况下,似乎还是用HashMap比较靠谱

性能问题

本次作业会出现的性能问题主要集中在容器的选择,qbs的算法,ageMean,ageVar等的算法。

对于容器的问题,我的避免超时的方法是采取了适合的容器如HashMap

我在第二次作业中大面积出现了性能问题(估计能踩的坑我都踩了)

  1. qbs的算法采用了规格描述的算法直接进计算,于使我对其进行了并查集算法的修改,在addPerson和delPerson的时候就对拥有同一个根节点的节点构成一个集合。(一开始还写了DFS,慢的要死就算了,还写了一堆BUG,忙一下午,服了。)

    private final HashMap<Integer, Integer> parent = new HashMap<>();
   private final HashMap<Integer, Integer> rank = new HashMap<>();


private int find(int id) {
       if (parent.get(id) != id) {
           parent.put(id, find(parent.get(id)));
      }
       return parent.get(id);
  }
   
   private void union(int id1, int id2) {
       int p = find(id1);
       int q = find(id2);
       if (p == q) {
           return;
      }
       if (rank.get(p) < rank.get(q)) {
           parent.put(p, q);
      } else if (rank.get(p) > rank.get(q)) {
           parent.put(q, p);
      } else {
           parent.put(p, q);
           rank.put(q, rank.get(q) + 1);
      }
  }

 

  1. ageMean,ageVar等的计算,起初我的计算直接采用了每次调用方法是从头开始计算的实现,结果导致每次计算要消耗大量的CPU超时,导致了CTLE,后改为在进行addperson的时候直接进行累加加和的操作,在询问ageMean的时候可以直接进行返回。

    private int ageSum = 0;
   private int ageMean = 0;
   private int ageVar = 0;
   private int valueSum = 0;
   @Override
   public void addPerson(Person person) {
       people.put(person.getId(), person);
       ageSum += person.getAge();
       ageMean = ageSum / people.size();
       ageVar = 0;
       for (Person p : people.values()) {
           ageVar += (p.getAge() - ageMean) * (p.getAge() - ageMean);
           if (p.isLinked(person)) {
               valueSum += p.queryValue(person) * 2;
          }
      }
       ageVar = ageVar / people.size();
  }
   @Override
   public void delPerson(Person person) {
       people.remove(person.getId());
       if (people.isEmpty()) {
           initialData();
           return;
      }
       ageSum -= person.getAge();
       ageMean = ageSum / people.size();
       ageVar = 0;
       for (Person p : people.values()) {
           ageVar += (p.getAge() - ageMean) * (p.getAge() - ageMean);
           if (p.isLinked(person)) {
               valueSum -= p.queryValue(person) * 2;
          }
      }
       ageVar = ageVar / people.size();
  }

 

架构设计

除了各个对象的HashMap以外,network维护一个并查集,group维护多个基本数据,在addPerson的能操作时进行各个数据的更新。

不知道写什么了,这单元挺搞心态的,对自己写BUG的能力又有了新的认识,因为自己时间不够能力不足,总做不好测试这一块,我也不知道怎么办,就尽力别写bug吧。不讲丧气话,这单元学到了JML规格相关知识,好像还是挺“严谨”的,如果以后工作或者什么遇到了,应该挺受益的,不过有一说一,我是不会愿意去自己写这个JML的,如果有中文版的JML能几句话讲清楚,那没准可以试试。

 

标签:总结,network,ageVar,int,person,BUAAOO,new,getPerson,单元
来源: https://www.cnblogs.com/acsoto/p/14824896.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有