OO第三单元总结

OO第三单元总结

设计策略

首先根据JML规格定义需要的属性,再理解各个方法的目的,最后根据理解来完成各个方法。对于方法的实现,需要先大致理解方法实现了怎样的功能,而不是直接根据规格就开始写代码,在明白方法规格的具体含义以后,要明确进入各个分支的前提条件,然后是每个分支造成了怎样的结果,最后是检查是否没有出现遗漏。在写代码的过程中,一般是先完成所有异常的抛出,再根据异常所避免的情况进行下一分支代码的实现。

测试策略

由于本单元中测数据极为简单,对于代码的评测极具迷惑性,导致不进行良好的测试可能导致强测翻车。并且,测试需要保证自己对规格的理解没有出现偏差,否则可能出现认为错误程序的输出正确的情况。在本单元的测试过程中,针对异常的测试只需要编写一些边界数据即可,针对方法功能的测试主要是确保测试数据全面,对于每种方法以及有关联性的方法组合都进行测试。在本单元的测试中只是编写了一些数据点来测试各方法的功能,且有几个细节上的错误没有测到。

容器选择和使用

在本单元作业中容器是比较多的,大部分选择了Map类容器,用于id与对象的对应,此外关于emoji的容器为List类,是因为规格规定了其通过两个List进行id与相应heat值的对应。总之还是根据规格选择需要的容器,不匹配规格而去选择另外的容器可能导致代码不适合迭代。

例如,在queryNameRank方法的实现过程中,我首先的想法是选择TreeMap容器实现nameMyPerson的映射,并且只需要使用for循环遍历即可通过TreeMap的特性实现Rank的计算,但是在具体测试过程中发现,虽然这样的做法在意义上与规格所要实现的功能相近,但是并不能很便利地完全符合规格,因此在容器的选择和使用上要以规格为准。

性能问题分析

本单元的显著特点就是需要进行大量属性的缓存,并设置相应的flag,在与属性关联的方法未被调用时再询问该属性,直接返回缓存作为输出。只有这样才能避免频繁计算导致的性能过低问题。在实现过程中针对每个能够缓存的属性都进行了缓存,例如meanvarqbssim等。

其中针对var的计算需要注意/运算,因此将公式展开,缓存平方和ageSquarSumn个平均值平方和persons.size()*ageMean*ageMean,和ageSum,计算时ageVar=(ageSquarSum+meanSquar-2*ageMean*ageSum)/persons.size()避免整除带来的bug。

针对sim中由于计算最短路径采用的算法时间复杂度为O(n²),因此第三次强测有一个数据点性能过低,这是算法实现上的问题。

此外还可能存在的性能问题是qbsisCircle的计算需要使用并查集,能够极大减少查询的时间消耗。通过在每个Person对象中存储一个BiggestBrother表示该成员的根成员,在每次addRelation时遍历修改相关Person的,对于一个Person数组,遍历一遍即可知道qbs的数量以及是否isCircle

架构设计

本单元的作业架构完全根据JML规格实现,将官方包提供的类或接口实例化,同时建立正确的继承或实现关系。但在实现过程中基本上没有自主建立的类之间的继承关系,实际实现上造成了代码冗余部分过多,复用处能够通过继承关系简化。

针对部分需要从NetworkGroup再到Person进行询问的方法,在代码实现过程中尽量地一层层调用名称类似的方法,实现代码耦合降低。此外需要实现异常类的设计,针对本次异常类的实例化,需要定义static属性来实现不同类抛出异常时都能够进行计数。总之,本单元的架构设计还是比较简洁。

posted @ 2021-05-30 16:03  Nya0  阅读(57)  评论(0编辑  收藏  举报