WcPro项目(WordCount优化)
1 基本任务:代码编写+单元测试
1.1 项目GitHub地址
https://github.com/ReWr1te/WcPro
1.2 项目PSP表格
| PSP2.1 | PSP阶段 | 预估耗时(分钟) | 实际耗时(分钟) | 
|---|---|---|---|
| Planning | 计划 | 20 | 20 | 
| · Estimate | · 估计这个任务需要多少时间 | 20 | 20 | 
| Development | 开发 | 870 | 1160 | 
| · Analysis | · 需求分析 (包括学习新技术) | 60 | 80 | 
| · Design Spec | · 生成设计文档 | 30 | 30 | 
| · Design Review | · 设计复审 (和同事审核设计文档) | 30 | 60 | 
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 30 | 
| · Design | · 具体设计 | 180 | 240 | 
| · Coding | · 具体编码 | 180 | 240 | 
| · Code Review | · 代码复审 | 120 | 120 | 
| · Test | · 测试(自我测试,修改代码,提交修改) | 240 | 360 | 
| Reporting | 报告 | 100 | 70 | 
| · Test Report | · 测试报告 | 30 | 30 | 
| · Size Measurement | · 计算工作量 | 10 | 10 | 
| · Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 60 | 30 | 
| 合计 | 990 | 1250 | 
1.3 个人接口及其实现
本次项目基本任务部分共分为输入控制、核心处理、输出控制和其他(本组计划添加GUI)组成,我所负责的部分为输入控制。(备注:由于负责优化的同学参与了代码的后期编写,所以最终结果可能和我的基本功能有些许出入,最终实现以GitHub代码为准)
1.3.1 任务需求
任务需求为:对输入进行有效性校验,识别和处理无效输入,并针对有效输入,从中提取所需数据。
根据需求定义了如下接口:
外部接口负责和其他模块通信,调用内部子接口实现功能:
/**
* get the content in a file and return the result
*/
public String parseCommand(String[] args)
子接口分别完成参数处理、获取地址、获取文本内容以及对于文本内容是否为半角字符的判断:
/**
* judge the input parameters
*/
public int paraHandling(String[] args)
/**
* get the address
*/
public String getAddress(String fileName)
/**
* get the content
*/
public String getContent(FileReader fr, BufferedReader br, StringBuffer sb, String address)
/**
* check half-width characters
*/
public int halfWidthChar(String content)
下面取两个典型代码段分析(全部代码请参见GitHub源码):
1.3.2 参与外部调用的接口,主函数通过调用该接口来读取文件并获得文件内容:
/**
* get the content in a file and return the result
*/
public String parseCommand(String[] args) {
    // initiate content file, each line, filename and address to store related info
    String address, content;
    // initiate file reader, buffered reader and string buffer to store file medially
    FileReader fileReader = null;
    BufferedReader bufferedReader = null;
    StringBuffer stringBuffer = null;
    // call the functions to get address and then content
    if (paraHandling(args) != 1) {
        // to return a void result
        return null;
    } else {
        address = getAddress(args[0]);
        content = getContent(fileReader, bufferedReader, stringBuffer, address);
        if (halfWidthChar(content) == 0) {
            return null;
        } else {
            return content;
        }
    }
}
该接口结构简单清晰,因为代码已经很好地封装在了其它函数中。
在完成了必要变量的初始化之后,直接使用简单的if结构调用内部函数就能完成相应功能。
调用内部函数的顺序为:
参数判断→获取地址→获取文本→半角字符判断
1.3.3 半角判断的函数,通过对于字符串字节长度的比较来判断文本内容是否全为半角字符:
/**
* check half-width characters
*/
public int halfWidthChar(String content) {
    if (content.getBytes().length == content.length()) {
        return 1;
    } else {
        System.out.println("half-width characters only!");
        return 0;
    }
}
1.4 测试用例的设计以及测试效率的满足
1.4.1 本次测试用例的设计采用黑盒测试和白盒测试相结合的方式
黑盒测试通过不同的输入类型(包含输入参数对应的文本文件内容类型)来测试功能的正确性;白盒测试在尽量覆盖所有路径(函数结构比较简单,所有路径大致与下列测试用例相符)的情况下对每个路径进行参数与返回值的匹配正确性测试:

1.4.2 单元测试代码举例如下:
/**
* #0 zero-parameter test (black-box)
*/
@Test
public void parseCommandTest0() throws Exception {
    String[] paras = {};
    System.out.println("parseCommand() Test0 started.");
    assertEquals("Failed",null, cp.parseCommand(paras));
    System.out.println("parseCommand() Test0 succeeded.");
    System.out.println("parseCommand() Test0 finished.");
}
所有测试用例请参见GitHub输入测试类。
1.5 测试用例的运行截图
1.5.1 单个测试用例的运行截图(代码参照上述代码):

1.5.2 所有用例的运行截图:

可以看出,每个测试用例都通过了,意味着实际输出与预期输出相一致,测试用例的质量和源代码质量都符合要求。
(所有测试用例见GitHub: UTCaseDesign_Input.xlsx,实现见测试类源代码)
1.6 小组贡献分
见毕博平台。
2 扩展功能:静态测试
2.1 选用的开发规范文档:《阿里巴巴Java开发手册》编程规约部分
该部分从命名风格、常量定义、代码格式、OOP规约、集合处理、并发处理、控制语句和注释规约八个方面详细地阐释了Java编程过程中应当注意和践行的规约,并且给出了恰当而形象的例子。
其中的编程规约主要分为“强制”、“推荐”和“参考”三类,以强制和推荐类型居多;强制的编程规约是要求程序员在Java开发过程中必须遵循的准则,如果不采用这些编程规范,则很有可能引发相当基础的错误,或者造成难以理解的歧义;推荐类型的规约则更像是告诉我们如何编写优雅高效的代码,通过简单的编程方式或者处理,我们可以让代码达到比较高的可读性和运行效果;参考给我们提供了更多可选择的编码方式,同时引发了更多关于编码技巧的思考。
举例理解:
《阿里巴巴Java开发手册》中指出:【强制】在 if/else/for/while/do 语句中必须使用大括号。即使只有一行代码,避免采用单行的编码方式:if (condition) statements。 说明:即使是最简单的一行语句,在紧接着控制语句时也应当加上大括号,使得代码结构更加清晰完整。
根据我的实践体会举例如下:以前编写代码(特别是C和C++)为了方便,很多时候都会忽略控制语句后面接的单行语句,将它们写在控制语句的同一行上面,而且不加大括号,例如:
if (count == 0) return 1;
现在想来如果这行代码前后结构很复杂,在没有大括号的情况下确实容易和其他代码混淆。因此,在控制语句中必须使用大括号是一种很实用且规范的编码方式。
2.2 组员代码分析
分析代码的作者学号后5位:17121。
为了更好地阐述分析思路,下面先给出我所分析的这一段代码:
/**
* 输出
*/
public String output(List<Map.Entry<String,Integer>> list){
    final String pathOfOutput="result.txt";
    String outContent="";
    Map.Entry<String,Integer> oMap;
    int amount=0;//仅输出单词词频从高到低排序的前100个(从1到100)
    for(Iterator<Map.Entry<String,Integer>> it=list.iterator();it.hasNext()&&amount<100;++amount){
        oMap=it.next();
        outContent+=oMap.getKey()+" "+oMap.getValue()+"\n";
    }
    outContent=outContent.substring(0,outContent.length()-1);//去除输出文件末尾多余的换行符
    writeFile(pathOfOutput,outContent);
    return outContent;
}
为了方便描述和理解,这里采用从前到后的顺序分析方式
- 第1~3行:注释,采用了/**内容*/的格式,符合规范(编程规约-注释规约-1-强制);
 - 第4行:类方法定义,接口类中方法和属性不要加任何修饰符号(public也不要),需要改进;左大括号前加空格,需要改进(编程规约-命名风格-13-推荐,编程规约-代码格式-5-强制);
 - 第5行:变量定义、赋值,名称:pathOfOutput,符合命名规范且语义明确;但双目运算符"="前后都需要添加一个空格,需要改进(编程规约-命名风格-4-强制,编程规约-代码格式-4-强制);
 - 第6行:变量定义、赋值,名称:outContent,符合命名规范且语义明确;但双目运算符"="前后都需要添加一个空格,需要改进(编程规约-命名风格-4-强制,编程规约-代码格式-4-强制);
 - 第7行:变量定义,名称:oMap,符合命名规范且语义较为明确(编程规约-命名风格-4-强制);
 - 第8行:变量定义、赋值、注释,名称:amount,语义不够明确(例如改为wordAmount可能更好一些);双目运算符"="前后都需要添加一个空格,需要改进;方法内部单行注释应该在被注释语句上方另起一行,需要改进;注释的双斜线与注释内容之间有且仅有一个空格,需要改进(编程规约-命名风格-4-强制,编程规约-代码格式-4-强制,编程规约-注释规约-4-强制,编程规约-代码格式-6-强制);
 - 第9~10行:for循环语句,for保留字与括号之间必须加空格,需要改进;双目运算符"&&"、"<"前后都需要添加一个空格,需要改进;左大括号前加空格,需要改进(编程规约-代码格式-3-强制,编程规约-代码格式-4-强制,编程规约-代码格式-5-强制);
 - 第11行:赋值表达式,双目运算符"="前后都需要添加空格,需要改进(编程规约-代码格式-4-强制);
 - 第12行:赋值表达式,双目运算符"+="和"+"前后都需要添加空格,需要改进(编程规约-代码格式-4-强制);
 - 第13行:右大括号前后换行,符合规范(编程规约-代码格式-1-强制);
 - 第14行:赋值表达式,双目运算符"="和"-"前后都需要添加空格,需要改进;定义或传递多个参数时,需要在逗号后加空格,需要改进;方法内部单行注释应该在被注释语句上方另起一行,需要改进;注释的双斜线与注释内容之间有且仅有一个空格,需要改进(编程规约-代码规范-4-强制,编程规约-代码规范-8-强制,编程规约-注释规约-4-强制,编程规约-代码格式-6-强制);
 - 第15行:方法调用,定义或传递多个参数时,需要在逗号后加空格,需要改进(编程规约-代码规范-8-强制);
 - 第16行:return语句,符合规范;
 - 第17行:右大括号前换行,符合规范(编程规约-代码格式-1-强制)。
 
2.3 静态代码检查工具
此次选择的静态代码检查工具是阿里的 Alibaba Java Coding Guidelines,与之前使用的《阿里巴巴Java开发手册》高度吻合,因此比较统一。
我使用该工具的方法是下载IDEA插件,GitHub地址为:
https://github.com/alibaba/p3c
同时也可以在IDEA的如下界面——Preferences(MacOSX)配置(Windows在File-Settings里配置):

2.4 静态检查结果
截图如下,可见,自己编写的代码有很多不符合规范的地方,还需要慢慢学习和改正。具体不符合规范之处就不一一列举,感兴趣的读者可以参见《阿里巴巴Java开发手册》。


存在的问题以及改进方法:
- if/else后没有加大括号,就算是只有一行也应该加上;
 - 出现魔法值,应该先定义常量;
 - 没有添加类创建者信息,每一个类都应该添加创建者信息;
 - 方法内部的单行注释都必须在原语句上另起一行;
 - 类、类属性、类方法的注释必须符合形如/**注释*/的规范。
 
2.5 小组代码整体分析
通过之前的组员互评以及后续的讨论,我们发现我们的代码规范问题主要集中在注释和if/else等控制语句后的大括号上面,通过与《阿里巴巴Java开发手册》对比,我们将我们的代码进行了改进,并最终呈现为最后提交到GitHub上的代码。
我自己修改后的部分代码及检测结果如下:

可见所有代码都符合了对应的编程规范。
3 高级任务:性能测试和优化
3.1 测试数据集设计思路
- 单元测试数据集:单元测试数据及也应采用黑盒测试和白盒测试相结合的方式,完整覆盖每一个功能,如果采用路径覆盖的白盒测试,就应做到对所有路径的完全覆盖;
 - 集成测试数据集:基于黑盒测试设计思想,对整个程序的功能进行测试,选用内容足够大且复杂的文件进行测试。
 
3.2 优化前的程序性能指标
由于各用户机器类型和性能有所差异,这里给出预期的优化率代替性能指标,预期优化率:50%
附性能检测部分代码:
//获取开始时间
long startTime = System.currentTimeMillis();
//获取结束时间
long endTime = System.currentTimeMillis();
//输出程序运行时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
3.3 同行评审过程
- 参与者:17122 17121 17098 17103;
 - 主持人&记录员:17122;
 - 评审员:17122 17121 17098 17103(交叉互审);
 - 讲解员:17098(代码深入分析、知识普及);
 - 评审内容:各功能模块;
 - 意见小结:代码规范可以改进、代码可以持续优化。
 
3.4 评审结论
影响性能的主要因素是循环的低效率和正则式自身的可优化特性,与同行评审大致相符。
- 正则表达式效率较慢,可以用状态机来提取单词。
 - 考虑到程序对查找的性能要求比较高,单词统计我们采用HashMap来存储。当数据容量较少时其内部实现为一个链表,当数据量较大时,自动改用二叉树进行存储,有效提高了查询效率。
 - 输出单词时,改变原来的每个单词打开一次文件的做法,只打开一次文件,全部输出后关闭文件流,提高了IO速度。
 
3.5 优化设计思路
去掉不必要的循环,同时采用比正则式更优的分词方式,性能指标同比增长100%(耗时为50%)。
3.6 附加功能
我们小组设计实现了GUI设计。
3.7 项目小结
个人认为它们的大致联系为:
基本任务——软件开发;
扩展任务——软件测试;
高级任务——软件质量;
当然,不可否认的是,基本任务中也包含了单元测试,但我认为单元测试也算是开发工作的一部分,同时也肯定是整个测试过程中的一环;值得注意的是,测试工作其实贯穿从基本任务到高级功能实现的整个过程,从始至终为高质量的软件开发提供支持和保证。
软件开发是手段,软件测试是工具,软件质量是目的。在产品开发的整个过程中我们都需要兼顾三者,权衡比重,保证软件过程的顺利、高效进行。
WcPro项目(WordCount优化)的更多相关文章
- 仿百度壁纸客户端(六)——完结篇之Gallery画廊实现壁纸预览已经项目细节优化
		
仿百度壁纸客户端(六)--完结篇之Gallery画廊实现壁纸预览已经项目细节优化 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度 ...
 - HUST软测1504班第4周小组作业成绩:WordCount优化
		
说明 本次公布的成绩为第四周作业的结果: 第4周小组作业:WordCount优化 博客推荐:本次作业有一位同学完成有创意,推荐优秀博客.(优秀博客不会对成绩带来正面或者负面影响)PS:做任何创新的任务 ...
 - 仿百度壁纸client(六)——完结篇之Gallery画廊实现壁纸预览已经项目细节优化
		
仿百度壁纸client(六)--完结篇之Gallery画廊实现壁纸预览已经项目细节优化 百度壁纸系列 仿百度壁纸client(一)--主框架搭建,自己定义Tab + ViewPager + Fragm ...
 - vue+webpack+element-ui项目打包优化速度与app.js、vendor.js打包后文件过大
		
从开通博客到现在也没写什么东西,最近几天一直在研究vue+webpack+element-ui项目打包速度优化,想把这几天的成果记录下来,可能对前端牛人来说我这技术比较菜,但还是希望给有需要的朋友提供 ...
 - 【Vuejs】335-(超全) Vue 项目性能优化实践指南
		
点击上方"前端自习课"关注,学习起来~ 前言 Vue 框架通过数据双向绑定和虚拟 DOM 技术,帮我们处理了前端开发中最脏最累的 DOM 操作部分, 我们不再需要去考虑如何操作 D ...
 - 个人项目WordCount(C++/QT)
		
个人项目WordCount(C++/QT) GitHub项目地址:https://github.com/Nova-cjp/Word-Count 百度云链接:https://pan.baidu.com/ ...
 - vue大型项目高性能优化----想说爱你真的不容易
		
一.背景 目前公司的电子合同采用表单设计器+合同业务配合实现,做了半年多后终于上线,但是下边员工普遍反映卡顿,甚至卡死,爆栈.尤其是新增和修改合同页面,因为这部分数据量大,逻辑复杂,很容易崩溃,所 ...
 - 第四周小组作业:Wordcount优化
		
1.小组github地址 https://github.com/muzhailong/wcPro 2.PSP表格 PSP2.1 PSP阶段 预计耗时(分钟) 实际耗时(分钟) Planning 计划 ...
 - WordCount优化
		
Github 地址:chaosrings/wcPro 1.PSP2.1表格 psp 2.1 psp阶段 预估耗时(分钟) 实际耗时(分钟) Planning 计划 10 10 Estimate 估计这 ...
 
随机推荐
- 【Unity]】AR小工具-Vuforia
			
很有意思的增强现实玩具,六分钟应用. https://www.youtube.com/watch?v=khavGQ7Dy3c
 - java对象在内存中的结构
			
在HotspotJVM中,32位机器下,Integer对象的大小是int的几倍? 我们都知道在java语言规范已经规定了int的大小是4个字节,那么Integer对象的大小是多少呢?要知道一个对象的大 ...
 - bat执行python脚本,执行多条命令
			
1.新建一个txt文档,输入以下命令 @echo offcmd /k python F:\Pycharm_Projection\Test\test2.py 2.将txt文档保存为.bat格式,然后双击 ...
 - Saltstack自动化操作记录(2)-配置使用
			
之前梳理了Saltstack自动化操作记录(1)-环境部署,下面说说saltstack配置及模块使用: 为了试验效果,再追加一台被控制端minion机器192.168.1.118需要在master控制 ...
 - [Ynoi2018]末日时在做什么?有没有空?可以来拯救吗?
			
这道题真的超级...毒瘤 + 卡常 + 耗 RP 啊... 传送门 noteskey 题解看 shadowice 大仙 的 code 如果发现自己 T 掉了,别心急,洗把脸再交一遍试试... //by ...
 - Android串口通信(Android Studio)
			
gilhub上已有开源项目: https://github.com/cepr/android-serialport-api 可以直接使用
 - 【原创】大数据基础之HDFS(2)HDFS副本数量检查及复制逻辑
			
HDFS会周期性的检查是否有文件缺少副本,并触发副本复制逻辑使之达到配置的副本数, <property> <name>dfs.replication</name> ...
 - java集合(list,set,map)
			
集合 集合与数组 数组(可以存储基本数据类型)是用来存现对象的一种容器,但是数组的长度固定,不适合在对象数量未知的情况下使用. 集合(只能存储对象,对象类型可以不一样)的长度可变,可在多数情况下使用. ...
 - VUE项目的目录关系
			
1.页面中只有一个index.html. 2.一个js文件.在路由中. 3.主要的app.vue. 4.最后就是可以放多个vue文件的~~(一个页面对应一个vue文件,一个vue组件对应一个js中的i ...
 - 表单组件 form  fastadmin(生成表单元素)
			
Form组件 定义文件位置: /extend/fast/Formphp 通用参数 $name 通常为我们组件的名称(name属性值),我们在后台接收时可以通过这个名称来获取到它所对应的值 $value ...