软工第二次作业
软工第二次作业
| 这个作业属于哪个课程 | 班级链接 |
|---|---|
| 这个作业要求在哪里 | 作业要求 |
| 这个作业的目标 | 设计一个论文查重算法,并使用性能分析工具进行代码优化,用github仓库进行代码管理 |
作业的github地址:https://github.com/Keygener53/3123004310
1、PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 50 | 50 |
| · Estimate | · 估计这个任务需要多少时间 | 20 | 30 |
| Development | 开发 | 300 | 360 |
| · Analysis | · 需求分析(包括学习新技术) | 100 | 80 |
| · Design Spec | · 生成设计文档 | 20 | 20 |
| · Design Review | · 设计复审 | 30 | 30 |
| · Coding Standard | · 代码规范(为目前的开发制定合适的规范) | 10 | 10 |
| · Design | · 具体设计 | 40 | 50 |
| · Coding | · 具体编码 | 60 | 60 |
| · Code Review | · 代码复审 | 20 | 10 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 50 | 60 |
| · Reporting | · 报告 | 30 | 30 |
| · Test Report | · 测试报告 | 20 | 30 |
| · Size Measurement | · 计算工作量 | 10 | 10 |
| · Postmortem & Process Improvement Plan | · 事后总结,并提出过程改进计划 | 20 | 30 |
| 合计 | 780 | 860 |
2、模块接口的设计与实现过程

核心类:OptimizedPaperChecker
- 初始化方法 init
- 停用词加载 _load_comprehensive_stopwords
- 带缓存的文件读取 read_file_cached
- 文本预处理 preprocess_text_optimized
- 余弦相似度计算 calculate_cosine_similarity_optimized
- Jaccard相似度计算 calculate_jaccard_similarity
- 混合相似度算法 hybrid_similarity
- 主查重方法 check_similarity
设计特点
- 模块化设计:每个方法职责单一,易于测试和维护
- 异常隔离:不同层次的异常独立处理,避免级联失败
- 优雅降级:主要功能失败时仍有基本输出
- 性能优化:文件缓存、并行处理、算法优化
- 可扩展性:易于添加新的相似度算法或预处理步骤
3、模块接口部分的性能改进

改进后的版本:
增加扩展功能:
- 添加混合相似度算法(余弦+Jaccard)
- 实现文件读取缓存机制
- 添加并行分词优化
- 扩展停用词表
进行性能优化:
- 优化余弦相似度计算逻辑
- 预编译正则表达式
- 添加内存使用监控
- 较原版本的性能效率提高10%以上,准确率提高20%以上
4、单元测试
列举其中三个
- 测试文件不存在异常
点击查看代码
def test_file_not_exist(self):
"""测试文件不存在异常"""
orig_file = "nonexistent_orig.txt"
copy_file = self.create_test_file("内容", "copy.txt")
result_file = os.path.join(self.temp_dir, "result.txt")
similarity = self.checker.check_similarity(orig_file, copy_file, result_file)
self.assertEqual(similarity, 0.0)
self.assertTrue(os.path.exists(result_file))
with open(result_file, 'r') as f:
self.assertEqual(f.read(), "0.00")
- 测试特殊字符处理
点击查看代码
def test_special_characters_handling(self):
"""测试特殊字符处理"""
orig_content = "这是一篇包含标点!@#的论文。"
copy_content = "这是一篇包含标点!@#的论文。"
orig_file = self.create_test_file(orig_content, "orig.txt")
copy_file = self.create_test_file(copy_content, "copy.txt")
result_file = os.path.join(self.temp_dir, "result.txt")
similarity = self.checker.check_similarity(orig_file, copy_file, result_file)
self.assertGreater(similarity, 0.5) # 相同内容应有较高相似度
- 测试文件不存在异常
点击查看代码
def test_file_not_exist(self):
"""测试文件不存在异常"""
orig_file = "nonexistent_orig.txt"
copy_file = self.create_test_file("内容", "copy.txt")
result_file = os.path.join(self.temp_dir, "result.txt")
similarity = self.checker.check_similarity(orig_file, copy_file, result_file)
self.assertEqual(similarity, 0.0)
self.assertTrue(os.path.exists(result_file))
with open(result_file, 'r') as f:
self.assertEqual(f.read(), "0.00")
5、模块部分异常处理说明
- 文件不存在异常
- 文件大小限制异常
- 空文件异常
- 编码异常
- 文件权限异常
点击查看代码
try:
# 检查文件是否存在
if not os.path.exists(file_path):
raise FileNotFoundError(f"文件不存在: {file_path}")
# 检查文件大小(防止处理过大文件)
file_size = os.path.getsize(file_path)
if file_size > 10 * 1024 * 1024: # 10MB限制
raise ValueError(f"文件过大: {file_size}字节,最大支持10MB")
# 检查文件是否为空
if file_size == 0:
raise ValueError("文件为空")
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read().strip()
if not content:
raise ValueError("文件内容为空")
return content
except UnicodeDecodeError:
# 尝试其他编码
try:
with open(file_path, 'r', encoding='gbk') as f:
content = f.read().strip()
if not content:
raise ValueError("文件内容为空")
return content
except UnicodeDecodeError:
raise Exception(f"无法解码文件编码,尝试使用UTF-8或GBK: {file_path}")
except PermissionError:
raise Exception(f"没有权限读取文件: {file_path}")
except Exception as e:
raise Exception(f"文件读取失败: {str(e)}")
浙公网安备 33010602011771号