第一次个人编程作业
作业概述
这个作业属于哪个课程 | 班级链接 |
---|---|
这个作业要求在哪里 | 作业链接 |
这个作业的目标 | 通过个人变成能力来实现论文查重,学习使用PSP表格以及git提交规范 |
一、个人github仓库
二、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 30 |
· Estimate | · 估计这个任务需要多少时间 | 200 | 300 |
Development | 开发 | 200 | 200 |
· Analysis | · 需求分析 (包括学习新技术) | 100 | 120 |
· Design Spec | · 生成设计文档 | 15 | 20 |
· Design Review | · 设计复审 | 25 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 20 | 20 |
· Design | · 具体设计 | 20 | 25 |
· Coding | · 具体编码 | 20 | 30 |
· Code Review | · 代码复审 | 30 | 30 |
· Test | · 测试(自我测试,修改代码,提交修改) | 20 | 30 |
Reporting | 报告 | 30 | 50 |
· Test Repor | · 测试报告 | 30 | 40 |
· Size Measurement | · 计算工作量 | 30 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 40 | 50 |
· 合计 | 800 | 995 |
三、需求分析
题目:论文查重
描述如下:
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。
原文实例:今天是星期天,天气晴,今天晚上我要去看电影。
抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:
从命令行参数给出:论文原文的文件的绝对路径。
从命令行参数给出:抄袭版论文的文件的绝对路径。
从命令行参数给出:输出的答案文件的绝对路径。
我们提供一份样例,课堂上下发,上传到班级群,使用方法是:orig.txt是原文,其他orig_add.txt等均为抄袭版论文。
注意:答案文件中输出的答案为浮点型,精确到小数点后两位。
四、计算模块接口的设计与实现过程
1.接口设计
类名 | 解释及作用 |
---|---|
PaperCheckMain | main方法所在的类 |
HammingUtils | 用于计算海明距离的类 |
SimHashUtils | 用于计算SimHash值的类 |
TxtIOUtils | 用于读写txt文件的工具类 |
ShortStringException | 用来处理文本内容过短的异常类 |
2.关键函数流程图
五、计算模块接口部分的性能改进
1.改进计算模块性能的耗时记录
整个函数耗时
2.描述改进思路
通过各种工具或手段,初步定位性能瓶颈点,通过各种工具或手段,初步定位性能瓶颈点,具体性能优化为getSimHash函数。
3.性能分析
3.1性能测试图
由图知,整个函数花费14438ms,其中计算海明距离花费时间最久,为14436ms
3.2方法调用情况
4.耗时最大的函数展示
此函数由于调用了HanLP,因此耗时最大。
点击查看代码
public static String getSimHash(String str) {
// 用数组表示特征向量,取128位,从 0 1 2 位开始表示从高位到低位
int[] v = new int[128];
// 1、分词
List<String> keywordList = HanLP.extractKeyword(str, str.length());//取出所有关键词
// hash
int size = keywordList.size();
int i = 0;//以i做外层循环
for (String keyword : keywordList) {
// 2、获取hash值
StringBuilder keywordHash = new StringBuilder(getHash(keyword));
if (keywordHash.length() < 128) {
int dif = 128 - keywordHash.length();
for (int j = 0; j < dif; j++) {
keywordHash.append("0");
}
}
// 3、加权、合并
for (int j = 0; j < v.length; j++) {
if (keywordHash.charAt(j) == '1') {
v[j] +=1;
} else {
v[j] -= 1;
}
}
i++;
}
六、计算模块部分单元测试展示
1.测试函数的说明
点击查看代码
// 核心类测试
class SimHashUtilTest {
@Test
void getHash() {
System.out.println(SimHashUtil.getHash("213123"));
}
@Test
void getSimHash() {
System.out.println(SimHashUtil.getSimHash("124123123"));
}
@Test
void getHammingDistance() {
}
@Test
void getSimilarity() {
String simHash1 = SimHashUtil.getSimHash("hasdoihasiodhoiasd");
String simHash2 = SimHashUtil.getSimHash("hasdoihasiodhoiasd");
System.out.println(SimHashUtil.getSimilarity(simHash1,simHash2));
}
2.测试数据的思路构建
功能测试的测试思路:测试每个部分的功能是否能达到预期结果
2.1模块接口测试
后台的数据集成在测试框架中,检查测试代码块之间的接口, 和数据的传输等问题。
2.2执行测试用例
利用下发的测试用例,执行用例将所有需求跑一遍,确认测试需求是否有功能点遗漏,查漏补缺。
3.测试自动化
进入代码运行直接出结果在ansAll.txt中
4.测试覆盖率
七、计算模块部分异常处理说明
1. 异常设计目标的介绍
当文本长度小于200时,文本过短无法提取除关键字进行对比,抛出一个文本过短异常
设计目标:为防止文本长度不满足要求而设置的规范长度异常
对应场景:当读取的文本内容少于300字符时将抛出。