第三次作业
结对编程WordCount
作业链接: | https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/homework/2882 |
GIT仓库地址: | https://github.com/wangli20173106/WordCount |
结对人员: | 201731062318王力;201731062315余希伦 |
1.结对项目PSP编写
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
30 |
20 |
· Estimate |
· 估计这个任务需要多少时间 |
30 |
20 |
Development |
开发 |
440 |
370 |
· Analysis |
· 需求分析 (包括学习新技术) |
20 |
20 |
· Design Spec |
· 生成设计文档 |
30 |
40 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
60 |
40 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
60 |
40 |
· Design |
· 具体设计 |
30 |
30 |
· Coding |
· 具体编码 |
180 |
150 |
· Code Review |
· 代码复审 |
30 |
30 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
30 |
20 |
Reporting |
报告 |
90 |
80 |
· Test Report |
· 测试报告 |
30 |
30 |
· Size Measurement |
· 计算工作量 |
30 |
20 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
30 |
|
合计 |
560 |
470 |
小结:看到题目之后,仔细审题并看来作业要求,评分指标,明显感觉这次作业难度更大,我们首先两个人商量制定PSP,使得整个
项目过程清晰明了,可以更好的把控项目进度和花费时间,然后重新复习了一遍《面向对象编程C#》这本书,温习了C#,然后阅读了
助教小姐姐的类似博客,就开始设计结构,明确分工,提高了开发效率和软件质量。
2.代码互审
2.1:代码规范
1.程序总体逻辑结构清晰,注释简洁清楚,十分方便别人阅读并理解代码;
2.对C#的一些函数比较熟悉;
3.运用了正则表达式处理单词识别的问题;
4.代码整体布局风格统一,比较规范;
5.主函数不宜写太长
6.可以把实现不同功能的部分代码抽取出来用函数实现。
2.2:互审过程及问题
提前制定了代码规范,并且设计了程序运行的结构,使得写出来的代码格式清晰,各部分函数分工明确,
让人很容易读懂代码的内容,了解程序的运行过程。余希伦是领航员,我是驾驶员,参照《软件工程原理》
中结对编程模式,共同开发。
3.设计
程序结构设计
输入类设计
难点:单词计数类设计
输出类:
4.代码说明
Main()方法
Main()方法中调用TestMethod()方法,接着由TestMethod()依次调用program.DataInput();//输入program.FileRead(path);//文件读取
program.MainCount();//计数program.Output();//输出program.FileSave();
public void TestMethod() { program.DataInput();//输入 program.FileRead(path);//文件读取 program.MainCount();//计数 program.Output();//输出 program.FileSave();//生成文本文件 } public void TestMethod(string l_path, string S_path, int num, int outNum) { path = l_path; number = num; outPutNum = outNum; s_path = S_path; program.FileRead(path); program.MainCount(); program.Output(); program.FileSave(); }
DataInput()
DataInput()方法写的方法和代码执行过程相对应,同时易于理解输入
void DataInput() { Console.WriteLine("输入读取文档路径:"); path = Console.ReadLine(); Console.WriteLine("输入想要输出的词组长度:"); number = int.Parse(Console.ReadLine()); Console.WriteLine("输出单词数量:"); outPutNum = int.Parse(Console.ReadLine()); Console.WriteLine("输出存储路径:"); s_path = Console.ReadLine();
文件读写代码
void FileRead(string path) { StreamReader sr = new StreamReader(path, Encoding.Default); string line; while ((line = sr.ReadLine()) != null) { Lines.Add(line); } }
核心代码:MainCount()
这个方法用于判断单词字符,应该是最难的部分,为了方便理解,代码中有详细注释。
void MainCount() { int wordJudge = 0;//单词长度标记 int MutiWords = 0;//判断目前是否为词组记录状态的标志变量 int MutiWordsJudge = 0;//词组长度标记 bool isWord = true; string _word = ""; foreach (var str in Lines) { int lineJudge = 0; foreach (var word in str) { //判断当前检测字符是否为空 if (word != ' ') { lineJudge++; characters++; //判断当前是否为单词检测状态,判断当前检测字符是否为字母 if ((isWord == true) && (((word >= 65) && (word <= 90)) || ((word >= 97) && (word <= 122))))//判断是否为字母内容 { wordJudge++; _word = _word + word; } else { //切换至非单词状态 if (wordJudge == 0) { isWord = false; MutiWords++; } else { //判断当前是否为单词数字后缀 if ((wordJudge >= 4) && ((word >= 48) && (word <= 57))) { _word = _word + word; } else { //判断是否已经构成单词 if (wordJudge >= 4) { WordAdd(_word); wordJudge = 0; _word = ""; } //结束当前判断周期,重新切换至单词检测状态 else { wordJudge = 0; _word = ""; isWord = true; MutiWords = 0; } } } } } else { MutiWordsJudge++; //检测到空字符时结束当前判断周期,开启新周期 isWord = true; MutiWords = 0; //判断当前检测结果是否构成单词 if (wordJudge >= 4) { WordAdd(_word); wordJudge = 0; _word = ""; } else { MutiWords++; wordJudge = 0; _word = ""; MutiWordsJudge = 0; } if ((MutiWords == 0) && (MutiWordsJudge == number)) { MutiWordsAdd(); MutiWordsJudge = 0; } } } //在行末判断是否已构成单词 if (wordJudge >= 4) { WordAdd(_word); wordJudge = 0; _word = ""; if ((MutiWords == 0) && (MutiWordsJudge == number - 1)) { MutiWordsAdd(); MutiWordsJudge = 0; } } //判断当前行是否为有效行 if (lineJudge != 0) { lines++; } } }
Output()
void Output() { List<string> words = program.WordSort(); Console.WriteLine("字符:" + program.characters); SaveStrs.Add("字符:" + program.characters); Console.WriteLine("单词:" + program.Words.Count); SaveStrs.Add("单词: " + program.Words.Count); Console.WriteLine("行:" + program.lines); SaveStrs.Add("行:" + program.lines); int i = 0; //输出高频单词 if (Words.Count < outPutNum) { for (; i < Words.Count; i++) { foreach (var iword in Words) { if (words[i] == iword.text) { Console.WriteLine(iword.text + " " + iword.num); SaveStrs.Add(iword.text + " " + iword.num); break; } } } } else { for (; i < outPutNum; i++) { foreach (var iword in program.Words) { if (words[i] == iword.text) { Console.WriteLine(iword.text + " " + iword.num); SaveStrs.Add(iword.text + " " + iword.num); break; } } } } //输出词组 foreach (var word in MutipleWords) { Console.WriteLine(word.text + " " + word.num); SaveStrs.Add(word.text + " " + word.num); } }
运行效果:
5.测试过程
单元测试:
断点测试
性能分析图
分析发现,Output()方法消耗最大,主要原因是在输出的时候运用了嵌套for循环。
异常及处理:
针对于文件输入时发生的错误。
6.上传代码
7.总结
在这次结对编程项目中,最大的感受就是1+1>2,如果一个人做,难度比较大。正所谓:兄弟齐心,其利断金;尤其是在找bug
方面。而且制定了代码规范,两个人的代码都相互易读。包括在最初的结构设计上,刚开始两人各抒己见,经过一番商讨之后,
设计出了双方都满意且最优的结构,在这里结对编程的优势更为明显。