结对项目
软件工程结对项目
| 软件工程 | 班级链接 |
|---|---|
| 作业要求 | 作业链接 |
| github链接 | github |
| 作业目标 | 实现一个自动生成小学四则运算题目的命令行程序(也可以用图像界面,具有相似功能)。 |
| 姓名 | 学号 |
| 陈昊宇 | 3121005115 |
| 刘苑佳 | 3121005136 |
PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
| Planning | 计划 | 20 | 20 |
| Estimate | 估计这个任务需要多少时间 | 12 | 12 |
| Development | 开发 | 200 | 300 |
| Analysis | 需求分析 (包括学习新技术) | 25 | 40 |
| Design Spec | 生成设计文档 | 30 | 40 |
| Design Review | 设计复审(和同事审核设计文档) | 35 | 45 |
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 15 | 15 |
| Design | 具体设计 | 60 | 120 |
| Coding | 具体编码 | 60 | 120 |
| Code Review | 代码复审 | 30 | 30 |
| Test | 测试(自我测试,修改代码,提交修改) | 45 | 60 |
| Reporting | 报告 | 50 | 80 |
| Test Report | 测试报告 | 10 | 20 |
| Size Measurement | 计算工作量 | 4 | 4 |
| Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 10 | 30 |
| 合计 | 606 | 936 |
性能分析
以其中一次运行为例,给出性能分析图如下:


其中,程序消耗最大的函数代码如下:
def main(argv: list[str]):
if len(argv) != 5:
print('参数错误!')
return
bn = manage(argv[1], argv[2])
bq = manage(argv[3], argv[4])
if bn or bq: # 生成题目
index = 0
global quantity
global max_value
exer = open('Exercises.txt', 'w', encoding='utf-8')
answ = open('Answers.txt', 'w', encoding='utf-8')
while index < quantity:
# print(max_value)
li = create_lis(max_value)
add_bracket(li)
reone = get_suffix(li)
resu = count_suffix(reone)
if is_rational(resu):
index += 1
# 写题目
ti = ''
for val in li:
ti += str(val)
ti += ' '
exer.write(f'{index}. {ti}=\n')
# 写答案
answ.write(f'{index}. {str(resu)}\n')
print('生成完毕')
else: # 对答案
rli, wli = correct()
with open('Grade.txt', 'w', encoding='utf-8') as graw:
graw.write(f'Correct:{len(rli)} {str(rli)}\n')
graw.write(f'Wrong:{len(wli)} {str(wli)}\n')
print(f'Correct:{len(rli)} {str(rli)}')
print(f'Wrong:{len(wli)} {str(wli)}')
设计实现过程
主程序中一共定义了1个类Number用来表示分数,并在其中提供了有关操作的方法,然后编写了10个函数用于功能的实现,分别是main、is_rational、correct、manage、str_to_num、create_number、create_char、create_lis、add_bracket、get_suffix和count_suffix,其中is_rational函数用于检查输入的参数是否合理,correct函数和manage函数用于生成答案文件和对答案,str_to_num用于实现字符串转化为数字,create_number、create_char、create_lis和add_bracket用于随机生成算式,get_suffix和count_suffix用于计算算式得到结果,最后main函数中会调用这些函数并得到最终结果。
代码说明
项目中的关键代码为create_number、create_char、create_lis和add_bracket这4个用于生成随机算式的函数,其思路是首先按要求生成每一项的数字,再随机生成运算符号,然后将算式转成列表,最后往里面随机添加括号,详细代码如下:
def create_number(maxv: int) -> Number:
pre = random.randint(1, 100)
if pre < 50: # 整数
return Number(str(random.randint(1, maxv - 1)))
elif 50 < pre < 75: # 分数
num = Number('')
up = random.randint(1, int(maxv / 2))
num.frac = Fraction(up, random.randint(up, maxv))
return num
else:
num = Number('')
left = random.randint(1, maxv - 1)
up = random.randint(1, int(maxv / 2))
down = random.randint(up, maxv - 1)
num.frac = Fraction(
left * down + left,
down
)
return num
def create_char() -> str:
ch = ['+', '-', '×', '÷']
return ch[random.randint(0, 3)]
def create_lis(maxv: int) -> list:
nums = [3, 5, 7]
li = []
for i in range(nums[random.randint(0, 2)]):
if i % 2 == 0:
num = create_number(maxv)
li.append(num)
else:
li.append(create_char())
return li
def add_bracket(li: list) -> None:
if len(li) < 7:
return
tnum = [0, 2, 4]
index = random.randint(0, 2)
li.insert(tnum[index], '(')
li.insert(tnum[index] + 4, ')')
测试运行
对主函数进行测试的十个测试用例代码如下:
def test_demo1():
#参数输入不完全
main(['demo1','-n','10'])
def test_demo2():
#少量生成测试
main(['demo2','-n','10','-r','10'])
def test_demo3():
#少量生成交换参数测试
main(['demo3','-r','10','-n','10'])
def test_demo4():
#大量生成测试
main(['demo4','-r','1000','-n','1000'])
def test_demo5():
#错误数量测试
main(['demo5','-n','-1','-r','10'])
def test_demo6():
#普通的答案校对
main(['demo6','-e','Exercises.txt','-a','Answers.txt'])
def test_demo7():
#校对参数换位置
main(['demo7','-a','Answers.txt','-e','Exercises.txt'])
def test_demo8():
#问题文件不正确
main(['demo8','-e','Answers.txt','-a','Answers.txt'])
def test_demo9():
#答案文件不正确
main(['demo9','-e','Exercises.txt','-a','Exercises.txt'])
def test_demo10():
#文件路径不正确
main(['demo10','-e','66.txt','-a','111.txt'])
测试结果截图


在主函数中运行这十个测试用例,程序能够正常运行,并显示出执行结果,这进一步表明了程序的正确性。
项目小结
本次结对作业很好地锻炼了我们两个人的编码能力和对具体问题的分析能力,在编写主要函数的时候,遇到的问题主要是分数的表示和运算、怎样合理地随机生成表达式、怎样在表达式中插入括号、生成题目后如何对结果进行处理和测试等,面对这些困难,我们的解决办法是查阅相关资料,在编写函数的过程中逐个调试,比较不同算法的性能,对照题目具体要求,从而得到较好的函数。在这一过程中,并不是每一次都能十分顺利的解决问题,总是会在测试运行的时候得到错误的结果,导致很大一部分努力都白费,甚至要重新考虑其它方法,以至于重新编写函数体,这时也会让我们感到沮丧,但是这也让我们懂得了在编写项目中需要两个人共同合作,共同讨论解决策略,避免陷入情绪化的争论,要在遇到困难的时候相互沟通,交换彼此的想法,尊重对方的意见,一起学习和成长,相互支持和鼓励,这也是我们在这次结对项目中最大的收获。

浙公网安备 33010602011771号