结对编程项目-最长英语单词链
1.课程班级及项目地址
- 教学班级:周五班
- 项目地址:最长单词链
2.预估&实际耗时
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 15 |
· Estimate | · 估计这个任务需要多少时间 | 900 | 1000 |
Development | 开发 | 630 | 560 |
· Analysis | · 需求分析 (包括学习新技术) | 80 | 140 |
· Design Spec | · 生成设计文档 | 40 | 50 |
· Design Review | · 设计复审 (和同事审核设计文档) | 20 | 25 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 15 | 20 |
· Design | · 具体设计 | 50 | 40 |
· Coding | · 具体编码 | 300 | 350 |
· Code Review | · 代码复审 | 40 | 55 |
· Test | · 测试(自我测试,修改代码,提交修改) | 180 | 220 |
Reporting | 报告 | 180 | 150 |
· Test Report | · 测试报告 | 90 | 80 |
· Size Measurement | · 计算工作量 | 20 | 30 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 10 | 15 |
Total | 总计 | 2565 | 2750 |
3.看教科书和其它资料中关于 Information Hiding,Interface Design,Loose Coupling 的章节,说明在结对编程中是如何利用这些方法对接口进行设计的。
Information Hiding:在编写代码时,我们并没有建立其他的类,唯一需要引用的我们自己写的外部文件是core.dll,在函数的接口方面,和课程组提供的接口是大致相同的,除了我们利用的是vector作为容器,这方面安全性应和课程组的接口安全性一致。
Interface Design:在接口设计方面,我们对于函数传入和传出的参数都进行了规范,除了一些必要的参数(关乎我们使用的容器,比如vector),我们都和课程组提供的接口参数保持了高度一致。比如对于输出部分的函数output,我们定义为int output(char* result[], int paraN, int paraM, int paraW, int paraC)
,result[]
是保存结果的数组,其他四个int
型参数以0或1来标记是否存在。
Loose Coupling:在设计上,为减少模块间的依赖,整个程序被我们大致分为了输入,计算,输出三个部分,每个模块再由对应的一个或几个函数组成,以减少模块间的相互依赖(不过貌似必须层层递进,上一步做完这一步才能做,这也算一种依赖?)。
4.计算模块接口的设计与实现过程
计算模块的接口设计是按照课程组要求来进行设计的。
为了方便计算,我们在实现函数时对vector
数组和char*
数组进行了互相转换。将传入的char*
数组转换为vector
数组,由vector
数组来进行核心计算。计算完成后再转换为char*
数组保存结果。
具体算法实现为,将传入的单词利用二分法去重转换成全小写字母加入到vector
数组中,再对不同首字母单词分类保存,这样知道该尾字母就可以立马找到下一个所需单词了,也就相当于构造了一个有向图,以便后续计算单词链。计算中最需时间的部分就是计算单词链了,该部分我们则是对上面图每个结点作为起点进行了一次遍历,将每个单词开头所能找到的走到尽头的单词链全部找到(无环和有环计算过程一致,但会因为传入的参数是否有-r来判断是否进行错误检查)。最后则是根据需求对链进行分割或者是判断最长,均是对上述找到的最长单词链进行一次遍历。
5.UML
计算模块的UML图如下:
6.性能改进
在输出所有单词链情况下,在性能占用方面,检查去重的开销尤为巨大(如上图所示)。我们对此尝试了优化处理。经发现,output数组中存在着由上一步走到尽头的单词链回退一步后的单词链,这对性能造成了一部分损失,我们对此进行了优化。在相同输入情况下,优化前后对比如下:
可以发现,用时及CPU占用相对都减少了。
7.Design by Contract,Code Contract
契约式设计在双方合作时能够使得双方的代码更好地契合起来,便于双方相互理解,能大幅提高代码阅读效率,便于之后的代码复审,出错时也能更有效地排查。缺点则是需要花费一定时间来制定双方都能满意的规范,且对双方都有一定的适应性要求,需要一段时间来适应,会一定程度上影响效率。
在此次代码编写时,我们对各种错误(我们认为的)都进行了分析,并在出错时对程序执行结束,用以避免出现其他情况以致误判。
8.单元测试
本部分主要是对core部分的4个函数进行测试及参数覆盖。
在构造测试样例时,我们主要是对参数进行组合来进行测试部分,对所有合法组合进行测试,以达到最后的结果。
以下只展示一部分:
-c及-r测试
-c及-h测试:
最后的代码覆盖率:
9.异常说明
这里借用项目中的表格来进行展示:
因为以上输出均是在标准输出中,所以这里利用命令行程序来表示错误的实现(这里对保存单词链的数组最大开到了20010,实现这个比较困难,因为会数组越界,导致vs报错,但是最后还是得到了结果):
单词链数量过大利用了以下的测试文本:
出错输出如下:
10&11 界面部分
本组并未进行UI设计,故这两部分缺失
12 结对部分
合作截图如下:
结对是由另一位同学找到我,经多方面评估认为实力相当进行了结对。
13.结对编程优缺点
优点:可以弥补两个人之间互有的不足之处,发挥长板效应,依据能力分配各自任务。
缺点:需要一定契合度,两者思考进度无法保证一致,会导致代码完成时的一定时间上的延迟。
优缺点 | 我 | 结对伙伴 |
---|---|---|
优点 | 沟通回应及时;代码完成较好;可以提出一些比较好的建议 | vs使用能力强;对代码理解及编写较快;做事迅速 |
缺点 | 写代码较慢,需要查阅些资料才能更好下手 | 消息回复延迟较高 |