第一次个人编程作业
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/Class56-Grade2024-CS |
|---|---|
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/Class56-Grade2024-CS/homework/15693 |
| 这个作业的目标 | 让我们熟悉软件开发的流程 |
GitHub链接为:https://github.com/south-symphony/2026Software-Engineering/tree/main/3124004141
一、PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | ||
| · Estimate | · 估计这个任务需要多少时间 | 20 | 20 |
| Development | 开发 | ||
| · Analysis | · 需求分析 (包括学习新技术) | 15 | 20 |
| · Design Spec | · 生成设计文档 | 10 | 10 |
| · Design Review | · 设计复审 | 10 | 15 |
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 15 | 10 |
| · Design | · 具体设计 | 40 | 50 |
| · Coding | · 具体编码 | 90 | 100 |
| · Code Review | · 代码复审 | 30 | 25 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 40 | 35 |
| Reporting | 报告 | ||
| · Test Repor | · 测试报告 | 30 | 30 |
| · Size Measurement | · 计算工作量 | 10 | 10 |
| · Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 15 |
| 合计 | 330 | 340 |
二、算法设计与类结构
核心算法思路
采用 中文分词 + 词袋模型 + 余弦相似度 方案:
- 文本预处理:去除标点、空格、换行、数字等无关字符,仅保留中英文
- 中文分词:基于 Jieba 分词器将文本切分为词语序列
- 词频统计:统计两篇文本中每个词语的出现次数,构建词频向量
- 余弦相似度计算:计算两个词频向量的夹角余弦值,取值 0~1,越接近 1 表示重复度越高
该算法对增删改、语序调换等常见抄袭形式有良好识别效果,计算效率高,满足 5 秒内出结果的要求。
类结构设计
遵循单一职责原则,拆分 4 个核心类:
- Main类:程序入口,处理命令行参数、文件读写、全流程调度
- TextPreprocessor类:文本预处理工具类,负责清洗无效字符
- WordSegmenter类:中文分词工具类,封装 Jieba 分词能力
- SimilarityCalculator类:相似度计算工具类,实现词频统计与余弦计算
项目目录结构

三、测试与测试覆盖率
采用 JUnit 5 白盒测试,覆盖所有工具类的核心方法与边界场景。

整体来看核心逻辑的测试质量是合格的,单元测试采用分层策略:重点覆盖核心算法工具类(TextPreprocessor/WordSegmenter/SimilarityCalculator),平均覆盖率 90%+;入口类 Main 通过命令行集成测试进行验证,不纳入单元测试覆盖统计。
- 三个工具类覆盖率优秀:
-
- SimilarityCalculator:指令覆盖率 97%,分支覆盖率 90%。
-
- WordSegmenter:指令覆盖率 90%,分支覆盖率 100%
-
- TextPreprocessor:指令覆盖率 80%,分支覆盖率 100%
- Main类0%属于正常情况,Main是程序入口类,导致测试结果为0%。
- 整体56%偏低完全是被Main类的0%拉低,纯核心逻辑的覆盖率应该在90%+
四、打包与运行测试
1、打包生成main.jar
2、本地运行测试
- 1、orig.txt:https://github.com/south-symphony/2026Software-Engineering/blob/main/3124004141/orig.txt
- 2、orig_add.txt:https://github.com/south-symphony/2026Software-Engineering/blob/main/3124004141/orig_add.txt
- 3、命令行运行: java -jar main.jar orig.txt orig_add.txt ans.txt
- 4、打开ans.txt得到结果
![image]()
五、性能分析与优化
分析工具
JProfiler工具
性能测试结果


性能表现的分析与优化
- 整体表现:程序总运行耗时约 600ms,内存峰值不足 100MB,远优于作业要求的 5 秒、2048MB 限制;全程仅 1 次新生代 GC,无内存泄漏。
- CPU 热点:耗时集中在三部分:字符串切分与正则清洗(约 28%)、HashMap 词频统计(约 18%)、Jieba 分词词典加载与匹配(约 15%),属于文本查重类程序的典型特征;文件 IO 占比不足 1%。
- 已做优化:分词器单例化避免重复加载词典、文本前置清洗减少无效计算量。
- 可优化方向:将正则替换改为字符数组遍历过滤,可进一步提升文本预处理速度。
六、异常处理
| 异常场景 | 触发条件 | 处理方式 | 对应测试样例 |
|---|---|---|---|
| 文件不存在 | 输入路径错误或文件丢失 | 捕获 IOException,打印错误信息后退出 | 传入不存在的文件路径 |
| 文件编码不兼容 | 文件为 GBK 等非 UTF-8 编码 | 先试 UTF-8,失败自动降级为 GBK 读取 | 用 GBK 编码的文本文件测试 |
| 空文本输入 | 文件为空或全是标点符号 | 返回相似度 0.0,程序不崩溃 | 传入内容为空的文件 |
| 通用运行异常 | 分词失败等未知错误 | 捕获异常,打印信息后安全退出 | 构造极端格式文本验证 |
七、总结
这个作业对我而言没有ai的帮助很难完成,一步步慢慢搞做完了。
过程中踩到了各种小坑,遇到挺多ERROR的,爆红了先自己查看能否解决,没办法的话再问ai。
1、JDK 版本与编译配置不匹配
一开始 pom.xml 直接配置了 JDK 11 编译,没考虑本地实际安装的是 JDK 8,导致直接报 “无效的目标发行版”。踩过才意识到,环境版本一致性是开发的第一步,代码写得再对,环境不匹配全白搭。
2、高版本API 向下不兼容
一开始使用了List.of()、Files.readString()这些 JDK 9/11 新增的 API,导致在 JDK 8 的环境下报ERROR。
3、单元测试覆盖率的误区
一开始看到整体覆盖率只有 56%,以为测试写崩了,在代码里好一顿寻找,想找到问题所在,后来才发现是 Main 入口类拉低了数值,核心工具类覆盖率其实都在 90% 以上。
4、Maven 缓存遗留问题
改完 pom 配置重跑还是报错,折腾半天才发现是之前编译失败的缓存没清,执行 mvn clean 清理完 target 目录就正常了。
这次作业最大的感受是,完整的软件开发远不止写核心算法那么简单。从环境配置、版本兼容、单元测试到性能分析,每一个环节都可能出小问题,也都有对应的规范和思路。
以前写代码只追求 “能跑就行”,这次才体会到:代码要考虑兼容性、可测试性,单元测试要聚焦核心逻辑,性能瓶颈不能靠猜要靠工具实打实地测。看着程序从编译报错到跑通测试、再到出性能报告,一步步排查解决问题的过程,比单纯写算法收获更多。

浙公网安备 33010602011771号