wordCountPro
Github地址
https://github.com/skz12345/wcPro
PSP表格
PSP2.1 | PSP****阶段 | 预估耗时****(分钟) | 实际耗时****(分钟) |
---|---|---|---|
Planning | 计划 | 15 | 12 |
· Estimate | · 估计这个任务需要多少时间 | 15 | 12 |
Development | 开发 | 410 | 430 |
· Analysis | · 需求分析 (包括学习新技术) | 75 | 80 |
· Design Spec | · 生成设计文档 | 50 | 45 |
· Design Review | · 设计复审 (和同事审核设计文档) | 30 | 25 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 45 | 40 |
· Design | · 具体设计 | 40 | 30 |
· Coding | · 具体编码 | 80 | 95 |
· Code Review | · 代码复审 | 30 | 40 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 75 |
Reporting | 报告 | 45 | 70 |
· Test Report | · 测试报告 | 20 | 30 |
· Size Measurement | · 计算工作量 | 15 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 10 | 20 |
合计 | 470 | 512 |
基本任务:代码编写+单元测试
接口实现
此次作业中我负责输入控制模块,即对输入进行有效性校验,识别和处理无效输入,并针对有效输入,从中提取所需数据。
因此,我所要做的工作无非是从参数中获取文件路径然后读取文件内容。在处理的过程中还要考虑到输入的文件是否是符合要求的(是否是没有文件名或者不是txt后缀的文件),关于不能同时处理多个文件的要求在主函数里面进行控制。在读入文本的同时,通过一个函数判断读入的文本里面是否有中文字符[1],为后面的性能提升做准备。
具体而言,因为是模块化设计,所以我将输入这个功能写成了一个类,将文件路径(filepath)和读取到的字符串(result)分别定义为类里面的变量。编写一个带参的构造函数,当外界创建一个该类的对象的时候就将文件路径传参进来进行filepath的初始化。在openFileAndPull()方法里面按行将文件的内容读取出来,并加上一个换行符,最后将整个读取到的文件的字符串值赋值给result,result作为函数返回值返回。在openFileAndPull()完成上述功能之前,通过文件路径长度判断和文件名后缀的比较来抛出参数异常,完成输入有效性检测。外界创建本类的对象后调用openFileAndPull()功能即可以得到读取得的文件内容,并且此时大部分的输入有效性检测已经完成。
输入类较为简单,在此仅贴出openFileAndPull()的代码:
public String openFileAndPull ()//处理输入的核心
{
if((this.filepath).length()==0)//判断输入是否为空,是则抛出异常
throw new IllegalArgumentException("Please input the filename!");
File file = new File(filepath);
if(!file.getName().endsWith(".txt"))//判断是否文件后缀为.txt,否则抛出异常
throw new IllegalArgumentException("Error file format!");
try{
BufferedReader reader=null;
StringBuilder strings=new StringBuilder();
reader=new BufferedReader(new FileReader(file));
String readline="";
while((readline=reader.readLine())!=null)//按行读取文件内容
{
strings.append(readline+"\n");//每行末尾添加一个换行符
readline=null;
}
this.result=strings.toString();//将结果存入result
if(isContainChinese(result))//调用方法判断result中是否有中文字符
{
System.out.println("(文本中有中文字符)");
}
reader.close();
}
catch (Exception e) {
System.out.println("Error path name!");
}
return result;
}
测试用例设计
本次一共设计了20个测试用例,采用了黑盒测试和白盒测试的方法。
在白盒测试中,我了解到在线学习2.3节对判定的测试中指出“语句覆盖就是要保证设计的测试用例应至少覆盖函数中所有的可执行语句”,为此,我针对程序,使用语句覆盖指标设计测试用例,对于getFilepath()方法、getResult()方法以及isContainChinese()方法进行了测试。同时为了覆盖if分支,对于openFileAndPull()方法也使用白盒测试的方法进行了少量测试。之后我也从黑盒测试的角度出发,划分了输入可能的情况(空输入、错误后缀、输入中有无中文)后进行了相应的测试。
部分测试用例如下:
@Test(expected = IllegalArgumentException.class)
public void openFileAndPullTest1()throws IllegalArgumentException {
String file="";
input=new input(file);
input.openFileAndPull ();
}//测试文件输入是否为空
@Test(expected = IllegalArgumentException.class)
public void openFileAndPullTest2()throws IllegalArgumentException {
String file="tes";
input=new input(file);
input.openFileAndPull ();
}//测试文件输入是否符合要求
@Test(expected = IllegalArgumentException.class)
public void openFileAndPullTest6()throws IllegalArgumentException {
String file="test2.html";
input=new input(file);
input.openFileAndPull ();
}//测试文件格式是否符合要求
@Test
public void getFilepathTest11() {
String file="test1.bat";
input=new input(file);
assertEquals("getFilepath wrong","test1.bat", input.getFilepath());
}//测试获取文件路径的方法
@Test
public void getResultTest13() {
String file="test7.txt";
input=new input(file);
input.openFileAndPull ();
assertEquals("getResult wrong","hello"+"\n", input.getResult());
}//测试获取结果的方法
@Test
public void isContainChineseTest15() {
String content="hello 你好 ";
assertEquals("chineseJudgement wrong",true, input.isContainChinese(content));
}//测试判断中文字符的方法
@Test
public void openFileAndPullTest17() {
String file="test9.txt";
input=new input(file);
input.openFileAndPull ();
String temp="content-based\ncontent-based\nTABLE1-2\nTABLE1-2";
assertEquals("fileContentGet Wrong",temp+"\n", input.openFileAndPull());
}//测试正常输入返回情况
单元测试
本次采用JUnit4在MyEclipse里面对我所负责的模块进行单元测试。
将测试用例运行后可以看到20个测试用例均正常通过,即看到了"GREEN BAR"
,从测试结果来看,每个测试用例运行的时间均较短,性能较好,能以较为简单的逻辑结构来完成对我所负责的模块进行单元测试。在此次的测试过程中,我对模块长得openFileAndPull()方法、getFilepath()方法、getResult()方法以及isContainChinese()方法采用了白盒测试和黑盒测试的方法进行了测试,结果证明,测试的功能均能正常通过测试,功能中的语句、判断均能正常运作,由此可见被测模块的质量有较为可靠的保证。
扩展任务:静态测试
代码开发规范
规范的理解
基于本次作业的代码复杂程度,我选择了附录4中的第一个,即邹老师所写的关于代码的规范与复审[2]。
我阅读了老师关于代码风格规范部分的讲解。就像老师在一开始就提到的,代码要有简明、易读、无二异性的特点。这很重要,我们可以使用很精巧的算法来大大缩减我们的代码量,可是我们的代码是会被复用的,而且我们的代码也许也要通过他人之手来检查改进。所以,简而言之,代码是我们自己工作的结果,但不能只从自己的角度出发。这次的作业也是这样,小组作业分工合作这就要求我们商量好并且做到自己的代码别人能看得懂,自己的接口别人能方便使用。我就采取了将模块封装的策略,而且方法的返回值直接就是调用模块所需要的,调用模块能很方便地使用。这在我的input类,openFileAndPull()方法中有较好地体现。
具体到规范的细节,我选取命名和注释规范来举例。邹老师在博客中说到:“在变量面前加上有意义的前缀,就可以让程序员一眼看出变量的类型及相应的语义。这就是’匈牙利命名法‘的用处。”也就是说,变量的命名要让阅读者明白这个变量的类型和语义,这样才会避免不必要的错误。虽然我没有那种很容易存在歧义的变量存在,但我依旧遵循简明准确的原则来命名。如我在类中的filepath和result就是为读取文件名和存储读取结果而设计的,简单易懂,比较明确。在input类里面的其他地方,我也较好地践行了这个原则。但在判断中文字符的方法里面,用简单的字母来命名变量就显得比较的不规范了,但基于方法较为简单,命名的变量也很容易看懂,在此变不做修改。再来看注释方面,总体来看我的注释的最大的问题是含有中文字符:
if((this.filepath).length()==0)//判断输入是否为空,是则抛出异常
throw new IllegalArgumentException("Please input the filename!");
File file = new File(filepath);
if(!file.getName().endsWith(".txt"))//判断是否文件后缀为.txt,否则抛出异常
throw new IllegalArgumentException("Error file format!");
就像邹老师在博客里面提到的“另外,注释(包括所有源代码)应只用ASCII字符,不要用中文或其他特殊字符,它们会极大地影响程序的可移植性。”虽然此次作业实现的任务非常简单,也很少或者可能涉及不到移植问题,但是这种思想还是要有的。
代码评价
我分析的是17076同学的代码。他为了能较好的测试和实现自己的代码,先将所有的功能实现了,我们之后选取他的核心功能模块化与我们的模块一起最后完成整个作业。
17076同学的代码很精简,仅仅几十行就实现了作业的要求,但是也存在些问题。首先,缺少注释。写注释是一个较好的代码习惯,对于复杂的函数或者需要注意的变量等,需要通过注释来告知代码阅读者这些代码的意义。所以没有注释的代码一般会比较让人头痛。但在变量命名方面,17076同学做得很好,变量的作用、意义也都通过名称体现了出来,而且在大小写方面也很注意。这是17076同学的有点,而且他做到了不在同一行命名不同变量,这就让代码看起来比较整洁。
静态代码检查
我采用的是阿里巴巴Java开发代码检测IDE插件
工具链接:https://p3c.alibaba.com/plugin/eclipse/update
使用方法参看教程:https://blog.csdn.net/wang_shuyu/article/details/78285074
扫描结果:
存在的问题主要为:1.if没有大括号跟随 2.包的命名方式存在问题 3.没有添加创建者信息。
于是根据扫描结果,我对代码进行了修改。我把即使if语句后只有一行语句的也加上了大括号。之后我又将包的命名中含有的大写字符给换成了小写,最后我加上了自己信息。其余也没有什么大的问题。虽然代码简单,但可以看出我的代码虽然有问题,但还是绝大多数都符合规范的。
小组代码问题
总体来说,小组的代码主要出的问题大都在注释,if花括号,作者信息,命名等方面。虽然都是一些小问题,但也反应出一些问题。首先这是个小组合作的作业,虽然模块化了,但是个人还是过于独立,沟通较少。小方面的代码问题也反应出对于代码不够上心,比较随意,以后需要注意。
小组贡献
此次实验中我负责输入模块,同时也跟进了项目的修改和模块化分工。根据小组讨论的结果,得出了贡献分,贡献分见毕博平台。
参考文献
[1]http://www.jb51.net/article/123117.htm
[2]http://www.cnblogs.com/xinz/archive/2011/11/20/2255971.html