个人项目WC(java)
WC个人项目(JAVA实现)
一、Github地址:https://github.com/qq544279946/repository
二、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 35 | 28 |
· Estimate | · 估计这个任务需要多少时间 | 35 | 28 |
Development | 开发 | 1135 | 1021 |
· Analysis | · 需求分析 | 60 | 55 |
· Design Spec | · 生成设计文档 | 40 | 43 |
· Design Review | · 设计复审 | 25 | 23 |
· Coding Standard | · 代码规范 | 20 | 20 |
· Design | · 具体设计 | 85 | 70 |
· Coding | · 具体编码 | 750 | 660 |
· Code Review | · 代码复审 | 35 | 30 |
· Test | · 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 145 | 120 |
· Test Report | · 测试报告 | 75 | 60 |
· Size Measurement | · 计算工作量 | 25 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 45 | 40 |
合计 | 1315 | 1169 |
三、解题思路
①命令行参数处理
在看到项目和对应的需求分析后,我想到这是一个命令行程序,我需要在命令行中输入需求需要设计的参数 -w -c -l -a -s -x等,然后得到正确的返回结果。所以我想到了调用org.apache.commons.cli包中的CommandLine类中的hasOption()方法来判断输入的命令参数,然后调用参数对应的方法。
②文件统计的处理
a.静态类:这些处理文件的方法我想到是全都放在了一个类中来集中处理,将这些方法都设置成静态方法,好通过类名直接调用,而不用多次创建实例对象。而这些方法返回的结果可能含有多条信息,
b.输出结果类的创建: 我创建了一个抽象基类,其中定义了一个抽象方法。然后通过继承这个父类来实现多个输出结果对应的类,同时实现这个父类的抽象方法来输出<结果类>的属性。
c.关于通配符的处理:我想到是直接根据输入的字符串,调用它的matc方法来匹配有没有?和 *这样的字符出现,返回返回对应的true和false,而转换,我是直接用字符串的replaceAll方法来替换掉?--->. 和 *-----> .+ 转成正则表达式 。
d.关于递归方法的处理:我是根据输入的字符串,先调用方法判断有没有通配符,然后转换成正则表达式,然后先判断是否是目录,是就直接调用 内部递归方法(e.提到),如果不是就分开文件名和父路径。
e.内部递归方法的考虑:我是想传入目录路径,和将带通配符的文件名转换成的正则表达式这两个形参,然后通过路径来创建File类并调用listFiles方法,传入一个过滤器来过筛选出“符合正则表达式的文件” 和 传入另一个过滤器来筛选出子目录。
f.关于listFiles方法传入的过滤器说明:关于文件筛选,我是直接用file类的isFile方法 和 String类的match方法来筛选。目录筛选,我直接用File类的isDirection方法而已。
③GUI的设计
关于这方面,我就直接WindowBuilder插件来实现可视化,通过直接拉组件修改其中部分代码就实现了,主要是一个JFrame 和 一个 JTextArea 类 和一个按钮。
四、设计实现过程
我主要设计了Main类处理命令,GUI窗体类,一个处理流的类,和一个处理文件的类
主要调用流程:
五、测试运行
用于测试文件包括:一个空文件、一个只有一个字符的文件、一个只有一个单词的文件、一个标准的java源文件、一个多目录嵌套的文件。
测试代码:
//基本功能的测试
@Test
public void testBaseFunction() {
String filename = "D:\\qweqe.c";
testBase(filename);
String filename1 = "D:\\text.c";
testBase(filename1);
}
private void testBase(String filename) {
Result r ;
System.out.println(filename);
r = FileHandle.numberOfChar(filename);
if(r != null)
System.out.println(r.information());
else
System.out.println("文件不存在");
r = FileHandle.numberOfLines(filename);
if(r != null)
System.out.println( r.information());
else
System.out.println("文件不存在");
r = FileHandle.numberOfWords(filename);
if(r != null)
System.out.println(r.information());
else
System.out.println("文件不存在");
r = FileHandle.numberOfComplexity(filename);
if(r != null)
System.out.println(r.information());
else
System.out.println("文件不存在");
}
//通配符,递归的测试
@Test
public void testRecursive() {
String filename = "D://123//t*.txt";
testRecursiveInner(filename);
filename = "D://123//text.txt";
testRecursiveInner(filename);
}
private void testRecursiveInner(String filename) {
boolean[] c = new boolean[] {true,true,true,true};
List<Result> rs = FileHandle.recursion(filename, c);
for (Result r : rs) {
if(r == null)
System.out.println("文件不存在");
System.out.println(r.getFilename());
System.out.println(r.information());
}
}
测试截图:
//文件不存在
//空文件
//一个字符的文件
//一个单词的文件
//一个java代码的文件
//递归调用
//通配符+递归测试
窗体测试:
代码覆盖率:
六、项目总结:
在这次的项目中,我深有感触,与之前写的那些小玩具有点不一样了,才知道代码写完后还有进行多方面的测试和调试,检测代码覆盖率等工作,真正经历了一遍个人软件开发的过程。在设计实现前,需要项目分析,框架的设计,用时的估计等任务,写完实现后还要定期进行维护。虽然,我整个过程用时有点长,各种软件的操作还不算太熟练,代码还会存在不足,但我还是学到了许多工程方面的知识。