BUAA OO Unit3 单元总结:规格化设计

BUAA OO Unit3 单元总结:规格化设计


前言

第三单元的主题是“规格化设计”,主要目的是基于JML规格语言进行代码实现。很像是看图说话,难度上并不大,但是规格更多的是一种对结果的要求,他对过程并不怎么关心。
本单元实现的是一个社交网络,一个图,代码优化真的很重要(笔者就是太懒了,写完就扔在那了)

本单元的测试过程

黑箱测试 & 白箱测试

  • 黑箱测试(Black Box Testing)是指在不考虑程序内部结构和工作原理的情况下,对程序进行测试。测试人员只需要关注输入和输出,以及程序对输入的响应和处理结果是否符合预期。黑箱测试目的是验证程序是否满足需求和规格说明书中的所有要求。

  • 白箱测试(White Box Testing)是指在了解程序内部结构和工作原理的基础上,对程序进行测试。测试人员需要检查程序的代码、结构、算法等信息,以便找出潜在的错误和缺陷。白箱测试通常由开发人员或专业的测试人员执行,其目的是发现程序的内部问题,提高程序的质量和可靠性。

单元测试、功能测试、集成测试、压力测试、回归测试

  • 单元测试(Unit Testing)是指对软件中的最小可测试单元进行测试,如函数、方法、类等。单元测试目的是验证代码是否符合设计要求,检查代码是否存在错误或缺陷。

  • 功能测试(Functional Testing)是指对软件的功能进行测试,以保证软件满足用户需求和规格说明书中的要求。功能测试目的是验证软件是否能够正确地完成各项功能。

  • 集成测试(Integration Testing)是指将多个单元或模块组装在一起进行测试,以确保它们能够正确地协同工作。集成测试目的是验证软件的各个部分是否能够正确地交互和协作。

  • 压力测试(Stress Testing)是指对软件进行负载测试,以测试其在高负载下的性能和稳定性。压力测试目的是模拟实际使用情况下的负载,检查软件是否能够承受并处理大量的数据和请求。

  • 回归测试(Regression Testing)是指对软件进行重新测试,以确保在修改软件后没有引入新的错误或缺陷。回归测试目的是验证软件的修改是否影响了原有的功能,并且确保软件的整体质量和稳定性没有受到影响。

测试工具

本单元还是延续自动化测试的传统。因为对于每个指令都有唯一正确的输出,所以使用 “对拍+文本比较” 的方式对正确性进行验证


作业分析

用第三次作业做总览即可。
homework3

结构设计

  1. Hashmap
    观察到查询的次数是使用频率最高的函数,为了减少查询的时间损耗,我选择了用哈希表。

算法设计

几个重点考察数据结构和算法的函数

  1. DFS
  • queryBlockSum(): 求图里的连通分支数
    public static void dfs(Person person, HashSet<Person> visited) {
            visited.add(person);
            HashMap<Integer, Person> friends = ((MyPerson) person).getAcquaintance();
            for (Integer id : friends.keySet()) {
                Person connected = friends.get(id);
                if (!visited.contains(connected)) {
                    dfs(connected, visited);
                }
            }
        }
  • queryTripleSum():求图里的三角形
    三重循环。这个函数和isCircle是我觉得我失误蛮大的一个地方,也是我比较后悔没有做好的地方。其实如果能在添加新点和新边的时候维护一下点的连通分支所在会降低很多时间复杂度。类似并查集,但是可以没有并查集那么复杂。
  1. Dijkstra
  • isCircle(id1, id2):求两点之间是否有通路
    这个函数其实不需要跑完完整的Dijkstra,因为他不需要最小,只要他有就行了,所以应该及时退出这个函数,但是非常可惜,本人又在马后炮 😕
  • queryLeastMoments(id):求过目标点的最小环
    这个函数的思路基本上就是,删边后的Dijkstra,比如求 Ui和Uj 的最小环,那么就先删除 Ui和Uj 之间的边,再用dijkstra,求出Path: Ui => Uj
    public int getMinCircle(HashMap<Integer, Person> people, int id) {
        // 求出与目标点相连的所有点的最小环
        for (int i : friendKeys) {
            Person friend = friends.get(i);
            int value = people.get(id).queryValue(friend);
            ((MyPerson) person).tempDelete(i);
            ((MyPerson) friend).tempDelete(id);
            leastLength.put(i, dijkstra(people, id, i));
            ((MyPerson) person).addAcquaintance(friend, value);
            ((MyPerson) friend).addAcquaintance(person, value);
        }
        // 把路径长 + 边长得到最小环长
        Person origin = people.get(id);
        int min = Integer.MAX_VALUE;
        for (int i : leastLength.keySet()) {
            Person connected = people.get(i);
            if (leastLength.get(i) != Integer.MAX_VALUE) {
                if (leastLength.get(i) + origin.queryValue(connected) < min) {
                    min = leastLength.get(i) + origin.queryValue(connected);
                }
            }
        }
        return min;
    }

以上几个函数,其实还可以设计一个脏位,如果有有效的边/点的变动,再重新计算,因为这几个函数时间复杂度都挺高的,所以如果能减少计算量那么对性能也有不小的提升。


规格与实现分离

规格与实现分离是一种软件开发中的设计原则,它强调在软件开发过程中要将规格和实现分离开来。具体来说,规格是指软件需要满足的功能需求和性能要求,而实现则是指将这些需求转化为实际的软件代码。

规格与实现分离的优点在于它可以使软件开发更加模块化和可维护。通过将规格和实现分离开来,我们可以将软件的各个部分独立开发,测试和维护。这不仅可以提高软件的可靠性和稳定性,还可以减少软件修改时的风险和成本。


OKTest

OKTest就是一个检查器,检查你写的这个函数是不是满足了JML所有的要求。

public int okTest(int limit,
                  ArrayList<HashMap<Integer, Integer>> beforeData,
                  ArrayList<HashMap<Integer, Integer>> afterData,
                  int result) {
        HashMap<Integer, Integer> beforeEmoji = beforeData.get(0);
        HashMap<Integer, Integer> afterEmoji = afterData.get(0);
        HashMap<Integer, Integer> beforeMessage = beforeData.get(1);
        HashMap<Integer, Integer> afterMessage = afterData.get(1);

        if (!rule1(limit, beforeEmoji, afterEmoji)) { //检查了是不是满足了第一条要求
            return 1;
        }
        if (!rule2(beforeEmoji, afterEmoji)) {
            return 2;
        }
        if (!rule3(limit, afterEmoji.size(), beforeEmoji)) {
            return 3;
        }
        //……………………
        return 0;
    }

虽然在这个函数设计可能有更简便的方法,但是我认为我这种写法会更明确 😃


心得体会

其实难度上比前两个单元都小,但是我完成的比前两个单元都差。第三单元横跨了本人的假期、生病受伤期,我大部分时间都是很快的写完,因为弱测和中测都是小图,而且测试强度不高,基本上公测交一次都过了,我会比较怠惰,甚至懒得对拍,我自我检讨。这也导致我强测寄的比较严重 😦
其实看我的作业分析就能看出我全都是马后炮,当事人现在就是非常后悔没好好写代码TT,如果有学弟学妹看到我的blog,这篇blog没有什么能辅导你的,只有一些心态上的注意事项。

别懈怠!!!!

总的来说,这是一个比较简单的单元,这个单元的作业完成它更多是对设计方面的理解,了解规格和实现分离带来的开发、测试、维护优势。也是让我更清晰设计与开发分离的方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值