项目 | 内容 |
---|---|
作业所属课程 | 2019软件工程_罗杰 |
作业要求链接 | 结对项目作业 |
课程目标: | 熟悉结对编程 |
该作业的帮助 | 实践了结对编程,对接对编程有了更深入的认识 |
1、本次作业github项目地址
2、开发前PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
- Estimate | - 估计这个任务需要多少时间 | 30 | |
Development | 开发 | ||
- Analysis | - 需求分析(包括学习新技术) | 240 | |
- Design Spec | - 生成设计文档 | 30 | |
- Design Review | - 设计复审 (和同事审核设计文档) | 20 | |
- Coding Standard | - 代码规范 (为目前的开发制定合适的规范) | 20 | |
- Design | - 具体设计 | 300 | |
- Coding | - 具体编码 | 480 | |
- Code Review | - 代码复审 | 200 | |
- Test | - 测试(自我测试,修改代码,提交修改) | 300 | |
Reporting | 报告 | ||
- Test Report | - 测试报告 | 120 | |
- Size Measurement | - 计算工作量 | 20 | |
- Postmortem & Process Improvement Plan | - 事后总结, 并提出过程改进计划 | 30 | |
合计 | 1790 |
3、看教科书和其它资料中关于Information Hiding, Interface Design, Loose Coupling的章节,说明你们在结对编程中是如何利用这些方法对接口进行设计的
- Information Hiding,信息隐藏,模块内部无需外部调用模块所知的则不可被外部调用者访问,保证模块数据安全。
- Interface Design,接口设计,再多模块的程序中,各模块之间进行数据交互时需要接口,使程序功能实现划分分明,由此可以增强程序的可拓展性,同时不影响各模块内部的运作。
- Losse Coupling,松耦合,消除模块之间不必要的依赖,只提供必要的外部接口,使模块的交互使用更加灵活,增强整个程序的可拓展性和灵活性。
在本次作业中践行结果:
- 类的内部通过private确保私有数据的安全性,public方法保证必需的方法得以被访问
- 本次作业我们并没有进行很复杂的类设计,内部计算的对外接口只有一个工作函数来完成此类职能范围内的功能
- 在本次作业中,c++核心算法模块提供完整的接口,c#部分对接收到的命令进行容错处理
4、计算模块接口的设计
计算模块是项目核心,计算功能封装在gen_chain_cpp函数接口中,重点在于从接受命令的外模块获取命令和单词,调用gen_chain_cpp函数计算出最长路径。
算法思路简介:根据函数获取的单词表,从中取得有效单词加入有效单词表中,建单词表的同时为每个单词建立后继表,计算入度,最终建立邻接链表。之后计算路径,对于是否有环的两种情况,首先会对单词进行拓扑排序,若能顺利进行拓扑排序,则是否有参数-r都采用动态规划算法;若不能顺利完成拓扑排序,则说明有单词环存在,此时检查是否有-r参数存在,没有则返回异常信息,有则采用深度优先算法逐个节点进行搜索。
算法关键及独到之处:在节点数据结构中同时存储了单词长度,因此计算时可根据-c和-w参数自由选择路径计算方式。在计算无环路径时,有无首字母要求的算法存在差异:若有首字母要求,则动态规划计算的起点只会选择符合首字母要求的单词,没有首字母要求时则是会选择入度为0的点作为起点进行计算。而对于有无确定尾字母的情况,根据动态规划算法的结果,每一个节点均会存储以该节点为结尾的最长链的路径和长度,因此只需在获取结果时选择符合尾字母要求的点,选出最长路径输出,无尾字母要求则直接从中选出最长路径输出。
5、UML图
6、计算模块接口部分的性能改进
计算模块接口部分的性能改进。 记录在改进计算模块性能上所花费的时间,描述你改进的思路,并展示一张性能分析图(由VS 2015/2017的性能分析工具自动生成),并展示你程序中消耗最大的函数
在完成程序的基本功能后,我们采用了一些数据对程序进行测试,在少量单词的数据下测试,我们修复了程序的一些逻辑问题,在能够正确运行小文本数据之后,我们利用一些大文本数据对程序进行测试,测试结果比较令人失望:由于数据结构的设计问题,程序出现了爆内存的问题。之后我们通过对数据结构进行重构优化,修复了这一问题,以下是一部分性能测试截图:
以上可以看出耗时最多的时进行动态规划计算时的函数,我们的动态规划计算性能还有提升空间。
以下是带有-r参数且图中有环的情况,可以看出searchpath作为深度优先递归函数被频繁调用:
由于采取暴力枚举的方法来进行有环路径的搜索,运行速度较慢,性能仍需要改进。
7、Design by Contract, Code Contract
Design by Contract,即契约式编程,Code Contract,即代码契约,这种方法要求软件设计者为软件组件定义正式的,精确的并且可验证的接口,这样,为传统的抽象数据类型又增加了先验条件、后验条件和不变式。这种方法的名字里用到的“契约”或者说“契约”是一种比喻,因为它和商业契约的情况有点类似。
代码契约的设计包括:前置条件,后置条件,类不变量。
(摘自百度百科)
在本次作业中,我们并没有严格按照契约式编程的方式来完成程序。
8、计算模块部分单元测试展示
以下是单元测试覆盖率截图:
为了对计算模块所能遇到的各种情况进行测试,我们采用了大量测试样例对程序进行测试,以下仅展示部分单元测试代码:
9、计算模块部分异常处理说明
根据可能出现的情况,我们对以下9种异常情况做了处理:
1、出现除了"-r -c -w -t -h"以外的关键字,如"-x"
单元测试用例:
2、-c -w同时出现
单元测试用例:
3、同一种参数重复出现,如 -t a -t a 或 -w -w
单元测试用例:
4、-c和-w参数缺失
单元测试用例:
5、-h 后面缺少字符
单元测试用例:
6、-t 后面缺少字符
单元测试用例:
7、命令中出现多余字符
单元测试用例:
8、文件打开失败
9、缺少-r参数的情况下文本有环,该情况由计算模块通过拓扑排序后得出文本是否存在单词环,返回信息给界面模块进行异常处理
10、界面模块的详细设计过程
界面我们仅采用简单的命令行方式处理:
以下是命令行界面:
11、界面模块与计算模块的对接
界面模块的对接就是界面模块从命令行获取所需数据,之后调用计算模块方法对计算模块进行调用,计算模块返回处理结果信息后,界面模块作出反馈。
12、描述结对过程
在结对过程中,我们两人本身并不熟悉彼此,从一开始尝试了解对方,然后开始对结对作业进行讨论,然后分配任务,由于我们两人并不属于同一专业,居住区域相隔较远,因此我们作业的完成过程大多采用线上的方式进行,尽量在有空的时候两人见面进行讨论。
由于是第一次进行结对编程,缺乏经验,且两人并不熟悉,开始的效率并不是很高,我们也经常会出现进度不同步进度滞后的情况。
在经历了坎坷和磨合的过程之后,我们两人的配合效率也得到了提高,双方互相反馈各自主要负责部分的问题,进行修改,最终也是顺利完成了结对项目。
总体来说这次结对过程给了我很新鲜的体验,第一次与比较陌生的人配合一起完成一个项目,两人通过不断地磨合最终也算是磕磕绊绊地完成了这次作业,对我来说算是一次收获颇丰的体验。
13、结对编程反思
结对编程的优点:
- 在结对过程中,通过两人的讨论配合,可以更高效的确定方案,尤其是在确定程序处理算法的过程中两人可以共同收集可用的算法并讨论确定最终算法,结对的过程很大的提升了这一过程完成的效率。
- 两人在结对过程中可以学习并养成更好地代码规范,来确保自己的搭档可以顺畅的阅读并理解对方的代码。
- 两人可以从对方可以互补缺点,从对方身上学到自己所不具备的技能。
结对编程的缺点: - 结对过程中两人可能会对某一问题出现摩擦,无法统一意见的情况会降低效率。
- 结对过程由于两人所了解熟悉的方面不同可能会演变成各自完成各自的工作而难以顾及对方的工作。
队友的优缺点 - 优点:非常刻苦努力,工作能力很强,完成工作的效率很高,很负责,经常提醒我完成进度。学习能力很强,不了解的内容能够在短时间内完成学习。
-缺点:由于并非计算机专业的学生,在编程及算法的能力上有部分欠缺(尽管我自己的能力也并不优秀)。
自己的优缺点 - 优点:身为计算机学院的学生,对算法的积累相对较多,在对方给自己提出要求和提醒后及时的反馈并完成自己的任务。
- 缺点:较为懒散,如不是队友提醒,可能会使进度滞后很多。
14、PSP表格回填
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
- Estimate | - 估计这个任务需要多少时间 | 30 | 60 |
Development | 开发 | ||
- Analysis | - 需求分析(包括学习新技术) | 240 | 200 |
- Design Spec | - 生成设计文档 | 30 | 60 |
- Design Review | - 设计复审 (和同事审核设计文档) | 20 | 20 |
- Coding Standard | - 代码规范 (为目前的开发制定合适的规范) | 20 | 10 |
- Design | - 具体设计 | 300 | 500 |
- Coding | - 具体编码 | 480 | 600 |
- Code Review | - 代码复审 | 200 | 300 |
- Test | - 测试(自我测试,修改代码,提交修改) | 300 | 500 |
Reporting | 报告 | ||
- Test Report | - 测试报告 | 120 | 60 |
- Size Measurement | - 计算工作量 | 20 | 10 |
- Postmortem & Process Improvement Plan | - 事后总结, 并提出过程改进计划 | 30 | 20 |
合计 | 1790 | 2340 |
ps:由于在完成项目的过程中,我们并没有准确的时间把控,以上所得出的实际时间也是我们在之后统计时间时进行的估计,并不完全准确。
15、模块松耦合
按照作业接口要求封装dll后,我们和16091049 16061057互换了Core,我们能正常使用对方的c++ dll,对方调用时却不能看到函数接口问题,但我方自测dll时用c#调用可以正常工作,可能与c++调用c#dll方式有一定关系。