零、前言
- 本次作业要求个人编写程序,截止日期2019年9月25日23:00。
- 请先阅读《构建之法》第一章至第三章的内容,并在下方作业里体现出阅读后的成果。特别是第2章中的效能分析及个人软件开发流程(PSP)。
一、编码要求
- 在Github仓库中新建一个学号为名的文件夹。
- 在开始实现程序之前,在PSP表格[附录1]记录下你估计在程序开发各个步骤上耗费的时间,在你实现程序之后,在PSP表格记录下你在程序的各个模块上实际花费的时间。
- 使用C++ 或者Java语言实现,C++请使用Visual Studio Community 2017进行开发,运行环境为64-bit Windows 10。
- 提交的代码要求经过Code Quality Analysis工具的分析并消除所有的警告。
- 完成项目的首个版本之后,请使用性能分析工具Studio Profiling Tools来找出代码中的性能瓶颈并进行改进。
- 使用Github[附录2]来管理源代码和测试用例,代码有进展即签入Github。签入内容请注意测试须知的组织目录,其余的文件(包括单元测试)不必上传,使用.gitignore忽略。签入记录不合理的项目会被助教抽查询问项目细节。
- 使用单元测试[附录3]对项目进行测试,并使用插件查看测试分支覆盖率等指标;并写出至少10个测试用例确保你的程序能够正确处理各种情况。
二、博客撰写要求
- 在文章开头给出Github项目地址。
- 给出PSP表格。
- 解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的过程。
- 设计实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?单元测试是怎么设计的?
- 记录在改进程序性能上所花费的时间,描述你改进的思路。
- 代码说明。展示出项目关键代码,并解释思路与注释说明。
- 结合在构建之法中学习到的相关内容,撰写解决项目的心路历程与收获。
三、需求
实现一个命令行程序,不妨称之为Sudoku。
百度百科简介:
数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。
具体任务:
现在我们想一步一步来,完成从三宫格到九宫格的进阶;完成三宫格和其他博客任务,就算过了初级考核,其他的算升级。具体各阶规则如下:
三宫格:盘面是3*3。使1-3每个数字在每一行、每一列中都只出现一次,不考虑宫;
四宫格:盘面是2*2四个宫,每一宫又分为2*2四个小格。使1-4每个数字在每一行、每一列和每一宫中都只出现一次;
五宫格:盘面是5*5。使1-5每个数字在每一行、每一列中都只出现一次,不考虑宫;
六宫格:盘面是2*3六个宫,每一宫又分为3*2六个小格。使1-6每个数字在每一行、每一列和每一宫中都只出现一次;
七宫格:盘面是7*7。使1-7每个数字在每一行、每一列中都只出现一次,不考虑宫;
八宫格:盘面是4*2八个宫,每一宫又分为2*4八个小格。使1-8每个数字在每一行、每一列和每一宫中都只出现一次;
九宫格:盘面是3*3九个宫,每一宫又分为3*3九个小格。使1-9每个数字在每一行、每一列和每一宫中都只出现一次;
输入:
输入文件名以命令行参数传入。例如我们在命令行窗口(cmd)中输入:
Sudoku.exe -m 9 -n 2 -i input.txt -o output.txt
其中各参数一定会出现,意义如下:
- -m 宫格阶级(3~9的整数)
- -n 待解答盘面数目
- -i 指定输入文件
- -o 指定程序的输出文件
输入文件说明:
总共包含n个盘面,每两个盘面间空一行,每个盘面中,每两个小格之间有一个空格;待填入的格子用0代替。输入保证有且仅有一个解,所编写的程序不需要考虑无解时的输出。
上面的命令行对应的输入文件input.txt如下:
0 0 8 0 0 4 0 0 9
0 6 0 0 0 0 1 0 0
0 3 7 0 0 0 0 0 0
8 0 1 2 6 9 0 0 3
0 2 5 4 7 0 0 6 8
0 9 0 0 0 5 0 0 0
9 0 0 1 5 2 3 7 4
0 4 0 3 9 8 0 1 6
1 5 3 6 4 7 8 0 2
2 0 0 0 0 0 0 0 0
0 0 6 3 0 0 0 7 0
5 0 0 0 0 0 1 0 0
9 6 7 4 0 0 0 0 5
8 1 3 0 0 0 0 0 0
4 2 0 7 1 8 9 6 3
3 5 0 0 4 1 6 9 7
6 9 8 2 7 3 5 4 1
0 4 0 0 5 9 2 0 8
输出:
输出n个程序解出的盘面,每两个盘面间空一行,每个盘面中,每两个小格之间有一个空格。
上面的命令行对应的输出文件output.txt组织如下:
5 1 8 7 2 4 6 3 9
2 6 9 5 8 3 1 4 7
4 3 7 9 1 6 2 8 5
8 7 1 2 6 9 4 5 3
3 2 5 4 7 1 9 6 8
6 9 4 8 3 5 7 2 1
9 8 6 1 5 2 3 7 4
7 4 2 3 9 8 5 1 6
1 5 3 6 4 7 8 9 2
2 7 9 1 8 4 3 5 6
1 8 6 3 2 5 4 7 9
5 3 4 9 6 7 1 8 2
9 6 7 4 3 2 8 1 5
8 1 3 5 9 6 7 2 4
4 2 5 7 1 8 9 6 3
3 5 2 8 4 1 6 9 7
6 9 8 2 7 3 5 4 1
7 4 1 6 5 9 2 3 8
四、测试须知
组织目录
助教在测试时,将运行自动测试程序编译源文件并运行,进行批量测试,因此请保证项目的组织目录符合要求
Java
对于使用Java语言的项目有以下两点要求:
- 【以学号为名的文件夹中】的目录下必须有src文件夹
- 在src目录下必须有名为Main.java文件,且Main.java中包含 public static void main(String[] args) 方法
一个Java项目的示例组织目录如下所示:
031702188 (文件夹名字为学号)
|- src
|- Main.java(主程序,可以从命令行接收参数)
|- lib.java(包含其它自定义函数,可以有多个,对名字不做要求)
C++
对于使用C++ 语言的项目有以下要求:
- 【以学号为名的文件夹中】的目录下必须有src文件夹
- 在src文件夹中是可在VS2017下编译运行的解决方案,解决方案的名字必须为 Sudoku。
一个C++工程示例组织目录如下所示:
031702188 (文件夹名字为学号)
|- src
|- Sudoku.sln
|- Sudoku
|- stdafx.cpp
|- stdafx.h
|- Sudoku.cpp
|- Sudoku.vcxproj
助教在测试时,将自动按照指定编译环境编译源代码,并利用命令行进行批量测试。
错误处理
本次自动测试会加入各种各样出错情况的测试,要求开发者程序不能崩溃,并且能够尽可能精确报错。你可以有“容错性”的出错设计,但必须输出必要的提示或说明。
五、评分规则
博客评分规则
以下可以作为同学们写博客的提纲参考,具体分数可能会做修改,修改时再提醒。(40'+10')
- 在文章开头给出你的仓库的Github项目地址。(1')
- 在开始实现程序之前,在下述PSP表格记录下你估计将在程序的各个模块的开发上耗费的时间。(5')
- 计算模块接口的设计与实现过程。 设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?说明你的算法的关键(不必列出源代码),以及独到之处。 (20')
- 计算模块接口部分的性能改进。 记录在改进计算模块性能上所花费的时间,描述你改进的思路。(3')
- 计算模块部分单元测试展示。 展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路;测试数据有覆盖到所有的代码吗?并将单元测试得到的测试结果,发表在博客中。 (5')
- 计算模块部分异常处理说明。 在博客中详细介绍每种异常的设计目标。每种异常都要选择一个单元测试样例发布在博客中,并指明错误对应的场景。(4')
- 在你实现完程序之后,在附录提供的PSP表格记录下你在程序的各个模块上实际花费的时间。 (2')
- 完成三宫格之上的更高阶级,并在以上各个条目体现出来。(10')
程序评分规则
正确性(20'+30')
- 完成三宫格(20')
- 之后的阶级每完成一个(5')
六、附录
1.PSP表格
PSP是卡耐基梅隆大学(CMU)的专家们针对软件工程师所提出的一套模型:Personal Software Process (PSP, 个人开发流程,或称个体软件过程)。
Planning | 计划 | ||
Estimate | 估计这个任务需要多少时间 | ||
Development | 开发 | ||
Analysis | 需求分析 (包括学习新技术) | ||
Design Spec | 生成设计文档 | ||
Design Review | 设计复审 | ||
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | ||
Design | 具体设计 | ||
Coding | 具体编码 | ||
Code Review | 代码复审 | ||
Test | 测试(自我测试,修改代码,提交修改) | ||
Reporting | 报告 | ||
Test Repor | 测试报告 | ||
Size Measurement | 计算工作量 | ||
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | ||
合计 |
一个功能完备的程序不是一蹴而就的。可将一个大任务划分为可操作的小任务,同时最好按照任务难度或紧急程度指定各个任务的完成次序。因此,在动手开发之前,要先估计将在程序各模块开发所需耗费的时间,以及完成整个项目所需的时间,将这个[估计值]记录下来,写成PSP 的形式。
PSP的目的是:记录工程师如何实现需求的效率,和我们使用项目管理工具(例如微软的Project Professional,或者禅道等)进行项目进度规划类似。
有关PSP的更多内容,请自行阅读邹欣老师的博客:工程师的能力评估和发展
2.Github
请阅读邹欣老师的博客:源代码管理,了解源代码管理的10个实践问题。
本次作业要求使用Github进行源代码管理,代码有进展即签入Github。签入记录不合理的项目会被助教抽查询问项目细节。
对代码签入的具体要求如下:根据需求划分功能后,每做完一个功能,编译成功后,应至少commit一次。具体的功能划分,请自行定义,并在撰写博客时体现出来,遵循自己对需求的功能划分来提交代码即可。
对Commit不是很熟悉的话,请阅读阮一峰的博客:Commit message 和 Change log 编写指南,了解更多细节。
3.单元测试
请根据自己以往积累的测试经验,在编码完成之后,提交产品之前,设计测试用例,并编写单元测试,对自己的项目进行测试。
首先,至少应采用白盒测试用例设计方法来设计测试用例,其他测试方法不限。其次,要设计至少10个测试用例,确保你的程序能够正确处理各种情况。最后,结合测试评估的要求,对自己的测试设计进行评价,这些测试用例能满足该程序测试的要求吗?
另一个重要的措施是要把单元测试自动化,这样每个人都能很容易地运行它,并且可以使单元测试每天都运行。每个人都可以随时在自己的机器上运行。团队一般是在每日构建中运行单元测试的,这样每个单元测试的错误就能及时被发现并得到修改。
推荐阅读邹欣老师的博客:关于单元测试和回归测试