第一次个人编程作业

作业github链接

一、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划
· Estimate · 估计这个任务需要多少时间 60 90
Development 开发
· Analysis · 需求分析 (包括学习新技术) 120 180
· Design Spec · 生成设计文档 20 10
· Design Review · 设计复审 10 10
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 5 5
· Design · 具体设计 30 40
· Coding · 具体编码 720 800
· Code Review · 代码复审 200 400
· Test · 测试(自我测试,修改代码,提交修改) 100 150
Reporting 报告 120 150
· Test Repor · 测试报告 20 20
· Size Measurement · 计算工作量 10 10
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 30 30
· 合计 1445 1815

二、计算模块接口

  • 计算模块接口的设计与实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?说明你的算法的关键(不必列出源代码),以及独到之处。

    答:本次编程作业代码主要分为六个类:主调度类、检测类、读文件类、写文件类、字型判断工具类、拼音转换工具类
    • 读文件类解析好的敏感词集合以及待检测文本列表后,交由检测类进行检测处理。接着检测类在字型判断类和拼音转化类的配合下,过滤敏感词,并将检测结果按输出格式存入列表中。之后将结果列表交给写文件类,完成输出任务
    • 算法关键:关键方法MatchSensitiveWordMap()生效的基础是DFA算法以及根据其构建出的DFA敏感词搜索树。但我当时了解到的DFA算法只能做到无变体敏感词的检测,无法识别经过拼音、英文大小写替换、插入无意义字符等的功能。因此,我在UpdateSensitiveWordMap()方法中构建DFA搜索树时,还额外构建了拼音-汉字的映射集合以及英文字母大写-小写的映射集合。接着在MatchSensitiveWordMap()中原DFA算法里添加了多个附加判断(多重的条件判断),并在每轮检索过程中累加形成原敏感词字符串(如“傻子”)以及变体敏感词字符串(如:“傻&……&zi”)。
  • 计算模块接口部分的性能改进。记录在改进计算模块性能上所花费的时间,描述你改进的思路,并展示一张性能分析图(由VS 2019、JProfiler或者Jetbrains系列IDE自带的Profiler的性能分析工具自动生成),并展示你程序中消耗最大的函数。

    答:下面先放一张用JProfiler工具生成的性能分析图。
    • 说实在话,我万万没想到是第三方库的方法消耗最大。不过抛开第三方库函数不说,我自己写的程序中,MatchSensitiveWordMap()方法不出意料地登顶消耗第一的榜首。原因在于这个方法是在基础DFA算法上拓展起来的,但是由于一开始设计不周全,导致写出来的代码耦合度很高,没法将各个检测模块分离开来。不仅代码冗余度较大,而且存在多重判断,代码繁杂,debug困难。
    • 改进的思路就是直接将不同模式的过滤直接分成不同类的功能模块,在一个调度类里写一个循环,然后在循环体里必要的地方设置不同模式的敏感词检测。(目前暂时没有时间重构代码,接下来将会考虑这方面,同时补全剩余未实现的检测功能)
  • 计算模块部分单元测试展示。展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路。并将单元测试得到的测试覆盖率截图,发表在博客中。

    答:项目部分单元测试代码(代码如下,该单元测试直接测试核心的敏感词匹配功能

    @Test
    public void test1(){
        FileReader fileReader =new FileReader();
        ArrayList<String> ans = fileReader.readCheckedFile("D:\\javatest\\answer.txt");

        BasicSensitiveWordChecker basicSensitiveWordChecker = new 
        BasicSensitiveWordChecker(fileReader.readCheckedFile("D:\\javatest\\a.txt"),fileReader.readSensitiveWordFile("D:\\javatest\\b.txt"));
        ArrayList<String> testResult = basicSensitiveWordChecker.FindSensitiveWord(0);
        Assert.assertEquals(ans,testResult);
        }
     }

下面是单元测试得到的测试覆盖率截图

关于测试函数的说明

  • 在answer.txt文件中存有事先准备好的正确检索结果,通过读文件类方法readCheckedFile()读入列表
  • 接着分别调用读文件类的readCheckedFile()方法和readSensitiveWordFile()方法分别将a.txt中的待测文本以及b.txt中的敏感词库读入,并初始化检测类
  • 调用检测类的检测方法得到一个结果列表,将该列表与最开始得到的正确结果列表相比较判断是否相同,相同则通过测试。

测试文件answer.txt、a.txt、b.txt的截图如下所示

构造测试数据的思路
首先我的代码还未实现部首偏旁拆分检测以及拼音缩写替换检测。因此我就主要针对剩下几种已经实现的过滤功能设计测试数据。尽量让一个敏感词变体具有多种变体形式混杂的特点,这样才能达到真正的代码测试效果。

  • 计算模块部分异常处理说明。在博客中详细介绍每种异常的设计目标。每种异常都要选择一个单元测试样例发布在博客中,并指明错误对应的场景。

    答: 本代码内主要处理的异常为io异常
    • 读文件类异常处理
      该异常主要是防止读文件类访问不存在的文件路径

      如下图所示,D:\javatest\d.txt的文件路径不存在,程序就会报错,报告找不到文件

    • 写文件类异常处理
      该异常主要是防止写文件类访问不存在的文件路径

      如下图所示,F:\javatest\d.txt的文件路径不存在,程序就会报错,报告找不到文件

三、心得

  • 不要磨洋工

    • 这次作业本来应该有充足的时间来设计和实现功能的,但由于我对作业的难度预期不足,以及我自身的懒散心态,导致作业完成进度一拖再拖,这也导致了后面几天真变成了老师所说的ddl驱动了。没必要,真的没必要。
  • 设计与日常并非泾渭分明

    • 回想从前,已经不止一次写过编程大作业了。在这一过程中,我不知为何,自然而然有了这样的感触:开发一样产品并非一日之功,对于产品设计的思考,应该能和日常生活交织在一起。细想起来,确实应该如此。毕竟,有的灵感,是不可能在一两个小时的枯坐中产生的。睡觉前想,洗澡时想,吃饭时想,或许新颖有趣的想法就能应运而生。
  • 增强使用搜索引擎的能力和学习积极性

    • 在这次的开发过程中,我很惊奇的发现,有些人的学习能力非常强,他们能从网上快速筛查出自己想要的知识,并迅速消化同时付诸实践。原因无非有二:首先他们能熟练使用搜索引擎获取到他们想了解的东西,其次是他们对新知识的渴望和热情,促使他们很快理解知识并很好地运用于实践中。
  • 多多与人讨论交流

    • 刚刚也说了,身边有很多学习能力超强的“巨佬”,我的学习能力没那么强,那我就“抱大腿”啊!在他们的交流中,总能发现一些常人发现不到的新颖的东西,这也是我们不断提升自己所必须具备的,没法像他们那样像团火一样发光那么至少靠近一点让自己不那么暗淡,再进一步,或许还能点燃自己呢。
posted @ 2021-09-16 22:15  枭魈  阅读(100)  评论(0编辑  收藏  举报