第4周小组作业:WordCount优化
0. 开始之前
在第一个实践作业中,我们分别实现了一个WordCount小程序,并实现了初步的单元测试。但仅仅满足功能要求就可以了吗?软件开发的最终目标是满足用户对软件产品的质量要求,让我们一起来把这个小程序升级为能稳定运行,给用户提供高质量服务的软件吧。
三个臭皮匠,顶个诸葛亮。本次作业将从个人英雄主义时代进入协作时代,作业将通过小组来完成,希望组员们在组长的带领下精诚合作。
1. 截止日期和提交通道
本次作业的提交截止时间:2018年4月9日00:00。
本次作业需要在如下通道进行提交:
(1)在Github提交代码。作业涉及的源代码及文档材料,根据作业要求,分期在Github上进行提交。对应网址:https://github.com/;
(2)在博客园提交博客作业。小组作业涉及的博客需在博客园的班级博客中提交作业。即发布博客后,需在班级博客的作业中提交。对应网址:https://www.cnblogs.com/;
(3)在课堂平台的作业中提交。请到第4周课程内容中查看第4周小组作业,将博客地址粘贴在作业中,提交即可。对应网址:https://elearning.hust.edu.cn。
2. 作业目标和要求
作业简述:根据需求,完成WordCount的改进版,并对其进行一系列测试和优化。
作业目标:通过基于框架的单元测试、静态测试、以及性能测试,发现编码的问题,提升软件性能,打造能稳定运行的软件。
本次作业分为三步,具体要求说明如下。
2.1 基本任务:代码编写+单元测试
注意:所有小组成员完成基本任务要求即可,视完成情况,最高可得本次作业满分的约70%。
任务简述:仔细阅读需求(见附录1:WordCount优化版功能需求说明),改进程序并将功能封装成独立模块,编写单元测试。
2.1.1 任务说明
如果程序中不同功能的代码混杂在一起,会对后期的维护造成很大的麻烦,我们应该精心优化程序的组织结构。
所以,任务要求各组把各部分功能封装成独立模块,分别由不同的组员负责。每个组员在提交代码之前,要使用单元测试框架,对自己的模块进行单元测试。尽量降低自己模块的修改对其他模块造成的影响。
建议封装成以下这些模块:
(1)输入控制
对输入进行有效性校验,识别和处理无效输入,并针对有效输入,从中提取所需数据。
(2)核心处理
对输入进行处理,如单词词频统计,排序等,完成对应业务需求。
(3)输出控制
对结果以合理方式输出,将单词词频排序的结果输出到文件。
(4)其他
一些特殊模块,如和架构相关的(例如main函数等)。
2.1.2 项目要求
围绕2.1.1的说明,各小组应完成下述任务:
(1)给出任务分工,商议好模块间的接口,将项目框架和分工提交到小组Github;
(2)各组员独立完成自己所负责的模块的编码,并提交到小组Github;
(3)各组员针对自己的代码,采用黑盒和白盒测试方法,设计至少20个测试用例,填写测试用例清单,整理测试数据集;
(4)各组员采用单元测试框架,编写单元测试脚本,并提交到小组Github,测试结果不需要提交;
(5)将所有代码集成,打包成exe文件,提交到小组Github。
(6)使用git tag stage1,标记基本任务已经完成。往Github提交时,使用--tags参数,将tag推送到Github。
注:
建议另外创建小组的Git,也可以是组长的Git;测试用例文档模板见附录2:测试用例文档模板。
对测试用例、测试数据集、测试脚本的要求详见评分细则。
2.1.3 博客要求
(1)博客开头给出Github项目地址;
(2)预估项目完成时间,完成PSP表格填写(程序完成后,需再次在PSP表格中记录实际花费的时间);
(3)在自己的个人博客中说明对该接口的实现,请勿简单贴代码;
(4)说明如何考虑测试用例的设计,如何满足测试效率的要求,请勿简单罗列测试用例;
(5)给出单元测试的运行截图,评价测试质量和被测模块的质量;
(6)根据小组讨论的结果,说明自己的小组贡献分。
注:PSP最新表格见附录3:PSP2.1表格;小组贡献分的说明,详见评分细则。
2.2 扩展任务:静态测试
注意:小组中学有余力的同学,可继续完成扩展任务要求,视完成情况,最高可得本次作业满分的约85%。
且如果全部组员均完成本次扩展任务,则每个成员本次作业最终得分为原始分的105%。
2.2.1 任务说明
基本任务中,大家完成了对代码的动态测试。
然而,在提交代码之前,最好能利用工具,对代码进行静态扫描,以达到以下效果:
(1)确保整个小组中所有人员的代码不会有一些常见的漏洞;
(2)确保整个小组中所有人员的代码符合行业规范;
(3)确保整个小组中所有人员的代码符合最基本的行业质量要求的。
2.2.2 项目要求
围绕2.2.1的说明,各小组针对本组选定的开发语言,应完成下述任务:
(1)各组员阅读对应开发规范,选择其中部分规范,举例说明自己对该规范的理解。
(2)各组员参照选定的那部分规范,对小组中另一个组员的部分代码进行评价。
(3)各组员选择至少一款静态代码检查工具,对自己的全部代码进行扫描,统计发现的错误和警告。
(4)各组员结合扫描的结果和其他人的意见,分析并改进自己的代码,再次运行单元测试,观察和之前有何不同。
(5)共同对整个小组的代码进行评价,反思主要存在的问题,并改进代码。将改进后的代码提交到Github。
(6)使用git tag stage2,标记扩展任务已经完成。往Github提交时,使用--tags参数,将tag推送到Github。
注:
Java和C++语言的开发规范详见附录4:开发规范说明。(建议从我们给的开发规范中选择,也可以自己选取其他的规范文档)
静态代码检查工具详见附录5:静态代码检查工具。
【对规范的理解】范例如下:
《阿里巴巴Java开发手册》中指出:【推荐】如果模块、接口、类、方法使用了设计模式,在命名时体现出具体模式。 说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。
根据我的实践体会举例如下:在代码“public class OrderFactory;”中,类名称的命名就体现了工厂模式的使用。
2.2.3 博客要求
(1)说明选择了哪种开发规范文档中的哪一部分;如果选择的不是附录4中的规范,说明选择的理由,并给出该文档的链接。
(2)说明使用该规范分析了哪位组员(说明学号后5位即可)的代码,并说明其代码有什么问题,或者说明其代码遵循了哪些好的规范。
(3)说明选择的是什么静态代码检查工具,给出工具的下载地址。
(4)说明工具对代码扫描的结果,应给出界面运行截图。并说明代码存在的问题和改进的方法。如果实在找不到问题,也可分析一下自己的代码遵循了哪些好的规范。
(5)说明整个小组的代码主要存在的问题,并说明代码改进的方法,最好能给出图、表等形式。
2.3 高级任务:性能测试和优化
注意:小组中学有余力的同学,可继续完成高级任务要求,视完成情况,最高可得本次作业满分的100%。
且如果大部分组员(仅缺席一名组员)均完成本次扩展任务,则每个成员本次作业最终得分为原始分的110%。高级任务与扩展任务的奖励分数不叠加。
2.3.1 任务说明
对于一个执行统计和排序的程序来说,内存的占用,运算的速度,都是要满足一定要求的。
所以我们需要设计程序的性能测试,来了解我们的程序是否符合这方面的要求,并根据测试的结果进行优化和改进。
2.3.2 项目要求
围绕2.3.1的说明,各小组应完成下述任务:
(1)考虑多大的数据量会给程序带来压力,并由此构建测试数据集,即一个在内容上能造成足够压力的txt文档。
(2)使用测试数据集,对当前程序的主要性能指标(即处理时长,以毫秒计算)进行测试和记录。
(3)通过组内所有成员展开同行评审,针对可能影响或制约程序性能指标的主要因素加以讨论。
(4)通过测试,发现影响或制约程序性能指标的主要因素,并与同行评审的结论进行比较,看二者是否一致;
(5)对程序代码加以改进,优化程序性能(此步骤可选);
(6)使用git tag stage3,标记高级任务已经完成。往Github提交时,使用--tags参数,将tag推送到Github。
注:
处理时长:在程序读取txt文件时开始计时,一直到程序将所有结果输出到结果文件时结束;
同行评审的内容和过程详见附录6:同行评审和代码复审;
2.3.3 博客要求
(1)说明测试数据集的设计思路。
(2)说明优化前的程序性能指标。
(3)说明同行评审的过程,包括有哪些人参加,谁主持,谁评审,对什么进行评审,提出了什么意见等。
(4)说明实际测试后得到的结论,即影响性能指标的主要因素是什么,如果与同行评审的结论不一致,分析为什么会不一致。
(5)说明优化的设计思路,并给出优化后的程序性能指标。
(6)结合本次作业实践,说明通过基本任务、扩展任务、到高级任务的完成,如何体现软件开发、软件测试、软件质量之间的关系。
2.4 附加题
通过图形用户界面提供WordCount优化版的功能。形式如下:
wcPro.exe -x //该参数单独使用,如果命令行有该参数,则程序会显示图形界面,用户可以通过界面选取单个txt文件,程序就会对该文件进行单词词频统计和排序,结果仍以指定格式输出到默认文件中。
3. 附录
3.1 附录1:WordCount优化版功能需求说明
WordCount优化版的需求可以概括为:对记事本(txt)文件进行单词的词频统计和排序,排序结果以指定格式输出到默认文件中,并要求能够快速地完成整个统计和结果输出功能。
可执行程序命名为:wcPro.exe,该程序处理用户需求的模式为:
wcPro.exe [input_file_name]
存储统计结果的文件为result.txt,放在与wcPro.exe相同的目录下。
具体细则见2.1.1到2.1.7的说明。
3.1.1 被处理的文件
第一,仅处理txt文件,不处理其他类型的文件。
第二,一次仅处理一个文件,不同时处理多个文件。
3.1.2 文件内容
文件中仅包含单词(a-z, A-Z)、常见字符、数字(0-9)。不包含其他内容。
3.1.3 对单词的规定
满足如下两个条件中的任意一个条件,则视为单词,
第一,由连续的若干个英文字母组成的字符串,例如,software,
第二,用连字符(即短横线)所连接的若干个英文单词也视为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。
3.1.4 对常见字符的规定
文件中包含的常见字符如下表所示,该表以外的特殊字符不考虑。
字符 |
~ |
` |
! |
# |
% |
^ |
& |
* |
_ |
... |
含义 |
波浪号 |
重音符号 |
感叹号 |
井号 |
百分号 |
指数符号 |
与符号 |
星号 |
下划线 |
省略号 |
字符 |
( ) |
[ ] |
+ |
= |
- |
: |
; |
“ |
‘ |
| |
含义 |
左右 小括号 |
左右 方括号 |
加号 |
等于号 |
短横线 |
冒号 |
分号 |
双引号 |
单引号 |
竖线 |
字符 |
< |
> |
, |
. |
/ |
? |
|
|
|
|
含义 |
小于号 |
大于号 |
逗号 |
点 |
反斜杠 |
问号 |
空格 |
换行符 |
水平制表符 |
|
3.1.5 对词频的定义
词频即某单词在文档中出现的次数。
3.1.6 对输出的规定
仅输出单词词频从高到低排序的前100个(从1到100),每行分别给出一个单词及其词频,单词按小写形式给出,单词和词频之间空一格。对于单词词频相同的情况,按照单词所包含的每个字母从a到z的次序依次排列。输出文件末尾多余的换行符应去除。
形式如下:
this 200 i 180 ij 180 the 180 |
3.1.7 对语言的规定
程序要求用Java或C++实现,其他语言恕不接受。
3.2 附录2:测试用例文档模板
测试用例设计清单(模板)。(受版权限制,测试用例设计清单请在课程平台的作业内容中点击链接下载)
注意:填写测试用例时,请在备注中说明使用的测试用例设计方法。
3.3 附录3:PSP2.1表格
最新的PSP2.1表格如下表所示。
PSP2.1表格
PSP2.1 |
PSP阶段 |
预估耗时 (分钟) |
实际耗时 (分钟) |
Planning |
计划 |
||
· Estimate |
· 估计这个任务需要多少时间 |
||
Development |
开发 |
||
· Analysis |
· 需求分析 (包括学习新技术) |
||
· Design Spec |
· 生成设计文档 |
||
· Design Review |
· 设计复审 (和同事审核设计文档) |
||
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
||
· Design |
· 具体设计 |
||
· Coding |
· 具体编码 |
||
· Code Review |
· 代码复审 |
||
· Test |
· 测试(自我测试,修改代码,提交修改) |
||
Reporting |
报告 |
||
· Test Report |
· 测试报告 |
||
· Size Measurement |
· 计算工作量 |
||
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
||
合计 |
3.4 附录4:开发规范说明
软件开发,当然是要有规范的。正所谓:码出高效,码出质量。代码评审,当然也是要采用一定的评审标准的。没有标准,如何评审代码?
Google很早就这样做了。Google将公司内部采用的所有语言的编码规范(其称为Style Guide)都开源在Github上。这份清单中包括了C++、Objective-C、Java、Python、R、Shell、HTML/CSS、JavaScript、AngularJS、Common Lisp、Vimscript等语言的编程规范。并且Google还发布了一个用于检查样式合规性的工具cpplint以及在Emacs中使用Google编程样式的配置文件google-c-style.el。
阿里巴巴也在做相同的事情,《阿里巴巴Java开发手册》就是阿里巴巴集团技术团队的集体智慧结晶和经验总结,经历了多次大规模一线实战的检验及不断的完善,于2017年11月30日正式对外发布,后经多次优化改版。
3.4.1 代码规范与复审(精简版)
如果你不想花太多精力来看几十页的代码规范,不妨直接去看邹欣老师在讲义“现代软件工程讲义 3 代码规范与代码复审”中所讨论的有关代码规范与代码复审的内容。内容短小精炼,适合快速入门。
3.4.2 阿里巴巴Java开发手册
如果你选用Java为开发语言,请直接到官网查看完整的阿里巴巴Java开发手册。
3.4.3 谷歌C++风格指南
如果你选用C++为开发语言,请阅读Google之C++风格指南(中文版),查看谷歌如何从头文件、作用域、类、函数等方面对编码进行规定。如果你希望阅读原汁原味的英文原版,请访问:https://github.com/google/styleguide。
3.4.4 其他语言代码规范
如果你想顺便了解其他语言代码规范,请访问如下地址:https://blog.csdn.net/lavorange/article/details/51441695。
3.5 附录5:静态代码检查工具
代码评审,全靠人工,可能是一件痛苦而低效的事情,通过采用静态代码检查工具,可以大大提高工作效率。
对于使用Java为开发语言的小组,不妨阅读静态代码检查工具简介来初步了解和筛选合适的静态代码检查工具。
对于使用C++为开发语言的小组,则可通过谷歌的cpplint、cppcheck等工具来执行静态代码扫描。
当然,也可以访问课程资源,了解有关国内自主产权的代码扫描工具CodeAnalyzer(CA)工具。
3.6 附录6:同行评审和代码复审
有关同行评审和代码复审的内容,大家可以阅读邹欣老师的博客:“代码规范与代码复审”,也可以到课程平台的第3周 白盒测试(续),观看和了解相关内容。
4. 评分细则
本次作业总分66分。具体细则如下表所示。
基本任务评分细则 |
|||||
序号 |
评分项 |
评分子项 |
评分细则 |
备注 |
满分 |
1 |
程序作业 (30分) |
独立模块编码 |
代码符合接口设计,设计合理,注释合理 |
个人分 |
5分 |
测试用例设计 |
测试用例格式规范,设计合理,至少20个,至少能结合课堂介绍的方法来设计测试用例。 |
个人分 |
3分 |
||
单元测试脚本 |
能使用测试框架编写测试脚本,测试脚本设计合理,满足对测试用例的覆盖要求,与测试数据独立,便于重用,便于管理,注释合理,能体现单元测试的运行及结果。(可参照课堂讲解来编写脚本) |
个人分 |
8分 |
||
接口及框架搭建 |
接口定义清晰,框架设计合理。 |
小组分 |
4分 |
||
源代码管理 |
通过源代码管理中的commit注释信息,增量修改的内容,是否有运行说明、任务分工等给分。 |
小组分 |
5分 |
||
程序正确性 |
应围绕需求,满足基本的正确性要求,运行结果应正确无误,有exe文件。 |
小组分 |
5分 |
||
2 |
博 客 (15分) |
Github项目地址 |
在文章开头给出Github项目地址,地址缺失或错误均不得分。 |
个人分 |
1分 |
填写PSP表格 |
包括程序开发前预估的各模块开发时间, 及程序各模式的实际开发时间。 |
个人分 |
2分 |
||
描述代码设计思路 |
说明如何设计实现该接口。 |
个人分 |
3分 |
||
测试设计过程 |
如何设计测试用例,如何满足测试效率的要求。 |
个人分 |
3分 |
||
测试运行和评价 |
给出单元测试的运行截图,评价自己的单元测试效果以及被测模块的质量水平。 |
个人分 |
4分 |
||
作业改进 |
对老师和助教的点评做出了中肯的回应,包括回复评论与改进博客,可得2分; 否则,如不回应老师和助教的点评,或不改进博客,或随便敷衍老师和助教的点评(例如,“嗯嗯”“好”等),则不得分 |
个人分 |
2分 |
||
3 |
|
小组贡献率 |
应清晰说明小组贡献率的分配方案。 |
不适用 |
|
扩展任务评分细则 |
|||||
序号 |
评分项 |
评分子项 |
评分细则 |
备注 |
满分 |
1 |
程序作业 (6分) |
源代码管理 |
通过源代码管理中的commit注释信息,增量修改的内容 |
小组分 |
1分 |
交叉代码评审 |
对其他组员的代码进行检查。 |
小组分 |
1分 |
||
静态代码扫描 |
使用代码扫描工具检查代码,检查自己的所有代码。 |
个人分 |
2分 |
||
代码改进和单元测试 |
代码改进,重新运行单元测试。 |
小组分 |
2分 |
||
2 |
博客 (5分) |
开发规范说明 |
说明选定的开发规范,以及用于检查代码的内容。 |
个人分 |
1分 |
交叉代码评审 |
说明代码评审对象,分析结论清晰,有理有据。 |
个人分 |
1分 |
||
静态代码扫描 |
说明使用的扫描工具,给出下载地址。 说明扫描结果,给出运行截图,分析结论清晰,有理有据。 |
个人分 |
2分 |
||
组内代码分析 |
说明整个小组的代码质量,分析结论清晰,有理有据。 |
个人分 |
1分 |
||
3 |
|
小组贡献率 |
应清晰说明小组贡献率的分配方案。 |
不适用 |
|
高级任务评分细则 |
|||||
序号 |
评分项 |
评分子项 |
评分细则 |
备注 |
满分 |
1 |
程序作业 (5分) |
测试数据集 |
测试数据集设计合理。 |
小组分 |
1分 |
性能指标记录 |
记录程序优化前和优化后的处理时长 |
小组分 |
1分 |
||
同行评审 |
能展开同行评审 |
小组分 |
1分 |
||
性能分析和优化 |
找到制约性能的因素,提升性能 |
小组分 |
2分 |
||
性能排名 |
按照程序处理时长(耗时最短)排名,前30% |
附加分 |
3分 |
||
2 |
博客 (5分) |
测试数据集 |
说明测试数据集的设计思路,描述清晰。 |
个人分 |
1分 |
同行评审过程描述 |
过程描述清晰,结论明确。 |
个人分 |
1分 |
||
性能分析 |
能清晰说明同行评审与实测的差异,得出有关影响程序性能的因素分析的结论。 |
个人分 |
1分 |
||
性能优化 |
清晰说明性能优化的设计思路 |
个人分 |
1分 |
||
作业小结 |
能结合本次实践来谈软件开发、软件测试、软件质量之间的关系。论述清晰。 |
个人分 |
1分 |
||
3 |
|
小组贡献率 |
应清晰说明小组贡献率的分配方案。 |
不适用 |
|
附加题评分细则 |
|||||
序号 |
评分项 |
评分子项 |
评分细则 |
备注 |
满分 |
图形用户界面 |
按照2.4节完成WordCount的图形用户界面功能,且运行正确。 |
附加分 |
5分 |
4.2 小组贡献率及其与作业分的关系
小组作业中,每个同学都是为了小组荣誉而“战”,采用小组贡献率来评价大家的贡献,要求如下:
(1)小组贡献率在0到1之间取值;
(2)每人的贡献率不能相同;
(3)所有成员的贡献率总和应等于1;
(4)贡献率精确到小数点后2位。
个人作业最终得分 = 小组分 * 实际贡献率 / 人均应贡献率 + 个人分 + 附加分。(附加分不计入作业映射分)
以4人小组为例,在基本任务中,小组分为12分,甲、乙、丙、丁四人对小组的贡献率分别为0.3, 0.25, 0.35, 0.2。此时,人均应贡献率为0.25(即1/4),而甲的个人分为26分,则甲的最终得分 = 12 * 0.3 / 0.25 + 26 = 40.4分。
4.3 补充说明
(1)对于完成了扩展任务,甚至完成了高级任务的小组而言,小组贡献率在全部作业完成后一并给出,例如,某小组在完成基本任务的基础上,还完成了扩展任务,则给出的小组贡献率是针对基本任务和扩展任务的总体贡献率,不单独计算针对每个任务的小组贡献率。
(2)对于完成了扩展任务,甚至完成了高级任务的小组而言,博客一次性提交,即,基本任务、扩展任务、高级任务的博客作业对应一篇博客。按照各次作业的博客内容要求,分标题撰写即可。不必写多篇博客。针对博客评论的改进同此要求。
5. 其他注意事项
注意按时提交作业。
- 按时间完成并提交——正常评分
- 晚交一周以内——0分
- 迟交一周以上或不交——倒扣本次作业分数
- 抄袭——按本次作业满分的两倍倒扣分数。【严禁代码与博客等一切形式的抄袭!请各位同学千万不要触碰底线!】