项目 | 链接 |
---|---|
软件工程 | 软件工程链接 |
作业要求 | 作业要求的链接 |
作业目标 | 两人用python实现一个自动生成小学四则运算题目的命令行程序 |
github项目链接 | github项目链接 |
团队成员
姓名 | 学号 |
---|---|
李金强 | 3121004868 |
赵继业 | 3121004890 |
1. PSP表格
PSP表格通常用于软件工程中,用于跟踪和记录开发者在项目中的时间估计和实际工作量。这有助于跟踪任务的时间管理和效率,并提供了有关项目进展的信息。
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 100 | 150 |
· Estimate | · 估计这个任务需要多少时间 | 100 | 150 |
Development | 开发 | 950 | 1060 |
· Analysis | · 需求分析 (包括学习新技术) | 120 | 200 |
· Design Spec | · 生成设计文档 | 100 | 120 |
· Design Review | · 设计复审 | 80 | 60 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 50 | 50 |
· Design | · 具体设计 | 120 | 180 |
· Coding | · 具体编码 | 200 | 240 |
· Code Review | · 代码复审 | 100 | 60 |
· Test | · 测试(自我测试,修改代码,提交修改) | 180 | 150 |
Reporting | 报告 | 110 | 140 |
· Test Repor | · 计算工作量 | 30 | 40 |
· Size Measurement | · 事后总结, 并提出过程改进计划 | 80 | 100 |
· 合计 | 1160 | 1350 |
2. 项目需求
- 使用 -n 参数控制生成题目的个数。
- 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围。
- 生成的题目中计算过程不能产生负数。
- 生成的题目中如果存在形如e1÷e2的子表达式,那么其结果应是真分数。
- 每道题目中出现的运算符个数不超过3个。
- 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。
- 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件。
- 程序应能支持一万道题目的生成。
- 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计。
3. 模块接口的设计与实现
这个应用程序包括三个主要模块:function、interface和main。这些模块共同实现了一个数学题目生成和答题检查的应用程序。
3.1 function模块
function模块包含了用于生成数学题目和进行相关计算的类和函数。
3.1.1 类Number数字
__init__(self,max:int=None,nums:tuple=None)
:初始化Number类的实例。根据输入参数max和nums生成随机数或根据给定的数字创建实例。reduce_fraction(self)
: 计算最大公约数并将分数简化为最简形式。__str__(self)
: 将Number实例转化为字符串表示,包括整数部分和分数部分。__float__(self)
: 将 Number 实例转化为浮点数。
3.1.2 类Fraction分数
__init__(self, f1: Number, f2: Number, op: str)
: 初始化 Fraction 类的实例,接受两个 Number 实例和一个操作符。calculate_fractions(self):
对两个分数执行指定的二元运算,并返回简化的结果。
3.1.3 类Expression表达式
__init__(self, max, question_num)
: 初始化 Expression 类的实例,接受最大值和题目数量。generate_subexpression(self, etype, op)
: 生成子表达式。generate_expression_list(self)
: 生成表达式列表。calculate_answer(self, expression_list)
: 计算表达式的答案。generate_expressions(self)
: 生成表达式。randomly_generate_questions(self)
: 随机生成题目。run(self)
: 运行生成题目和表达式的流程。
3.2 interface模块
实现了用户界面,允许用户输入参数、生成题目、提交答案并查看结果。
3.2.1 类MathQuizApp数学题目生成应用程序
__init__(self, root)
: 初始化应用程序界面,创建各种GUI元素。generate_questions(self)
: 获取用户输入的题目数量和最大值,调用 function.py 中的函数生成题目,然后在界面上显示题目。check_answers(self)
: 获取用户输入的答案,比较用户答案和正确答案,然后在界面上显示答题结果。
3.3 main模块
该模块为应用程序的入口,启动GUI界面。
if __name__ == "__main__
:在这个条件下创建了 tkinter 的主窗口 root,然后实例化了 MathQuizApp 类作为应用程序的主要部分。最后,通过 root.mainloop() 启动了 GUI 界面,进入应用程序的运行状态。
3.4 算法的关键
- 随机生成数学表达式: 该程序的算法关键点之一是能够随机生成数学表达式。它使用随机数生成器来创建包含分数的算术表达式,包括不同的操作符(加法、减法、乘法、除法)和分数的分子和分母。
- 分数运算和简化: 算法的另一个关键点是能够执行分数运算和简化。它使用自定义的Number、Fraction、Expression类来处理分数的加法、减法、乘法和除法运算,并确保答案以最简形式呈现。
- 错误处理和异常处理: 算法包括错误处理机制,以处理可能出现的异常情况,例如除零错误或无效的表达式。程序会继续尝试生成有效的表达式,以确保用户可以获得可答题目。
3.5 独到之处
- 用户友好的图形界面: 程序提供了一个直观的图形用户界面(GUI),用户可以轻松输入题目数量和最大值,然后生成题目并答题。这使得程序更易于使用,特别适合教育和娱乐。
- 答案检查和反馈: 用户提交答案后,程序会自动检查答案的正确性,并提供明确的反馈,显示哪些题目回答正确,哪些回答错误。这种实时反馈有助于用户了解他们的表现。
- 结果保存和导出: 该程序允许用户将生成的题目和正确答案保存到文件中,以供以后查看或导出。这对于教育或记录进度非常有用。
4.模块化设计: 代码被模块化组织,使得每个功能块都可以独立工作。这使得程序更易于维护、扩展和重用。
3.6 流程图
该流程图介绍了各模块的运行机理及模块调用操作。
4. 性能分析
py-spy是一款出色的性能分析工具,旨在监测运行中的Python进程,为性能调优和故障排除提供强大支持。它主要提供两种关键视图,即Flamegraph(火焰图)和Top(顶部)视图,以便以图形方式呈现Python应用程序的性能数据。这两种视图具有重要功能,有助于深入了解应用程序中的性能瓶颈和函数调用情况。在终端中运行:
py-spy record -o profile.json -f speedscope -- python main.py
· 火焰图(Flamegraph):火焰图是一种强大的可视化工具,用于展示函数调用层次关系。通常,它被用于分析性能数据,以便更好地理解哪些模块在应用程序中花费了大量时间。火焰图的横轴表示函数调用的层次结构,纵轴表示调用的深度。每个矩形块代表一个函数调用,块的宽度表示该函数占用的时间比例。通过火焰图,可以迅速识别哪些函数的执行时间较长,从而有针对性地进行性能优化。
· Top(顶部)视图:这个视图显示了正在运行的Python进程中占用CPU时间最多的函数,能展示程序中消耗最大的函数。
5. Code Quality Analysis
Code Quality Analysis是一种软件开发过程中的质量评估方法,用于评估和衡量编写的代码的质量。这个过程涉及审查、测试和评估代码,以确保其符合最佳实践、规范和标准,从而确保代码的可维护性、可读性、性能、安全性和可靠性。代码质量分析的目标是发现并纠正潜在的问题,以确保软件在生产环境中能够稳定、高效地运行。
本次代码质量分析考虑了以下内容:
- 代码风格和规范: 检查代码是否遵循了一致的编码风格和编程规范,以确保代码的可读性和可维护性。
- 性能分析: 评估代码的性能,识别潜在的性能瓶颈和优化机会,以确保软件在运行时具有良好的性能。
- 安全性分析: 检查代码是否容易受到安全漏洞和攻击的威胁,以确保软件的安全性。
- 静态分析: 使用工具来分析代码的静态结构,识别潜在的问题,如死代码、未使用的变量等。
- 动态分析: 运行代码并监视其行为,以识别运行时问题,如内存泄漏、异常等。
- 单元测试和集成测试: 编写和运行测试用例,验证代码的功能是否按预期工作。
- 持续集成: 集成代码质量分析工具到持续集成流程,以确保每次代码提交都会进行自动分析和测试。
依次对代码文件进行分析,最终消除了所有的错误及警告:
6. 单元测试
6.1 单元测试用例
6.2 测试覆盖率
7. 后续优化改进
- 模块分割和组织: 根据功能和责任,将代码拆分成更小的模块或类。这有助于提高代码的可维护性和可重用性。
- 文档和注释: 添加详细的文档字符串和注释,以解释代码的目的、功能和用法。这将使其他开发人员更容易理解和使用代码。
- 异常处理改进: 在代码中的异常处理方面,可以更具体地捕获不同类型的异常,并提供有用的错误消息,以便更好地诊断问题。
- 输入验证: 对于用户输入,进行更严格的验证和检查,以确保输入的正确性和安全性。这有助于防止潜在的错误或恶意输入。
- 错误处理和日志记录: 对于错误处理,可以使用日志记录器(如 Python 的 logging 模块)来记录错误和异常,以便更容易进行故障排除。
8. 项目小结
本次项目为两人分工合作,明确每个人在项目中的责任分工非常重要,以确保项目能够高效进行:
团队成员 | 工作内容 |
---|---|
李金强 | 图形界面及主函数的实现,性能分析,撰写博客 |
赵继业 | 功能函数的实现,单元测试 |
收获内容:
- 项目管理: 项目的规划和管理对于两位成员都是一次宝贵的经验。他们学会了如何分配任务、制定计划并按时完成工作。
- 实际应用开发: 这个项目使两位成员有机会将编程和软件开发技能应用到实际项目中,从而更好地理解了如何创建有用的应用程序。
- 问题解决能力: 在项目中,他们不仅要编写代码,还需要解决各种问题和挑战。这锻炼了他们的问题解决能力。