项目 | 内容 |
---|---|
这个做业属于哪一个课程? | 北航软工 |
这个做业的要求在哪里? | 第一次结对做业 |
我在这个课程的目标是? | 学习高效严谨的软件工程开发过程,创建团队意识 |
这个做业在哪一个具体方面帮助我实现目标 | 熟悉并了解软件工程的基本知识,创建兴趣 |
项目有两个分支,master分支是命令行形式,UI分支是带GUI的程序。c++
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
· Estimate | · 估计这个任务须要多少时间 | 30 | 30 |
Development | 开发 | 815 | 1200 |
· Analysis | · 需求分析 (包括学习新技术) | 30 | 120 |
· Design Spec | · 生成设计文档 | 30 | 90 |
· Design Review | · 设计复审 (和同事审核设计文档) | 15 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 15 |
· Design | · 具体设计 | 50 | 30 |
· Coding | · 具体编码 | 300 | 600 |
· Code Review | · 代码复审 | 60 | 90 |
· Test | · 测试(自我测试,修改代码,提交修改) | 300 | 500 |
Reporting | 报告 | 240 | 195 |
· Test Report | · 测试报告 | 120 | 120 |
· Size Measurement | · 计算工做量 | 15 | 15 |
· Postmortem & Process Improvement Plan | · 过后总结, 并提出过程改进计划 | 105 | 60 |
合计 | 1085 | 1700 |
信息隐藏是指在设计和肯定模块时,使得一个模块内包含的特定信息(过程或数据),对于不须要这些信息的其余模块来讲,是不可访问的。 在咱们的设计过程当中,模块除了被调用的两个接口或者说成员函数之外,其余的成员都是private
属性的,它如何实现算法,如何存储数据,过程当中某个变量的值如何,都与外部无关,从外部不可访问和修改,保证编程的安全性。git
对调用者和使用者而言,不须要知道函数内部的实现,只须要掌握接口的信息。接口设计主要是做用和反作用的明确性,若是接口应该一开始就设计的比较成熟,这样咱们修改实现接口的程序时,调用接口的程序就不用修改。咱们设计的两个接口,约定了函数的具体做用即以不一样的方式寻找最长单词链,约定了传入参数的具体意义,而且规定了只能修改char * result
变量做为结果的输出,其余的参数应该不改变。程序员
松耦合和接口设计是相辅相成的。只有在规定好接口规范之后,才能实现进一步的解耦合。咱们只规定接口的做用,而不规定接口的内容。这样不一样组件之间能够轻易地作到互相独立。github
咱们在完成代码编写后,与其余组同窗互换了GUI和DLL,另外一个组是周二的白世豪(16061167),宋卓洋(16061170)组。因为生成dll的教程相似,并无出现什么问题,对于无异常状况能够正常运行,以下图所示:算法
其中Core.dll是咱们生成的dll,DLL1.dll是另一个组的dll,通过测试,加载两个dll时GUI的行为一致。
编程
整个程序的逻辑大体以下图所示:设计模式
由于GUI程序是不会涉及到普通的参数正确性的(只有关于指定头尾的字母是否正确),因此 出于解耦合的须要,咱们并无将处理参数的程序集成在Core类之中,而是独立出来,在main函数中判断参数的正确性。Core类中确保接受到的是正确的单词组char *words[]
和其余合适的参数。咱们暴露在外的只有两个接口。安全
int gen_chain_word(char* words[], int len, char* result[], char head, char tail, bool enable_loop); int gen_chain_char(char* words[], int len, char* result[], char head, char tail, bool enable_loop);
其余的部分以private
成员的形式,供内部使用。微信
而后每一个接口中对单词的处理也须要分红两种。
\\没有-r选项,检测有环时直接报错,无环时以宽度优先搜索的形式(不会陷入死循环)找到最长单词链; \\有-r选项,不须要检测是否有环,直接以深度优先搜索的形式搜索最长单词链; \\伪代码以下 if(!enable_loop) { roundtest();//有环时抛出错误 createMap();//创建bfs的地图 BFS();//宽度优先搜索 getBFSResult();//处于节省时间和空间的考虑,上一步宽度优先搜索并无保存路径,而是得出了最长的长度,而后根据长度倒推出路径。 } else { createMap();//创建dfs的地图 DFS();//深度优先搜素 getDFSResult();//推导最终路径,缘由同上 }
基础的函数大体就是这些,两种类型chain_word
和chain_char
的各有一套。而后咱们还引入了get_tails()
就是在扫描边的时候,排除不可能的首尾选项。大体原理就是当不成环的时候,出度为0的点才多是尾字母,不然不多是最长链。这样咱们能够剪枝,减小搜索时的复杂度。
使用了自动化工具生成类图与调用关系,参考工具Github,生成的调用关系以下: 手画类图以下,咱们的类关系至关简单。
总体上说,咱们采起了BFS解决没有-r的状况,使用DFS解决有-r的状况。
首先是没有-r的部分。因为算法在设计之初就已经考虑到了一些优化,咱们重复执行同一条指令50次,取得更好的采样效果。如图所示,整个算法的耗时最长是在建图与删重边。程序在输入8000个单词时运算时间在1s之内。所以没有作进一步改进,这里介绍一下完成的优化。
咱们主要完成了如下几个优化:
在含有-r的部分,考虑到这是一个NP问题,并且要求的是准确解,不是近似解,咱们采用回溯法进行深度搜索。程序输入90个单词,摘自Wikipedia的一个随机网页,运行时间3分04秒。
能够发现,程序在DFS上耗费了大量的时间。咱们对于这种模式依然作了一些优化,咱们同BFS同样减小了可能的起点,由于起点的出度>=入度,终点的入度>=出度,也有必定效果。
此外,咱们还在总体上对程序进行了优化。考虑处处理器支持AVX指令集,咱们在编译选项中选择了支持生成AVX2指令的编译选项,取得了不错的效果,对于一组较复杂的测试用例,运行时间从2分58秒减小到2分03秒,提高接近1/3。
契约式设计要求软件设计者为软件组件定义正式的,精确的而且可验证的接口,接受一个合规的输入,并保证合规的输出。根据百科的定义来看,这种设计模式重在精确二字。
本次结对做业中,首要契约是做业要求中规定的接口,这个下降了沟通的一部分任务。实际编程中咱们制定的契约主要是双方完成的函数方法部分对于类成员的行为,以及对于异常状况的处理。在如此契约之下,咱们才完成了从Core
类到GUI的低耦合。
单元测试总体覆盖率91%。未覆盖到的部分主要是抛出异常的if语句。
计算模块暴露的接口共有两个,分别为
咱们对其进行了单元测试。测试的流程是测试程序加载一组测试数据,放入char * words[]中,与一些参数一块儿传入函数,获得返回的result后加载标答并逐个比较,以下面的代码片断所示:
TEST_METHOD(TestMethod1) { Core * core = new Core(); // do sth to update words core->gen_chain_word(words1, len, result1, 0, 0, false); // get true value into realAnswer Assert::AreEqual(51, length_of_result1); for (int i = 0; i < length_of_result1; i++) { Assert::AreEqual(strcmp(result1[i], realAnswer[i]), 0); } }
对于正常数据,咱们使用随机生成+对拍的方式检验。 对于异常数据,咱们构造了如下几个特殊状况:
其中对于有环的状况,咱们还分了如下几种状况:
如下为单元测试展现,因为太长默认收起。
注意,请依次运行每一个单元测试,不要一块儿运行,防止出错。
TEST_METHOD(TestMethod1) { Core * core = new Core(); int len = readFile1("../WordChainUnitTesr/words1.txt"); core->gen_chain_word(words1, len, result1, 0, 0, false); int len2 = readFile1("../WordChainUnitTesr/solution1.txt"); Assert::AreEqual(51, len2); for (int i = 0; i < len2; i++) { Assert::AreEqual(strcmp(result1[i], words1[i]), 0); } }其中 words1.txt, solution1.txt能够在Github上找到。