个人项目
软件工程 | <网工1934> |
---|---|
作业要求: 1.在 Github 仓库中新建一个学号为名的文件夹。 2.在开始实现程序之前,在 PSP 表格记录下你估计在程序开发各个步骤上耗费的时间,在实现程序之后,在PSP表格记录下你在程序的各个模块上实际花费的时间。 3.语言不限,并将编译好的程序发布到 Github 仓库中的 releases 中。 4.提交的代码要求经过 Code Quality Analysis 工具的分析并消除所有的警告。 5.完成项目的首个版本之后,请使用性能分析工具Studio Profiling Tools来找出代码中的性能瓶颈并进行改进。 6.使用Github来管理源代码和测试用例,代码有进展即签入Github。 7.使用单元测试对项目进行测试,并使用插件查看测试分支覆盖率等指标;写出至少10个测试用例确保你的程序能够正确处理各种情况。 |
<作业要求> |
作业的目标: 设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。 |
1. PSP表格
*PSP2.1* | *Personal Software Process Stages* | *预估耗时(分钟)* | *实际耗时(分钟)* |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 1210 | 1590 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 300 | 420 |
· Design Spec | · 生成设计文档 | 120 | 100 |
· Design Review | · 设计复审 | 40 | 20 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 40 | 20 |
· Design | · 具体设计 | 200 | 300 |
· Coding | · 具体编码 | 300 | 420 |
· Code Review | · 代码复审 | 100 | 60 |
· Test | · 测试(自我测试,修改代码,提交修改) | 100 | 180 |
Reporting | 报告 | ||
· Test Repor | · 测试报告 | 30 | 20 |
· Size Measurement | · 计算工作量 | 30 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 50 | 30 |
· 合计 | 1210 | 1590 |
2. 计算模块接口与实现过程
2.1 程序实现类
主类:
Application ,包含main方法,可以接收指定参数,传递给Document类进行文件的输入输出,并调用其他工具类中的方法实现程序的运行。
工具类:
CuttingWordsUtil,中文工具类,具有中文分词的方法。
DocumentUtil,文件工具类,控制文件的输入输出。
SimpleCommonWords,简单共有词计算类,通过简单共有词算法对两个文档的相似度进行计算。
测试类:
TestCoverage,测试各模块的功能是否正常。
项目结构:
项目流程:
2.2 关键函数的分析与实现
实现查重的关键点在于分词函数和相似度算法
在开始编写程序前,查询了很多关于分词器和相似度算法的资料,参考了以下文章
中文分词器的基本原理和简单实现
11大Java开源中文分词器的使用方法和分词效果对比
文本相似度算法
Java分布式中文分词组件 - word分词
经过考虑后,选择word分词器和简单共有词算法来完成本次设计。
简单共有词算法简单流程如下:
String1: 我读过那么多故事。
String2: 我听过那么多故事。
1) 分词
String1: [我, 读过, 那么多, 故事]
String2: [我, 听过, 那么多, 故事]
2) 分别计算总字符数
words1 = 4
words2 = 4
3) 计算共有词的总字符
commonwords = 3
4) 计算相似度
选取长度最长的字符数为分母,共有词的总字符为分子
result = 3 / 4 = 0.75
这个算法的思路比较直观,易于理解其基本原理,直观的讲就是首先统计需要比较相似度的两篇文档的总字数,其次分别统计文档中共有词语的总字符数,第三用共有词语除以最长文档的字数得到相似度衡量的数值。
3. 计算模块接口部分的性能改进
第一版程序耗时相当多,需要将近40秒的运行时间
经过研究后发现是由于分词器自带的控制台输出日志占用的时间太多了,于是进行了改进
第二版程序,将依赖中的分词器版本下调到1.2,运行速度明显提升很多
可以看出占用最多的是分词器查询字典函数调用
但是日志输出还是耗费了很多时间,于是又去寻找禁用日志输出的方法
第三版禁用了日志输出,输出时间再次减少
4. 计算模块部分单元测试展示
4.1 CuttingWordsUtil类测试
测试结果:
可以看出,word分词器可以识别一些特殊符号并同样划分出来
4.2 SimpleCommonWords类测试
测试结果:
当两个句子为空串时,输出为NaN,需要做异常处理
4.3 代码覆盖率
5. 模块部分异常处理说明
在单元测试模块中可以知道,当两个字符串为空串时输出NaN,需要进行异常处理
在Application类中添加判断,如果都为空则输出提示信息并结束程序
6. 项目程序功能测试
当原文件和抄袭论文文件为UTF-8编码格式时测试代码为:
java -Dfile.encoding=utf-8 -jar PaperCheck.jar D:\tests\orig.txt D:\tests\orig_0.8_dis_10.txt D:\tests\result1.txt
当原文件和抄袭论文文件为ANSI编码格式时测试代码为:
java -jar PaperCheck.jar D:\tests\orig.txt D:\tests\orig_0.8_dis_10.txt D:\tests\result1.txt
此处的SLF4J提示为禁用日志输出的结果,不影响程序正常运行
运行结果文件: