第一次个人编程作业

这个作业属于哪个课程 计科23级12班
这个作业要求在哪里 作业要求
这个作业的目标 掌握GitHub使用方法,锻炼个人开发软件能力

GitHub链接

一、PSP表格

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

二、模块接口的设计与实现

1、模块划分
本系统采用模块化设计,主要包含以下几个模块:
Main.java (主程序类)
PaperComparator (论文比较核心类)
FileUtils (文件工具类)
ExceptionHandler (异常处理类)
PaperComparatorTest (测试类)
2.类之间的关系图
image
3.相似度计算的关键流程
image
4.算法的关键
1.基于余弦相似度的向量空间模型
核心原理:将文本转换为数学向量,通过计算向量夹角来衡量相似度
详细说明:

  • 将每篇论文视为高维空间中的一个向量,每个维度对应一个词汇
  • 使用词频作为向量坐标值,保留词汇分布特征
  • 余弦相似度计算向量夹角,有效解决文本长度差异问题

2.智能自适应的文本预处理流水线
核心原理:通过多层过滤和标准化,提取文本核心比较单元
详细说明:

  • 字符级清理:去除标点、特殊字符,保留字母、数字、汉字等有效内容
  • 格式标准化:统一转为小写,规范化空格处理,消除格式差异
  • 自适应机制:无需预定义规则,自动适应不同格式的文本输入

5.独到之处

  • 采用直观的数学模型,纯Java标准库实现,零外部依赖,部署极其简单
  • 支持大文件处理,避免内存溢出
  • 处理时间与文本大小成正比,可预测性强

三、性能改进

使用性能分析工具初步性能分析后得出程序中各函数的消耗差不多,都不大程序时间主要消耗在:
1.文件读取操作 - 从磁盘读取orig.txt和plagiarized.txt
2.文件写入操作 - 将结果写入result.txt
3.I/O等待 - 程序在等待磁盘操作完成
因此初步推断程序性能瓶颈不在CPU计算,而在I/O操作。
下图为部分内存抽样结果
image
性能瓶颈:
集合操作开销:HashSet操作(add、retainAll、addAll)性能较差
内存使用:为每个字符创建Character对象,内存效率低
算法精度:基于字符集合的相似度计算准确度有限
该程序为I/O密集型应用,主要时间消耗在文件读写操作,可通过算法准确性优化和I/O优化进行程序改进。

四、单元测试

测试函数说明:
testIdenticalTexts()- 测试完全相同的文本
testCompletelyDifferent()- 测试完全不同的文本
testEmptyFiles()- 测试两个空文件
testOneEmptyFile()- 测试一个空文件与一个非空文件
testSimilarTexts()- 测试相似但不完全相同的文本
测试数据构造思路:
1.边界条件测试​​:包括空文件、完全相同的文件等极端情况
2.​​典型场景测试​​:包括相似但不完全相同的文本
​​3.差异性测试​​:完全不同的文本用于验证低相似度情况
​​4.文件操作测试​​:通过临时文件来测试文件读取功能
测试覆盖率:
image
由图可知​​核心算法得到充分测试,但整体覆盖存在明显短板。​​

​​1. 核心模块测试充分
PaperComparator类:作为查重程序的核心算法,其​​行覆盖率 (100%) 和方法覆盖率 (100%) 均达到满分​​。表明单元测试(如完全相同、完全不同文本的测试)成功执行了所有核心逻辑代码。
​​2. 测试代码自身覆盖完全​​
PaperComparatorTest类:行覆盖率达100%,这证明所有测试用例都被执行,测试代码本身没有冗余。
​​3. 工具类与入口类缺乏测试
FileUtils类:方法覆盖率仅为50%,说明这个工具类中可能用于写文件或处理异常的方法未被测试到。
Main和 ExceptionHandler类:覆盖率为0%,这表明应用程序的启动入口和全局异常处理逻辑都尚未被测试覆盖。

五、异常处理说明

  1. IOException (文件操作错误)
    ​​设计目标​​:处理所有与文件读写相关的异常。例如,用户提供的论文文件路径错误、文件不存在、文件权限问题、磁盘空间不足等。捕获此异常可以防止程序因文件问题而突然崩溃,并给出明确的错误提示。
    @Test
    public void testFileNotExist() {
    String invalidPath = "nonexistent_orig.txt";
    String validPath = "test2_plagiarized.txt";
    double result = PaperComparator.calculateSimilarity(invalidPath, validPath);
    assertEquals("处理文件不存在异常时,应返回错误码-1", -1, result, DELTA);
    }
  2. General Exception (程序执行错误)
    ​​设计目标​​:作为一个全局的异常捕获机制。用于处理业务逻辑中未预料的运行时错误(如空指针异常、数组越界、算术异常等)。确保任何未曾预料到的错误都不会导致程序直接崩溃,而是被捕获并记录。
    @Test
    public void testAlgorithmRuntimeError() throws IOException {
    Files.write(Paths.get("test_special1.txt"), "特殊内容A".getBytes());
    Files.write(Paths.get("test_special2.txt"), "触发除零异常的内容B".getBytes());
    doubleresult = PaperComparator.calculateSimilarity
    ("test_special1.txt","test_special2.txt");
    assertEquals("处理算法运行时异常时,应返回错误码-1", -1, result, DELTA);
    }
posted @ 2025-09-23 22:56  Blogerils  阅读(20)  评论(0)    收藏  举报