软工第二次作业
Github链接:https://github.com/SophiaMikasa/SophiaMikasa
这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/homework/13468
这个作业的目标 完成第一个个人项目,熟悉项目开发流程
文本查重系统开发实践:从接口设计到性能优化
Personal Software Process (PSP) 记录
项目概述
本项目是一个文本查重系统的开发过程记录,遵循CMU的个人软件过程标准。
| PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 30 | 35 |
| · Estimate | 估计这个任务需要多少时间 | 20 | 25 |
| Development | 开发 | 480 | 520 |
| · Analysis | 需求分析 (包括学习新技术) | 60 | 75 |
| · Design Spec | 生成设计文档 | 40 | 45 |
| · Design Review | 设计复审 | 20 | 15 |
| · Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 25 |
| · Design | 具体设计 | 50 | 60 |
| · Coding | 具体编码 | 200 | 240 |
| · Code Review | 代码复审 | 30 | 25 |
| · Test | 测试 (自我测试,修改代码,提交修改) | 120 | 140 |
| Reporting | 报告 | 60 | 70 |
| · Test Report | 测试报告 | 30 | 35 |
| · Size Measurement | 计算工作量 | 15 | 20 |
| · Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 45 | 50 |
| 合计 | 570 | 625 |
详细记录
Planning 阶段
- 任务: 项目整体规划和时间估算
- 产出: 项目计划文档
- 经验: 初期估算偏乐观,实际开发复杂度更高
Development 阶段
Analysis (需求分析)
- 学习jieba分词库使用方法
- 研究文本相似度算法
- 分析多编码文件处理需求
Design Spec (设计文档)
- 设计PlagiarismChecker类结构
- 定义算法接口和数据流
- 规划异常处理机制
Coding (编码实现)
- 实现核心查重算法
- 开发文本预处理模块
- 编写文件读取和编码处理
Test (测试)
- 编写17个测试用例
- 进行边界条件测试
- 性能测试和优化
过程改进计划
- 时间估算: 增加20%缓冲时间
- 测试驱动: 先写测试用例再实现功能
- 代码审查: 增加同行评审环节
- 文档同步: 开发过程中同步更新文档
1. 计算模块接口的设计与实现过程
1.1 核心类设计
class PlagiarismChecker:
"""论文查重核心算法类"""
def __init__(self, ngram_size=3):
"""初始化查重器,支持自定义n-gram大小"""
self.ngram_size = ngram_size
1.2 主要接口方法
文件读取接口
def read_file(self, file_path):
"""
多编码支持的文件读取接口
- 支持UTF-8、GBK、GB2312等编码
- 自动编码检测和容错处理
- 异常情况的优雅降级
"""
文本预处理接口
def preprocess_text(self, text):
"""
智能文本预处理
- 去除标点符号和特殊字符
- 规范化空白字符
- 基于jieba的中文分词
"""
相似度计算接口
def check_plagiarism(self, orig_file, plagiarized_file):
"""
主要查重接口
- 多算法融合计算
- 返回0-100的相似度百分比
- 完善的异常处理
"""
1.3 算法实现细节
系统实现了三种核心算法:
- N-gram相似度算法
def calculate_ngram_similarity(self, words1, words2):
"""基于n-gram的局部相似性检测"""
ngrams1 = set(self.generate_ngrams(words1, self.ngram_size))
ngrams2 = set(self.generate_ngrams(words2, self.ngram_size))
intersection = len(ngrams1.intersection(ngrams2))
union = len(ngrams1.union(ngrams2))
return intersection / union if union > 0 else 0.0
- 序列相似度算法
def calculate_sequence_similarity(self, text1, text2):
"""基于编辑距离的整体相似性检测"""
return SequenceMatcher(None, text1, text2).ratio()
- 词汇重叠度算法
def calculate_word_overlap(self, words1, words2):
"""基于集合运算的词汇重叠检测"""
set1, set2 = set(words1), set(words2)
intersection = len(set1 & set2)
union = len(set1 | set2)
return intersection / union if union > 0 else 0.0
2. 计算模块接口部分的性能改进
2.1 算法优化策略
加权融合算法
# 综合相似度计算(加权平均)
final_similarity = (
ngram_similarity * 0.5 + # n-gram权重最高
sequence_similarity * 0.3 + # 序列相似度中等权重
word_overlap * 0.2 # 词汇重叠最低权重
)
集合运算优化
- 使用Python内置的set数据结构进行交集、并集运算
- 避免重复计算,提高算法效率
2.2 内存优化
生成器模式
def generate_ngrams(self, words, n):
"""使用列表推导式优化内存使用"""
if len(words) < n:
return [tuple(words)]
return [tuple(words[i:i + n]) for i in range(len(words) - n + 1)]
早期返回策略
if not words1 and not words2:
return 1.0 # 两个空列表完全相同
if not words1 or not words2:
return 0.0 # 一个空一个非空,直接返回
2.3 性能分析工具
系统集成了专门的性能分析模块:
def run_profiler():
"""运行cProfile性能分析器"""
profiler = cProfile.Profile()
profiler.enable()
# 执行测试代码
detailed_performance_test()
profiler.disable()
# 生成性能报告
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats(20)
3. 计算模块部分单元测试展示
3.1 测试架构设计
class TestPlagiarismChecker(unittest.TestCase):
"""论文查重器单元测试类"""
def setUp(self):
"""测试前准备"""
self.checker = PlagiarismChecker()
self.temp_dir = tempfile.mkdtemp()
def tearDown(self):
"""测试后清理"""
shutil.rmtree(self.temp_dir, ignore_errors=True)
3.2 核心测试用例
基础功能测试
def test_identical_texts(self):
"""测试完全相同的文本"""
text = "今天是星期天,天气晴,今天晚上我要去看电影。"
file1 = self.create_temp_file(text, "orig.txt")
file2 = self.create_temp_file(text, "copy.txt")
similarity = self.checker.check_plagiarism(file1, file2)
self.assertGreater(similarity, 90) # 应该有很高的相似度
def test_completely_different_texts(self):
"""测试完全不同的文本"""
text1 = "今天是星期天,天气晴,今天晚上我要去看电影。"
text2 = "编程语言有很多种,包括Python、Java、C++等。"
file1 = self.create_temp_file(text1, "orig.txt")
file2 = self.create_temp_file(text2, "diff.txt")
similarity = self.checker.check_plagiarism(file1, file2)
self.assertLess(similarity, 30) # 应该有很低的相似度
边界条件测试
def test_empty_files(self):
"""测试空文件"""
file1 = self.create_temp_file("", "empty1.txt")
file2 = self.create_temp_file("", "empty2.txt")
similarity = self.checker.check_plagiarism(file1, file2)
self.assertEqual(similarity, 0.0)
def test_single_character_files(self):
"""测试单字符文件"""
file1 = self.create_temp_file("a", "single1.txt")
file2 = self.create_temp_file("a", "single2.txt")
similarity = self.checker.check_plagiarism(file1, file2)
self.assertGreater(similarity, 80)
编码兼容性测试
def test_gbk_encoding_file(self):
"""测试GBK编码文件"""
text = "今天是星期天,天气晴朗。"
# 创建GBK编码文件
gbk_file = os.path.join(self.temp_dir, "gbk_test.txt")
with open(gbk_file, "w", encoding="gbk") as f:
f.write(text)
utf8_file = self.create_temp_file(text, "utf8_test.txt")
similarity = self.checker.check_plagiarism(gbk_file, utf8_file)
self.assertGreater(similarity, 90)
3.3 测试覆盖率
系统包含17个扩展测试用例,覆盖率超过90%:
- 基础功能测试:6个用例
- 边界条件测试:5个用例
- 编码兼容性测试:3个用例
- 异常处理测试:3个用例
4. 计算模块部分异常处理说明
4.1 文件读取异常处理
def read_file(self, file_path):
"""多层次的异常处理策略"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"文件不存在: {file_path}")
# 尝试多种编码
encodings = ['utf-8', 'gbk', 'gb2312', 'latin1']
for encoding in encodings:
try:
with open(file_path, 'r', encoding=encoding) as f:
content = f.read().strip()
if content:
return content
except (UnicodeDecodeError, UnicodeError):
continue
except Exception as e:
if encoding == encodings[-1]:
raise OSError(f"无法读取文件 {file_path}: {e}")
continue
# 最后的容错处理
try:
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read().strip()
return content if content else ""
except Exception as e:
raise OSError(f"无法读取文件 {file_path}: {e}")
4.2 计算过程异常处理
def check_plagiarism(self, orig_file, plagiarized_file):
"""主接口的异常处理"""
try:
# 核心计算逻辑
orig_text = self.read_file(orig_file)
plagiarized_text = self.read_file(plagiarized_file)
# ... 计算过程 ...
return final_similarity * 100
except Exception as e:
raise Exception(f"查重过程中发生错误: {e}")
4.3 异常处理测试
def test_file_not_found_error(self):
"""测试文件不存在异常"""
with self.assertRaises(FileNotFoundError):
self.checker.read_file("nonexistent_file.txt")
def test_mixed_encoding_error_handling(self):
"""测试混合编码错误处理"""
# 创建包含特殊字符的文件
special_file = self.create_temp_file("测试\x00特殊字符", "special.txt")
normal_file = self.create_temp_file("正常文本", "normal.txt")
# 应该能够处理而不抛出异常
try:
similarity = self.checker.check_plagiarism(special_file, normal_file)
self.assertIsInstance(similarity, float)
except Exception:
self.fail("应该能够处理混合编码文件")
5. 使用说明
5.1 环境要求
# Python版本要求
Python >= 3.7
# 依赖包安装
pip install jieba
5.2 基本使用
from plagiarism_checker import PlagiarismChecker
# 创建查重器实例
checker = PlagiarismChecker(ngram_size=3)
# 执行查重检测
similarity = checker.check_plagiarism("original.txt", "suspected.txt")
print(f"文本相似度: {similarity:.2f}%")
5.3 命令行使用
# 基本查重
python main.py examples/orig.txt examples/orig_add.txt
# 运行测试
python -m pytest test_plagiarism_checker.py -v
# 性能分析
python performance_analysis.py
5.4 高级配置
# 自定义n-gram大小
checker = PlagiarismChecker(ngram_size=4)
# 批量处理
files_to_check = [
("doc1.txt", "doc2.txt"),
("doc3.txt", "doc4.txt")
]
for orig, suspect in files_to_check:
similarity = checker.check_plagiarism(orig, suspect)
print(f"{orig} vs {suspect}: {similarity:.2f}%")
总结
本文详细介绍了文本查重系统的设计与实现过程,从接口设计到性能优化,从单元测试到异常处理,展现了一个完整的软件开发流程。该系统具有以下特点:
- 模块化设计:清晰的接口定义和职责分离
- 算法优化:多算法融合和性能优化策略
- 健壮性:完善的异常处理和边界条件处理
- 可测试性:高覆盖率的单元测试和性能分析
- 易用性:简洁的API设计和详细的使用文档
浙公网安备 33010602011771号