第一次个人项目

软件工程 软件工程
这个作业要求在哪里 作业要求
这个作业的目标 使用 Python 实现基于 SimHash 算法的文本查重程序,读取待比对的两份文本,计算文本相似度并输出结果;同时完成代码规范检查、单元测试、性能分析,用 Git 在 GitHub 管理项目代码。

Part 1 github链接

https://github.com/3214153741-sudo/paper-checking

Part 2 PSP表格

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

Part 3 计算模块接口的设计与实现过程

本次项目基于 SimHash 算法实现中文文本查重工具,整体代码采用函数式组织,没有定义类,由多个独立函数分工完成文本处理、指纹计算、相似度比对功能,函数之间依靠参数传递数据。

代码结构与函数关系

  1. preprocess_text():文本预处理函数。负责读取文本,去除多余换行、空格、标点符号,调用分词库对中文句子分词,输出清洗后的词语列表;是整个程序的前置模块,为 SimHash 计算提供干净的分词结果。
  2. calculate_hash():计算单个词语的哈希值,将词语映射为固定长度二进制串。
  3. simhash():核心 SimHash 指纹生成函数,遍历分词列表,累加各位权重,生成文本 64 位 SimHash 指纹。调用calculate_hash()得到每个词哈希,是本项目核心计算模块。
  4. hamming_distance():计算两段文本指纹之间的汉明距离。
  5. calc_similarity():根据汉明距离换算得到文本相似度,保留两位小数。
  6. main():入口函数,接收命令行传入的三个文件路径参数,依次调用预处理、simhash、汉明距离、相似度计算函数,最后将结果写入输出文件。

调用关系:main() → preprocess_text() → simhash() → calculate_hash();simhash得到两个指纹后,调用hamming_distance(),再传入calc_similarity()得到最终相似度。
独到之处有

  1. 针对中文场景做文本清洗,过滤无效符号,减少无关字符对指纹的干扰,提升查重准确度;
  2. 模块化拆分,每个函数职责单一,方便单独单元测试,便于后续维护和性能优化;
  3. 加入文件读取异常捕获,程序鲁棒性更强,遇到空文件、不存在文件不会直接崩溃。

Part 4 计算模块接口部分的性能改进

在性能分析与模块优化阶段,预估耗时 30 分钟,实际耗时约 35 分钟。主要花费在性能采样、定位热点函数、代码重构与反复对比测试。

改进思路是使用 Python 内置cProfile工具对完整程序进行性能剖析,采集全流程函数调用耗时,识别出程序中simhash () 指纹生成函数为耗时占比最高的热点函数。原版本在循环内重复执行分词与哈希计算,存在不必要的重复运算。
00b223586ba03618d5aba48620cf0321

本次使用 cProfile 生成性能分析统计图表,图中可以直观看到各函数累计执行时间:
消耗最大函数为 simhash(),该函数占用了绝大部分 CPU 执行时间;其次是文本预处理preprocess_text()。其余辅助函数(汉明距离、相似度换算)耗时占比很低,不是性能瓶颈。

Part 5 单元测试与测试覆盖率

针对项目核心功能编写单元测试,覆盖文本读取、文本预处理、相似度计算、文件异常等多个分支场景。一共设计 9 个测试用例:包含正常文本比对、空文本输入、不存在文件路径等边界用例,验证各个函数在正常输入与异常输入下能否得到预期结果。

我分别在git bash里面用这两条命令做了测试
使用pytest框架执行全部测试用例,运行后所有 9 个用例全部通过,说明各模块逻辑符合预期:pytest test_main.py -v
a2100c013a6ce374590884f990b3e850

配套使用pytest-cov统计代码覆盖率:pytest test_main.py --cov=main
1308cbaacde0c9fe097c4df5e0cc5832

Part 6 异常处理

为了防止程序在文件读写模块期间出错,所以设计了三种提前纠错的检测
1.文件不存在异常
当输入的原文路径、比对文本路径不存在时捕获该异常,打印提示信息 “程序异常:文件不存在” 并安全退出。
image

  1. 文件 IO 读写异常
    读取文件、写入结果文件时捕获 IO 相关异常,区分读取失败、写入失败两类提示,方便排查权限、路径等问题。
    image

  2. 通用兜底异常
    增加通用 Exception 捕获,捕获其余未知运行错误,避免原始堆栈错误直接展示给使用者,提升程序健壮性。
    单元测试中专门设计了对应异常场景的测试用例,验证异常捕获分支可以正常触发,异常处理逻辑有效。
    image

Part 7 开发实际耗时

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

Part 8 迭代提交记录

项目使用 Git 进行版本管理,代码托管于 GitHub,各次提交迭代如下:

1.初始化项目,学号目录新建main.py与requirements.txt:创建项目基础文件,完成仓库初始化。
2.第一次代码测试:对核心代码进行初步功能测试,验证基础逻辑。
3. 新增注释:为源码添加注释,提升代码可读性。
4.修改为调用txt的方式,之前是写死的文本:改造输入逻辑,从直接写死文本改为读取外部 txt 文件。
5.新增十组用例:扩充单元测试,增加 10 组测试用例覆盖更多场景。
6.新增测试代码覆盖率,和添加gitignore:增加.gitignore 文件,引入工具统计单元测试覆盖率。
7.添加 README.md项目说明文档:编写项目介绍 README,完善仓库主页说明。
8.添加requirements.txt,记录项目依赖包:完善依赖清单,记录项目需要安装的库。
9.代码测试完成:全部功能与测试验证完毕,项目开发收尾。
image

Part 9 总结

本次项目实践完成了从需求分析、代码开发、迭代完善到测试验证的完整流程。项目中掌握了Git版本控制工具的使用,学会将本地仓库关联GitHub远程仓库,通过多次commit记录代码变更并推送到远端保存版本。开发阶段依据需求完成基础代码实现,再逐步补充功能、增加异常处理逻辑,最后编写单元测试,对正常与异常场景开展验证。本次实践完整展示了增量开发的工作模式,熟悉了软件工程基础开发流程。

posted @ 2026-09-14 20:01  张高朗  阅读(15)  评论(0)    收藏  举报