这个做业属于以下课程:软件工程
这个做业的要求位于以下连接:结对编程
我在这个课程的目标是:锻炼复杂软件开发能力,取得大于85分的成绩。
这个做业在以下方面帮助我实现目标:快速上手C++语言;将结对编程、单元测试、添加注释、抛出异常等付诸实践。git
一、在文章开头给出GitHub项目地址。
项目地址程序员
二、在开始实现程序以前,在下述PSP表格记录下你估计将在程序的各个模块的开发上耗费的时间。
见附录部分。github
三、看教科书和其它资料中关于Information Hiding, Interface Design, Loose Coupling的章节,说明大家在结对编程中是如何利用这些方法对接口进行设计的算法
In computer science, information hiding is the principle of segregation of the design decisions in a computer program that are most likely to change, thus protecting other parts of the program from extensive modification if the design decision is changed.编程
——引用自维基百科"Information Hiding"
我对Information Hiding比较有感触的是处理来自文件的输入的子程序。在第一遍实现时,咱们将文件读入和解析的功能所有写在一个readFile函数中,鼓捣了半天也没调通。以后,我重写了这一部分代码:readFile函数只负责不停地以行为单位读取文件中的内容,而具体解析的工做交由另外一个process_line函数完成。重写后的代码长度更短,并且调试花费的时间更少。在这个例子中,process_line向readFile函数隐藏了解析用户输入的信息。并且,一旦用户输入的格式发生变化,通常只须要修改process_line函数便可;代码的可维护性较好。app
没有找到太多资料。核心模块的函数接口在做业要求的基础上略做修改(例如使用了vector和string),其他函数基本遵循以下原则:名称易于理解、参数尽量少。less
In computing and systems design a loosely coupled system is one in which each of its components has, or makes use of, little or no knowledge of the definitions of other separate components. Subareas include the coupling of classes, interfaces, data, and services.
Components in a loosely coupled system can be replaced with alternative implementations that provide the same services. Components in a loosely coupled system are less constrained to the same platform, language, operating system, or build environment.ide
——引用自维基百科"Loose Coupling"
咱们没有完成选作做业“松耦合”,对松耦合的支持不够好:咱们将FileInput类的一个对象做为了wordHandler的成员变量,为以后写单元测试代码带来了必定的麻烦。更好的作法是让wordHandler仅拥有一个存有文件中全部单词的容器(例如vector
四、计算模块接口的设计与实现过程。
在设计之初,为了下降代码单元间的耦合度,咱们将整个程序拆分为3个类:FileInput读取用户文件,wordHandler寻找单词链,output将单词链以文件形式输出。这样的设计使得各个代码单元之间尽可能分离,避免纠缠不清,形成修改困难。性能
在算法上,咱们采用蛮力算法进行求解。尽管在单词数量增多后难以取得使人满意的性能,可是可以返回最优解,而不是像某些算法只能返回近似解。
五、画出UML图显示计算模块部分各个实体之间的关系。
六、计算模块接口部分的性能改进。
因为采用蛮力算法,且时间有限,咱们未对计算模块进行性能改进。一个可能的方向是将全部单词排序,而后采用索引查找方法,以提升时间效率。
性能分析图以下:
七、看Design by Contract, Code Contract的内容;描述这些作法的优缺点, 说明你是如何把它们融入结对做业中的
契约式设计在同一个软件项目的开发人员之间造成契约:在前置条件下,程序员必须保证本身编写的方法维持了不变式内容,且知足后置条件。其优势是程序员能够认为前置条件为真而无需进行大量检查。其缺点是不遵照契约的程序员会为整个项目带来巨大破坏,并且程序员须要多花一部分时间撰写契约规格。
本次做业中,咱们未能使用契约式设计,形成了一些不良后果。一个典型的错误是某个变量究竟表明容器中元素的个数仍是下标的最大值(两者差1)。这一点两人事先没有约定好,最终形成了BUG的发生。
八、计算模块部分单元测试展现。
TEST_METHOD(TestMethod1) { FileInput fin; fin.readFile("D:\\word_chain\\01.txt"); wordHandler wh(fin); char *words[20]; vector<string> result; wh.gen_chain_word(words, 0, result, 0, 0, false); Assert::IsTrue(result.at(0) == "apple"); Assert::IsTrue(result.at(1) == "elephant"); Assert::IsTrue(result.at(2) == "toad"); } TEST_METHOD(TestMethod2) { FileInput fin; fin.readFile("D:\\word_chain\\02.txt"); wordHandler wh(fin); char *words[20]; vector<string> result; wh.gen_chain_char(words, 0, result, 0, 0, false); Assert::IsTrue(result.at(0) == "pseudonym"); Assert::IsTrue(result.at(1) == "moon"); }
01.txt
apple
elephant
toad
方法1测试了gen_chain_word方法的正确性,状况设置得比较简单:在输入上没有设置干扰单词,且给出的单词顺序就是链的顺序。
02.txt
leaf, fox
pseudonym, moon
moon
方法2测试了gen_chain_char方法的正确性,状况较为复杂:设置了重复的单词做为干扰项。
咱们还编写了其它单元测试代码,限于篇幅没法一一展现,请前往GitHub项目地址查看相应代码。
九、计算模块部分异常处理说明。
十、界面模块的详细设计过程。
按指导书中的命令行参数,设计了解释程序。如出现'-r',则将对应的bool型变量置为true,'-h'则按顺序读入下一个命令行参数,将其复制给char型变量,'-t'同上。'-w'先按顺序读入下一命令行参数做为文件路径,调用gen_chain_word()接口;'-c'同上,不一样在于调用gen_chain_char()接口。读到文件路径后完成对命令行的解析。
while (true) { con = false; switch (ptr[1]) { case 'r': recur = true; con = true; break; case 'h': ptr++; head = *ptr; con = true; break; case 't': ptr++; tail = *ptr; con = true; break; case 'w': fun = 'w'; break; case 'c': fun = 'c'; break; default: break; } if (con) { i++; ptr = argv[i]; continue; } else { break; } } try { fin.readFile(argv[i + 1]); } catch (FINException& fine) { fine.what(); return 0; } if (fun == 'w') { wordHandler whword(fin); whword.gen_chain_word(_words, _len, result, head, tail, recur); } else if (fun == 'c') { wordHandler whchar(fin); whchar.gen_chain_char(_words, _len, result, head, tail, recur); } else { cout << "Invalid command!" << endl; }
十一、界面模块与计算模块的对接。
咱们在main函数中实例化了FileInput, wordHandler两个类的对象,wordHandler的构造方法传入FileInput类的对象。main函数接受了命令行参数后,将识别的文件路径传入FileInput的相关方法,从而实现对接。
十二、描述结对的过程,提供非摆拍的两人在讨论的结对照片。
我和杨亦鑫是隔壁班的同窗,之前在打篮球时有过接触。课程开始后,咱们分别进入了不一样的团队。所以,咱们符合结对编程的条件,通过简短的沟通后正式结对。
咱们结对编程的形式主要是先由我约一个两人都方便的时间,而后来到新主楼2层,找一个走廊里的座位,开始结对编程。
因为是初次接触结对编程形式,咱们在实际操做中出现了必定的问题。我在时间控制上不太敏感,常常是连续工做了一个多小时而忘记了交换角色。领航员有时候注意力开了小差,没有进行随时复审。不过两人合做的氛围较为轻松愉快,没有发生剧烈冲突。
总的来讲,此次结对编程并未提升咱们的工做效率。可是,因为是两我的一块复审,咱们最终仍是发现了很多BUG,并且对于每一个概念上的错误都能在过后牢记。此次体验对个人开发能力有所促进,但也提出了更高的要求。
1三、说明结对编程的优势和缺点。结对的每个人的优势和缺点在哪里 (要列出至少三个优势和一个缺点)。
优势1:写代码和查API的工做能够交由两人并行完成,既提升了效率也造成了知识的共享。
优势2:定时休息能够避免一我的长时间敲代码(这种状况经常致使BUG数增长)
优势3:错误被发现时两人都留下了深入的印象。
缺点1:做为课程的一部分时,结对编程须要在两个学生都有空的时候进行,并且缺少好的环境(大运村没有公共休息室),所以效果打了折扣。
1四、在你实现完程序以后,在附录提供的PSP表格记录下你在程序的各个模块上实际花费的时间。
见附录。
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | 估计这个任务须要多少时间 | 15 | 4 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 180 | 120 |
· Design Spec | · 生成设计文档 | 240 | 0 |
· Design Review | · 设计复审 (和同事审核设计文档) | 60 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 120 | 0 |
· Design | · 具体设计 | 480 | 20 |
· Coding | · 具体编码 | 1440 | 480 |
· Code Review | · 代码复审 | 480 | 180 |
· Test | · 测试(自我测试,修改代码,提交修改) | 960 | 120 |
Reporting | 报告 | ||
· Test Report | · 测试报告 | 480 | 30 |
· Size Measurement | · 计算工做量 | 45 | 5 |
· Postmortem & Process Improvement Plan | · 过后总结, 并提出过程改进计划 | 60 | 5 |
合计 | 4560 | 964 |