301
社区成员
发帖
与我相关
我的任务
分享目录
2. 对单元测试、功能测试、集成测试、压力测试、回归测试的理解
三、分析作业中出现的性能问题及其修复情况,谈谈自己对规格与实现分离的理解
本单元较前两个单元还是比较简单的,比较难的还是在于算法,要维护变量,不能完全照着规格写,不然就会超时。
黑盒测试就是把软件(程序)当作一个有输入与输出的黑匣子,它把程序当作一个输入域到输出域的映射,只要输入的数据能输出预期的结果即可,不必关心程序内部是怎么样实现的。白盒测试又叫透明盒测试,它是指测试人员了解软件程序的逻辑结构、路径与运行过程,在测试时,按照程序的执行路径得出结果。白盒测试就是把软件(程序)当作一个透明的盒子,测试人员清楚地知道从输入到输出的每一步过程。而我们的作业就是黑箱测试,我们只关心输出,不关心内部的具体实现。
对于数据构造,我们必须要考虑全面,所有可能发生的情况都要考虑进去,在数据要求范围内随机生成,数量要大从而包括的情况多,每次测必须要测到一些极端情况,比如一些临界情况,一般这种情况的行为比较特殊,容易被忽略。
第一次作业:在第一次作业中,我们重点维护blocksum和triplesum,blocksum就是在加人时加1,加边删边时看两点是否连通来判断,triplesum就是在加边删边时看原先有几个点连了这两个点来计算。在第一次作业我们还要引入并查集来方便查看两个点是否连通,从而iscircle很方便。但是在删边时需要重建并查集,可以看删边后连不连通来决定是否重建,如果两个人不连通了,就需要重建。主要方法就是用dfs,将从id1能到达的所有点的父亲变为id1,如果不连通,就将从id2能到达的所有点的父亲变为id2,重建就完成了。
第二次作业:我们在这一次作业中维护了bestid、valuesum、agemean。首先agemean就是加人删人是维护即可。bestid在加边,删边时需要维护,就是与原先的bestid比较,看谁更好,注意的是如果跟bestid的value减少时需要重新遍历寻找bestid。最难的是valuesum,有的大佬使用treeset来给熟人排序,查询时从头部取出即可, 这个方法需要自己写比较方法来给熟人排序,插入时有复杂度,取出来很方便。而我还是动态维护,在加人,删人,加边,删边时动态维护,重点是在加边、删边时,我们可以找到两个人的共同熟人,遍历这个共同熟人的tag来找到同时有着两个人的tag来维护valuesum。还有就是查找最短路径用bfs即可达到要求。
第三次作业:这次作业比较简单,跟优化有关系的地方比较少。每个人的信息用linkedlist来存,这样在sendmessage和Receivemessage是插入与删除操作较方便。还有就是在deletecoldemoji和clearnotices需要用迭代器实现边遍历便删除。
总结来说,我们需要选择合适的数据结构来减少复杂度,比如hashmap,treemap,linkedlist。 其次就是一些量我们需要动态维护,保证在查询时复杂度是O(1),在它改变的时候再重新计算。 最后就是我们认为将复杂度优化到O(n)以下就行了,不用花大量时间在算法上。
我是按照上文那样优化的,这三次作业没有出什么问题。不过我在后面才发现我在维护triplesum时每次进入加边删边方法时都会无脑的循环所有人来找到同时与这两个点相连的点,其实可以不用无脑的循环的,在add时只有加边前两个点连通时才需要循环,modify时只有删边后两个点连通时才需要循环,这又会优化速度。
实现规格与实现的分离通常通过接口和实现类的方式来实现。接口定义了系统的规格,包括了系统的行为和接口约定;而实现类则负责具体实现接口定义的功能。这样的设计使得系统更易于扩展和维护,并且降低了系统内部组件之间的耦合度。往往按照规格实现性能会很差,因为规格只是介绍了这个方法的行为,数据的约束以及方法的副作用,我们实现可以在满足规格的基础上做性能上的优化。
首先就是对于pure,我们要检验调用对象在调用方法前后不会发生改变,其次我们要保证ensure里的内容正确,还有就是对于异常的行为,我们要保证对于异常的处理正确,对于assignable之外的变量以及\not_assigned的变量保证不做改变,最后保证调用方法后的返回值要与用测试数据按照规格计算出来的结果一致。完全按照JML规格写的测试代码肯定是对的,但是当测试数据比较复杂时,测试起来性能就会很差。
本单元学习到了JML这种语言,了解了如何用JML写规格,如何通过JML来实现方法,如何做到规格和实现相分离。JML虽然感觉比较麻烦冗长,看的时候感觉太繁琐,但是在以后大型项目中,尤其是要求精准度比较高的项目中,应该会发挥比较大的作用,所以现在学了对以后还是好的。这一单元相较以前而言还是轻松的,希望下一个单元也能这么轻松吧。