WordCount优化

WordCount优化



基本任务


项目地址:https://github.com/ReWr1te/WcProjava

PSP表格

PSP2.1 PSP阶段 预估耗时 实际耗时
(分钟) (分钟)
Planning 计划 20 20
· Estimate · 估计这个任务须要多少时间 60 65
Development 开发 90 102
· Analysis · 需求分析 (包括学习新技术) 10 5
· Design Spec · 生成设计文档 10 12
· Design Review · 设计复审 (和同事审核设计文档) 30 35
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 20 25
· Design · 具体设计 10 5
· Coding · 具体编码 80 90
· Code Review · 代码复审 20 25
· Test · 测试(自我测试,修改代码,提交修改) 30 25
Reporting 报告 120 120
· Test Report · 测试报告 60 35
· Size Measurement · 计算工做量 20 25
· Postmortem & Process Improvement Plan · 过后总结, 并提出过程改进计划 20 20
合计 600 609

接口实现思路

按照小组讨论的分工,我负责的是从字符串中提取而且统计词频,接口为:git

HashMap<String, Integer> parseContent(String str)

这个接口接受一个String参数,表示要分析的字符串内容,返回HashMap 泛型部分表示单词以及对应的词频。 github

下面来看一下对于单词的定义,单词规定以下:正则表达式

知足以下两个条件中的任意一个条件,则视为单词,框架

第一,由连续的若干个英文字母组成的字符串,例如,software,ide

第二,用连字符(即短横线)所链接的若干个英文单词也视为1个单词,例如,content-based,视为1个单词。函数

注意,单词不区分大小写,不考虑英文之外的其余语言,且仅考虑半角。工具

有关单词识别的部分典型状况的说明:性能

第一,Let’s,这种包含单引号的状况,视为2个单词,即let和s。单元测试

第二,night-,带短横线的单词,视为1个单词,即night。

第三,“I,带双引号的单词,视为1个单词,即i。

第四,TABLE1-2,带数字的单词,视为1个单词,即table。

第五,(see Box 3–2).8885d_c01_016,带数字、经常使用字符和单词的状况,视为4个单词,即see, box, d, c。

其实这么长一串总结起来就两句话:

  • 单词是相似于 a、a-a、a-a-a 这种。
  • 单词字母要转换成小写。

所以可使用正则表达式来实现,代码以下(相关注释在代码中给出):

public class ContentParser {
    private String regEx = "[a-zA-Z]+(-[a-zA-Z]+)*";
    private Pattern pattern = Pattern.compile(regEx);
    //输入文件内容,返回单词统计信息
    @Test
    public HashMap<String, Integer> parseContent(String content) {
        HashMap<String, Integer> wordMap = new HashMap<>();
        if (content == null || "".equals(content)) {
            return wordMap;
        }
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            String word = matcher.group().toLowerCase();
            if (wordMap.containsKey(word)) {
                wordMap.replace(word, wordMap.get(word) + 1);
            } else {
                wordMap.put(word, 1);
            }
        }

        return wordMap;
    }
}

用例设计

这里采用白盒测试黑盒测试的思路来进行用例设计(因为用例数量较多,这里仅给出 连接),下面分别进行说明:

黑盒测试采起等价类划分的方法,经过对上面单词的定义进行分析,对输入有以下四条划分规则:

  • 是否含有字母
  • 是否含有数字
  • 是否含有特殊字符(除-,由于-能够被包含在单词内)
  • 是否含有-

据此能够产生16个测试用例。

白盒测试对函数的路径和断定进行分析,可获得以下程序图:

经过对代码循环部分分析能够合并两个测试用例,获得五个测试用例。

测试用例文档以下:

经过上面的分析能够得出结论,黑盒测试可以包含全部输入的等价类,白盒测试路径覆盖率为100%,测试用例足够少,测试足够完善,所以可以知足测试效率要求

测试结果

在代码实现时,将测试用例按照必定格式提早写入txt文件,测试时动态读取,方便了测试用例的动态管理,测试结果以下:

测试用例采用黑盒测试和白盒测试两种方式进行设计,黑盒测试可以包含全部输入的等价类,白盒测试路径覆盖率为100%。可是二者中出现了一部分重复的测试用例,说明黑盒测试和白盒测试具备必定的共同点。

被测试的程序经过了全部的测试用例,说明被测程序可以很好的完成程序功能,正确应对各类合理输入数据,而且可以正确处理异常输入数据,健壮性较好。


静态测试


这里根据《阿里巴巴Java开发手册》进行代码规范分析。《阿里巴巴Java开发手册》中指出,

【强制】在使用正则表达式时,利用好其预编译功能,能够有效加快正则匹配速度。

据此我将正则表达式的预编译放在了对象初始化的过程当中,这样方法不论被调用多少次,预编译只会执行一次,提升了正则匹配速度和方法执行速度:

public class ContentParser {
    private String regEx = "[a-zA-Z]+(-[a-zA-Z]+)*";
    private Pattern pattern = Pattern.compile(regEx);
    //输入文件内容,返回单词统计信息
    @Test
    public HashMap<String, Integer> parseContent(String content) {
        ······
        return wordMap;
    }
}

另外,《阿里巴巴Java开发手册》中指出:

【强制】类名使用UpperCamelCase风格,但如下情形例外:DO/ BO / DTO/ VO/ AO/ PO等。

【强制】方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须听从驼峰形式

这两点对类和方法、参数等的命名作出了规范,类统一使用大驼峰命名法,方法、变量、参数等统一使用小驼峰命名法。这样可使得代码阅读更加方便。所以在程序中类命名为ContentParser 变量方法命名相似于wordMapparseContent

代码规范分析

这里分析了学号为17121的同窗的代码。

从变量和方法等的命名来看 ,变量和方法的命名采用了小驼峰命名法,类的命名采用了大驼峰命名法,如sortwriteFile() 等,符合《阿里巴巴Java开发手册》中对命名规范的规定。

从工程目录规范的角度来看 ,《阿里巴巴Java开发手册》中指出:

【强制】单元测试代码必须写在以下工程目录:src/test/java,不容许写在业务代码目录下。

说明:源码构建时会跳过此目录,而单元测试框架默认是扫描此目录。

该同窗的Test文件所有放在了src/test/目录下,符合开发手册的规定,方便了测试用例的管理,提升了源码构建的效率。

静态检查工具

我采用的静态检查工具是Alibaba Java Coding Guidelines,下载地址

检查结果

采用Alibaba Java Coding Guidelines对ContentParser进行检查,结果以下:

对ContentParserTest进行检查,结果以下:

下面对检查中出现的问题逐条进行分析:

  • 对应第一条,在ContentParser中添加了author信息
  • 对应第二条,由于ContentParser不是Test类,不须要以Test结尾所以属于误判。
  • 对应第三条,注释内容是对方法功能的说明,所以改成使用/**内容*/形式的注释。
  • 对应第四条,因为最多分析100个单词,所以将hashmap的初值定位130。

比较好的地方是,在ContentParserTest的finally语句块中,会检查文件输出流的状态,确保不管是发生异常仍是正常退出都能及时关闭。

小组代码存在的问题

  • 没有及时关闭文件流
  • 代码中多处出现魔法值
  • 注释不规范,包括不能有尾行注释,添加author信息,使用javadoc规范注释等等

改正方法:

  • finally中判断文件流是否关闭不然关闭文件流

  • 使用final定义常量

  • 按照规范改写注释


高级任务


测试用例设计

咱们选取了一本O'Reilly的JQury教程构造咱们的测试用例,将其复制屡次,获得了24.03M的txt文件,并进行测试。初步估计运行时间在1000ms以上。

优化前性能指标

测试结果以下:

次数 时间(毫秒)
1 1777
2 1994
3 1978
4 2023
平均 1943

同行评审及结论

  1. 角色分工:
    • 主持人&记录员:田诗园
    • 讲解员:邱利光 沃锦文 王启萌 田诗园
    • 评审员:邱利光 沃锦文 王启萌 田诗园
    • 做者:邱利光 沃锦文 王启萌 田诗园
  2. 评审结果及结论
    • 正则表达式效率较慢。
    • 考虑到程序对查找的性能要求比较高,应当选取合适的容器类。
    • 提升IO速度。

优化设计思路

  • 能够用状态机来提取单词,提升效率。
  • 单词统计咱们采用HashMap来存储。当数据容量较少时其内部实现为一个链表,当数据量较大时,自动改用二叉树进行存储,有效提升了查询效率。
  • 输出单词时,改变原来的每一个单词打开一次文件的作法,只打开一次文件,所有输出后关闭文件流,提升了IO速度。

做业感想

想想此次做业,编码的时间大概只占到了三分之一左右,剩下的时间大约三分之一用在了设计用例,编写测试框架,剩下的三分之一时间用在了写博客上。

这门课叫软件质量测试,从此次做业也能够感觉到,软件测试的过程是贯穿整个开发过程当中的,不论是基本功能,仍是扩展任务,再到高级任务,测试的思想一直贯穿其中,基本任务要根据本身负责的模块设计二十个测试用例,扩展任务则是对本身的代码进行静态检查,也是一种软件质量测试,高级任务则是进行压力测试,检查程序的健壮性。

经过一系列测试过程,一方面让我从另外一个角度了解了本身写的程序,另外一方面让我对程序的健壮性有了信心,毕竟一个简单的模块写了二十个测试用例Orz

个人理解就是软件测试 贯穿了软件开发 的整个过程,保证了所开发软件的质量

相关文章
相关标签/搜索