Github project address | WordCount |
---|---|
Cooperation classmates job link | 201731091317 |
Operational requirements Links | Pair programming requirements |
Part 1. PSP form
PSP2. | Personal Software Process Stages | Estimated time consuming (minutes) | The actual time-consuming (minutes) |
---|---|---|---|
Planning | plan | 60 | 80 |
· Estimate | • Estimate how much time this task requires | 60 | 80 |
Development | Develop | 700 | 785 |
· Analysis | · Needs analysis (including learning new technologies) | 60 | 45 |
· Design Spec | Generate design documents | 30 | 45 |
· Design Review | · Design Review (and his colleagues reviewed the design documents) | 30 | 30 |
· Coding Standard | · Code specifications (development of appropriate norms for the current development) | 30 | 25 |
· Design | · Specific design | 40 | 40 |
· Coding | · Specific coding | 300 | 400 |
· Code Review | · Code Review | 90 | 80 |
· Test | · Test (self-test, modify the code, submit modifications) | 90 | 120 |
Reporting | report | 90 | 120 |
· Test Report | · testing report | 30 | 60 |
· Size Measurement | · Computing workload | 30 | 40 |
· Postmortem & Process Improvement Plan | · Hindsight, and propose process improvement plan | 30 | 20 |
total | 850 | 985 |
Part 2. calculation module interface design and implementation
First, the problem-solving ideas
- Character Statistics: traversing determine whether the character is empty, do not empty character accumulates statistics of the total number of characters
- Word counts: first unified case-word, for example: Word, WORD, Word is the same word, we will convert uppercase letters to lowercase letters. And then the number of words in the word statistics, the characters in the document into a string array, the array of strings to determine the comparative figure out a different number plus one.
- The number of rows Statistics: traversal to determine whether the blank lines, not the number of rows of empty lines accumulates statistics of non-empty rows.
- Word frequency statistics: the number of words and the frequency of words into a set of <string, int>, respectively words and word frequency. Lexicographical sort carried out on the frequency of all the words. The number of words a certain number of final output frequency and the number.
- Statistical phrase length: The method in accordance with the length of words and word frequency statistics are stored in a set <string, int>, respectively words and word length. To get the word when a length in which to find, print out all the words of this length.
Therefore, in the design process we put this program functions are divided into two categories:
1. basic functions. , By:
- Character counts files;
- Total word count of the document;
- The effective number of lines statistical document;
- Statistics document the frequency of use of each word;
- Output to a txt file in lexicographic order.
2. new features. , By:
- Word frequency statistics in the specified folder phrase length;
- User-specified output frequency of the first n words and their frequencies of:
- -L parameter setting file read path;
- -M parameter set phrase length statistics;
- Parameter set number of words -n output;
- -O path generating parameter setting storage file.
Second, the code organization
During implementation of the present program includes 10 class functions 16, as shown in the following table:
The class name | function | Features |
---|---|---|
Program | Main | Main: For the user to select whether to process the command parameter |
select_way | instruction nointrction the_error | instruction: if necessary instructions for processing parameters. nointrction: if necessary instructions for the processing parameters. the_error: processing for abnormality |
file_path | no | Statement input and output file path variables |
result | print_char print_word print_lines print_wordsort print_selectedlong | print_char: the number of characters output. print_word: Output total number of words. print_lines: output number of effective lines. print_wordsort: Output word sorting. print_selectedlong: Find the word of a predetermined length. |
asccII_count | ascciicount | Count the number of characters: ascciicount |
word_count | word_sum word_frequency | word_sum: Print high-frequency words. word_frequency: Print the frequency of the word |
line_count | lines | The number of rows statistical files: lines |
ins_process | ins_select ins_right | ins_select:对于用户选择的指令参数进行处理。ins_right:对已选择的指令进行相应的赋值 |
uniform_character | uncharater | uncharater:统一字符大小写 |
函数之间的关系可用下图表示:
Part 3.代码复审
一、代码规范
1.命名约定
- 对于类名和变量名,我们都采用“aa_bb”的命名方式,其中aa表示变量名,bb表示操作名。
2.注释约定
- 将注释放在单独的行上,而不是放在代码行的末尾;
3.布局约定
- 使用默认的代码编辑器设置(智能缩进,四字符缩进,制表符另存为空格)。
- 每行只写一条语句;
- 每行只写一条声明;
- 如果连续行没有自动缩进,请缩进一个指标位(四个空格)。
二、代码互审
在代码互审过程中,我主要关注的是具体功能是否能够实现、代码是否符合规范、异常处理以及代码的结构。在代码互审的过程中我们遇到的问题以及改进方法如下:
- 原来版本打开exe文件只能进行无指令操作,经过改进,我们可以进行选择,既能无指令操作又能有指令操作。
- 原来版本的代码结构的方法比较简单,即就几个大的功能的类,没有细分功能的实现,改进后,我们的代码结构更有逻辑性,能容易理解,方便团队协作。
- 原来版本的对异常的处理比较少,对于许多错误指令没有考虑,没有提示,改进后,我们会加入错误指令的提示。
Part 4.计算模块接口部分的性能改进
在改进计算模块性能的过程中,我们发现的问题以及改进思路如下:
1.对统一字符的处理,原来需要对一个单词的每一个字符用for循环来依次判断,再对产生的flag进行判断,而这样的对时间和空间的占用率较高,我们将去到for循环,对一个单词统一判断,减少判断次数和循环次数。提高代码的运行速度。
2.对于使用率较高的word_wore和word_len两个参数,原来是放在一个类里面,导致其他地方调用十分复杂,所以我们对两个参数进行封装重构,减少了代码的臃肿。
使用VS的性能探查器得到的效能分析报告如下图:
从上图中我们可以看到,result类中的print_char函数在总CPU耗时中占用了56%左右,由于print_char函数只是由打印语句和调用line_count中的lines函数构成,所以在总CPU耗时最多的函数等价为lines函数。
Part 5.计算模块部分单元测试展示
- 对word_count类中的word_sum方法进行测试:新建一个字典集合,向集合中添加一个单词,比较添加后的情况。
public void Test_word_sum()
{
//
// TODO: 在此处添加测试逻辑
//
Dictionary<string, int> frequen = new Dictionary<string, int>();
file_path.output_path=@"E:\GITwrod\WordCount\201731062322\WordCount\UnitTest_WordCount\testoutfile.txt";
string a = "word";
frequen.Add(a, 1);
//frequen.Add("word",1);
Assert.AreEqual(1, word_count.word_sum(frequen));
// Assert.Fail();
}
- 对字符统计的测试:读取文件内容(该文件为空文件),比较文件中的字符数与人工算出的字符数是否相等,相等则测试成功,否则失败。
public void TestMethod1()
{
//
// TODO: 在此处添加测试逻辑
//
file_path.input_path = @"E:\GITwrod\WordCount\201731062322\WordCount\UnitTest_WordCount\testfile.txt";
int num = 0;
Assert.AreEqual(num, asccII_count.ascciicount());
//Assert.Fail();
}
测试结果为:
3.对行数统计的测试:与测试字符数的方法类似,读取文件内容(该文件为空文件),比较文件中的行数与人工算出的字符数是否相等,相等则测试成功,否则失败。因为本程序是除去了空行的,所以当没有显示的字符(空格不显示)的时候为零行。
public void TestMethod1()
{
file_path.input_path = @"E:\GITwrod\WordCount\201731062322\WordCount\UnitTest_WordCount\testfile.txt";
int x = 0;
Assert.AreEqual(x, line_count.lines());
// Assert.Fail();
}
测试结果为:
Part 6.计算模块部分异常处理说明
在本程序中,异常处理主要是针对用户输入的异常处理:
1.在选择是否使用指令参数时的异常处理。如果用户输入了不存在或者错误的选项,则报错:
switch(cmd_num)
{
case 1: select_way.instruction();
break;
case 2: select_way.nointrction();
break;
default: select_way.the_error();
break;
}
public static void the_error()
{
Console.WriteLine("the error instruction");
Console.ReadKey();
}
2.在输入指令参数是的异常处理。如果用户输入了不存在或者错误的参数,则报错:
else
{
Console.WriteLine("the wrong instruction");
Console.ReadKey();
}
3.在没有输入输入文件路径时的异常处理。如果用户没有输入输入文件路径就要进行下一步,则报错:
if(x%2==0)
{
Console.WriteLine("need a input file");
Console.ReadKey();
}
Part 7.部分代码展示
1.对选择方式的实现,主要是对有指令和无指令的命令行操作进行判断,可以选择两种方式中的任意一种方式进行操作。有指令操作的话,会输出想显示的内容,但是必须输入读取的文件路径;无指令操作,会输出固定的内容(字符数,单词数,行数和10个高频单词),需要输入读取文件路径和输出文件路径。
public class select_way
{
illustration ill2 = new illustration();
result re1 = new result();
ins_process inp1 = new ins_process();
public void instruction(word_len len,word_more more)
{
ill2.illu_function();
Console.WriteLine("input your instructions");
string all_char = Console.ReadLine();
string[] ins_arr = all_char.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
int ind_sum = 0;
for (int i = 0; i < ins_arr.Length; i = i + 2)
{
ind_sum = ind_sum + inp1.ins_select(ins_arr, i,len,more);
}
inp1.ins_right(ind_sum,len,more);
}
public void nointrction(word_len len,word_more more)
{
Console.WriteLine("the input path:");
string inputpath = Console.ReadLine();
file_path.input_path = inputpath;
//result.Word_more = 10;
//result.Word_len = 0;
Console.WriteLine("the output path:");
string outputpath = Console.ReadLine();
file_path.output_path = outputpath;
//re1.WM.Wordmore = 10;
re1.print_char();
re1.print_word(len);
re1.print_lines();
re1.print_wordsort(more.Wordmore,len);
}
public void the_error()
{
Console.WriteLine("the error instruction");
Console.ReadKey();
}
2.对有指令时进行了哪些操作(即需要展示哪些内容和未设置的内容进行默认设置的操作)。我们先通过循环对每一组指令进行判断,实现对应的操作,通过16进制数对不同的操作返回不同的值来区分这些操作。最后将这些值加起来判断输入了哪些操作,需要对哪些参数进行更改、哪些参数进行默认设置。
public class ins_process
{
static string str1 = "-l";
static string str2 = "-m";
static string str3 = "-n";
static string str4 = "-o";
result re2 = new result();
public int ins_select(string[] array, int i,word_len len,word_more more)
{
int flag = 0;
if (array[i].Equals(str1, StringComparison.OrdinalIgnoreCase) == true)
{
file_path.input_path = array[i + 1];
flag = 1;
}
else if (array[i].Equals(str2, StringComparison.OrdinalIgnoreCase) == true)
{
len.Wordlen = Convert.ToInt32(array[i + 1]);
//result.WL.Wordlen = Convert.ToInt32(array[i+1]);
flag = 2;
}
else if (array[i].Equals(str3, StringComparison.OrdinalIgnoreCase) == true)
{
//result.WM.Wordmore = Convert.ToInt32(array[i + 1]);
more.Wordmore = Convert.ToInt32(array[i + 1]);
flag = 4;
}
else if (array[i].Equals(str4, StringComparison.OrdinalIgnoreCase) == true)
{
file_path.output_path = array[i + 1];
flag = 8;
}
else
{
flag = -16;
}
return flag;
}
public void ins_right(int x,word_len len,word_more more)
{
if (x > 0)
{
if (x % 2 == 0)
{
Console.WriteLine("need a input file");
Console.ReadKey();
}
else
{
if (x == 1)
{
//result.Word_more = 10;
file_path.output_path = "output.txt";
//result.Word_len = 0;
re2.print_char();
re2.print_word(len);
re2.print_lines();
re2.print_wordsort(more.Wordmore,len);
}
else if (x == 3)
{
//result.Word_more = 10;
file_path.output_path = "output.txt";
re2.print_char();
re2.print_word(len);
re2.print_lines();
re2.print_wordsort(more.Wordmore, len);
re2.print_selectedlong(len.Wordlen );
}
else if (x == 5)
{
file_path.output_path = "output.txt";
//result.Word_len = 0;
re2.print_char();
re2.print_word(len);
re2.print_lines();
re2.print_wordsort(more.Wordmore, len);
}
else if (x == 7)
{
file_path.output_path = "output.txt";
re2.print_char();
re2.print_word(len);
re2.print_lines();
re2.print_wordsort(more.Wordmore, len);
re2.print_selectedlong(len.Wordlen);
}
else if (x == 9)
{
//result.Word_more = 10;
//result.Word_len = 0;
re2.print_char();
re2.print_word(len);
re2.print_lines();
re2.print_wordsort(more.Wordmore, len);
}
else if (x == 11)
{
//result.Word_more = 10;
re2.print_char();
re2.print_word(len);
re2.print_lines();
re2.print_wordsort(more.Wordmore, len);
re2.print_selectedlong(len.Wordlen);
}
else if (x == 13)
{
//result.Word_len = 0;
re2.print_char();
re2.print_word(len);
re2.print_lines();
re2.print_wordsort(more.Wordmore, len);
}
else
{
re2.print_char();
re2.print_word(len);
re2.print_lines();
re2.print_wordsort(more.Wordmore, len);
re2.print_selectedlong(len.Wordlen );
}
}
}
else
{
Console.WriteLine("the wrong instruction");
Console.ReadKey();
}
}
}
Part 8.结果展示
1.对GUI界面的设计实现:
2.有指令和无指令时的黑白板输出:
测试的内容:
有指令的黑板运行结果:
有指令的白板运行结果:
无指令的黑板运行结果:
无指令的白板运行结果:
Part 9.描述结对的过程
结对编程(非摆拍)图片
Part 10.心得体会
1.分工:在本次项目中,我主要负责单词数的统计和主函数的编写;单数数的统计代码难度不是很大,用了集合之后还更加方便了,使得整体的编写速度大大提高。
2.结对的优点:在写代码的过程中有卡壳的时候,但是我的队友能及时的点醒我,同时这个时候我也意识到自己的注意力开始下降了,如果是我一个人做的话,可能会继续下降,但是有了队友,他的提醒使我又重新专注起来。自己代码写错了被发现还是一件挺尴尬的事情,所以户使得我们更加专注、高效的编写代码。当然在队友编程的时候可以稍微休息一下眼睛,但是可以从队友代码的书写中可以学到许多东西,还是要保持一定的注意力。
3.在代码中学习:本次项目中,更加熟练的应用集合和封装的知识。以前在写代码的过程中不怎么用集合的,封装也很少用,这一次有两个参数很重要,不重构的话,逻辑会很混乱。于是我们就用了重构,但是很久不写C#的代码,有些知识忘记了,封装的地方总是出错,但是通过我们的不懈努力,最终还是解决了。也学到不少知识。