第二次作业-个人项目

个人项目
Github链接:https://github.com/Linee128/paper-checker-system

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/homework/13468
这个作业的目标 完成第一个个人项目,熟悉项目开发流程

一、PSP表格

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

二、模块接口的设计与实现过程
1、模块划分
本系统采用模块化设计,共包含3个核心类和1个测试类:
PaperChecker(主程序类):程序入口,负责协调文件处理和相似度计算流程
FileHandler(文件处理类):封装文件读写操作,提供统一的文件访问接口
SimilarityCalculator(相似度计算类):实现编辑距离算法,提供文本相似度计算功能
PaperCheckerTest(测试类):验证各模块功能正确性
2、类与类的关系
image
PaperChecker是主控类,依赖于FileHandler和SimilarityCalculator。FileHandler和SimilarityCalculator各自独立,遵循单一职责原则。PaperCheckerTest测试时可直接调用FileHandler、SimilarityCalculator,也能间接验证PaperChecker。
3、关键函数流程图
image
4、关键算法
编辑距离计算法
image
先计算两个文本的编辑距离(将 text1 转换为 text2 所需的最少插入、删除和替换操作次数),再进行归一化处理:similarity = 1 - editDistance / maxLength
(其中 maxLength 是两个文本长度的最大值),确保相似度在 [0.0, 1.0] 范围内。
5、独到之处
(1)空间优化的编辑距离算法:采用滚动数组替代传统的二维数组,将空间复杂度从 O (n*m) 降至 O (min (n,m)),特别适合处理大文本比较。
(2)完善的边界处理:妥善处理 null 和空字符串输入,确保相似度计算结果严格在 [0.0, 1.0] 范围内;异常处理机制保证文件操作的稳定性。
(3)接口设计的高内聚低耦合:文件操作与算法计算完全分离,便于单独扩展;统一的异常处理机制,便于上层调用。
三、性能分析与改进
性能分析图
软工11
软工111
缺点:String、byte[]、HashMap/节点、int[] 的实例数极高,表明存在大量短寿命对象和集合节点;内存使用稳定但偏高(~230MB),GC有波动但无严重Full GC,说明瓶颈是大量对象分配与内存使用而不是单方法CPU瓶颈。
改进:(1)MinHash:用固定长度(例如 128 或 256)的一组哈希签名近似表示一篇文档或段落的 n-gram 集合。签名长度远小于原始集合大小,显著减小内存(减少 HashMap/String 节点与 byte[] 数量)。
(2)LSH(局部敏感哈希):把 MinHash 签名分成若干 band,快速把可能相似的文档对筛出来,避免在候选空间上做昂贵的精确比较(避免 O(N^2) 全比较)。
(3)可变/多尺度 n-gram 窗口 k:小 k(比如 3)能捕获局部相似(更敏感,对抄袭改写鲁棒);但会产生更多 n-gram(集合更大);大 k(比如 7)更保守,集合更小,对任意改变更敏感;使用多尺度(例如同时用 k=3、k=5)对结果进行融合,能在速度与准确度之间取得平衡:先用小 k 的 MinHash + LSH 快速召回候选,再用大 k 或精确相似度(如 Jaccard 或 Levenshtein)对候选复核。

四、部分单元测试
测试覆盖率
image
image
测试样例说明

测试函数 测试目的 说明
testCalculateSimilarityWithSameText 完全相同文本检测 两个字符串内容完全一致,验证相似度计算函数返回 100%(即相似度值为 1.0)。
testCalculateSimilarityWithDifferentText 完全不同文本检测 原文和待检测文本内容无关联,验证相似度计算函数返回较低相似度(小于 0.8)。
testCalculateSimilarityWithModifiedText 部分相似文本检测 原文经过部分改写,存在部分语义和表述相似性,验证相似度计算函数返回中间范围相似度(0.5 到 1.0 之间)。
testCalculateSimilarityWithEmptyText 原文为空检测 原文为空字符串,待检测文本非空,验证相似度计算函数返回 0%(即相似度值为 0.0)。
testCalculateSimilarityWithBothEmptyText 两个空字符串检测 原文和待检测文本均为空字符串,验证相似度计算函数返回 100%(即相似度值为 1.0)。
testGetEditDistanceWithSameText 相同文本编辑距离检测 两个完全相同的字符串,验证编辑距离计算函数返回 0。
testGetEditDistanceWithDifferentText 不同文本编辑距离检测 两个有差异的字符串(如“kitten”和“sitting”),验证编辑距离计算函数返回合理的编辑距离值(如示例中返回 3)。
testReadFileWithValidPath 有效文件路径读取检测 对存在且内容已知的文件,验证文件读取函数能正确读取文件内容。
testReadFileWithInvalidPath 无效文件路径读取检测 对不存在的文件路径,验证文件读取函数会抛出 IOException 异常。
testWriteFileWithValidPath 有效文件路径写入检测 向有效文件路径写入指定相似度值,验证文件写入函数能成功写入且内容正确(如写入 0.85,文件内容为“0.85”)。

五、异常处理说明
1、文件不存在
传入了错误的文件路径(例如 invalid_path.txt),或运行环境无权限读文件时,readFile 捕获底层IO错误并向上抛出IOException,main在外层捕获并打印错误信息/返回非 0状态。
@Test(expected = IOException.class)
public void testReadFileWithInvalidPath() throws IOException {
FileHandler fileHandler = new FileHandler();
fileHandler.readFile("this_path_should_not_exist_12345.txt");
}
2、空输入
输入文件为空、或者 readFile 返回空字符串时,函数入口对空串做显式判断并返回固定值。
@Test
public void testCalculateSimilarityWithBothEmptyText() {
SimilarityCalculator calc = new SimilarityCalculator();
double result = calc.calculateSimilarity("", "");
assertEquals(1.0, result, 0.01);
}

@Test
public void testCalculateSimilarityWithEmptyText() {
SimilarityCalculator calc = new SimilarityCalculator();
double result = calc.calculateSimilarity("", "今天是星期天,天气晴。");
assertEquals(0.0, result, 0.01);
}
3、超长输入
一次性比较多 MB / GB 的文本,可能导致长时间运行甚至内存耗尽。此时,在 calculateSimilarity 开头做长度检查,如果超过阈值(可配置,如 MAX_LEN=5_000_000),抛出受检异常 CalculationException 并提示分段或使用近似算法。
@Test(expected = CalculationException.class)
public void testCalculateSimilarityWithTooLargeInput() throws CalculationException {
SimilarityCalculator calc = new SimilarityCalculator();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 20000; i++) sb.append('a'); // 假设测试环境阈值较小
calc.calculateSimilarity(sb.toString(), "short");
}
六、PSP实际花费时间

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 20
Estimate 估计这个任务需要多少时间 10 10
Development 开发 200 240
Analysis 需求分析(包括学习新技术) 40 50
Design Spec 生成设计文档 25 30
Design Review 设计复审 20 15
Coding Standard 代码规范(为目前的开发制定合适的规范) 15 20
Design 具体设计 50 45
Coding 具体编码 100 110
Code Review 代码复审 20 15
Test 测试(自我测试,修改代码,提交修改) 100 120
Reporting 报告 30 30
Test Report 测试报告 20 15
Size Measurement 计算工作量 10 10
Postmortem & Process Improvement Plan 事后总结,并提出过程改进计划 30 40
总计 690 730
posted @ 2025-09-23 17:16  Linee  阅读(207)  评论(0)    收藏  举报