福大软工1816 · 第二次做业 - 我的项目

Deadline: 2018-09-12 23:00pmhtml


零、任务

实现一个可以对文本文件文件中的单词的词频进行统计的控制台程序。java

1、编码要求

  1. 按照[附录1]提示,Fork github 项目到本身的仓库,在Github仓库中新建一个学号为名的文件夹,完成项目后正确发起一个Pull Request,并确保本身的代码最终成功签入(成功签入将在源仓库中看到本身学号为名的文件夹)。
  2. 在开始实现程序以前,在PSP表格[附录2]记录下你估计在程序开发各个步骤上耗费的时间,在你实现程序以后,在PSP表格记录下你在程序的各个模块上实际花费的时间。
  3. 使用C++ 或者Java语言实现,C++请使用Visual Studio Community 2017进行开发,运行环境为64-bit Windows 10。
  4. 提交的代码要求通过Code Quality Analysis工具的分析并消除全部的警告。
  5. 完成项目的首个版本以后,请使用性能分析工具Studio Profiling Tools来找出代码中的性能瓶颈并进行改进。
  6. 使用Github[附录3]来管理源代码和测试用例,代码有进展即签入Github。签入记录不合理的项目会被助教抽查询问项目细节。
  7. 使用单元测试[附录4]对项目进行测试,并使用插件查看测试分支覆盖率等指标;写出至少10个测试用例确保你的程序可以正确处理各类状况。

2、博客撰写要求

  1. 在文章开头给出Github项目地址。
  2. 给出PSP表格。
  3. 解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的过程。
  4. 设计实现过程。设计包括代码如何组织,好比会有几个类,几个函数,他们之间关系如何,关键函数是否须要画出流程图?单元测试是怎么设计的?
  5. 记录在改进程序性能上所花费的时间,描述你改进的思路,并展现一张性能分析图(由VS 2017的性能分析工具自动生成),并展现你程序中消耗最大的函数。
  6. 代码说明。展现出项目关键代码,并解释思路与注释说明。
  7. 结合在构建之法中学习到的相关内容与我的项目的实践经历,撰写解决项目的心路历程与收获。

3、需求

实现一个命令行程序,不妨称之为WordCount。git

第一步、实现基本功能

输入文件名以命令行参数传入。例如咱们在命令行窗口(cmd)中输入:github

//C语言类
WordCount.exe input.txt
//Java语言
java WordCount input.txt

则会统计input.txt中的如下几个指标算法

  • 统计文件的字符数:
    • 只须要统计Ascii码,汉字不需考虑
    • 空格,水平制表符,换行符,均算字符
  • 统计文件的单词总数,单词:至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。
    • 英文字母: A-Z,a-z
    • 字母数字符号:A-Z, a-z,0-9
    • 分割符:空格,非字母数字符号
    • 例:file123是一个单词, 123file不是一个单词。file,File和FILE是同一个单词
  • 统计文件的有效行数:任何包含非空白字符的行,都须要统计。
  • 统计文件中各单词的出现次数,最终只输出频率最高的10个。频率相同的单词,优先输出字典序靠前的单词。
  • 按照字典序输出到文件result.txt:例如,windows95,windows98和windows2000同时出现时,则先输出windows2000windows

    • 输出的单词统一为小写格式
  • 输出的格式为架构

characters: number
words: number
lines: number
<word1>: number
<word2>: number
...

第二步、接口封装

在写了一些代码开胃以后,你们都完成了一份知足WordCount基本功能的代码。
你们的代码都各有特点,若是如今咱们要把这个功能放到不一样的环境中去(例如,命令行,Windows图形界面程序,网页程序,手机App),就会碰到困难:代码散落在各个函数中,很难剥离出来做为一个独立的模块运行以知足不一样的需求。
同时咱们也看到,不一样的代码解决不一样层面的问题:框架

  1. 有些是计算数据的(例如统计单词)
  2. 有些是控制输入的(例如scanf,cin,图形界面的输入字段)
  3. 有些是数据可视化的(例如printf,cout,println,DrawText)
  4. 有些则更为特殊,是架构相关的(例如main函数,并非全部的程序都须要某个特定格式的main)

这些代码的种类不一样,混杂在一块儿对于后期的维护扩展很不友好,因此它们的组织结构就须要精心的整理和优化。
咱们但愿把基本功能里的:函数

  1. 统计字符数
  2. 统计单词数
  3. 统计最多的10个单词及其词频

这三个功能独立出来,成为一个独立的模块(class library, DLL, 或其它)。这样的话,命令行和GUI的程序都能使用同一份代码。为了方便起见,咱们称之为计算核心"Core模块",这个模块至少能够在几个地方使用:工具

  1. 命令行测试程序使用
  2. 在单元测试框架下使用
  3. 与数据可视化部分结合使用

把计算核心在单元测试框架中作过完备的测试后,咱们就能够在算法层级保证了这个模块的正确性。
但咱们知道软件并不是只有计算核心,实际的软件是交付给最终用户的软件,除了计算核心外,还须要有必定的界面和必要的辅助功能。
这个Core模块和使用它的其余模块之间则要经过必定的API来交流。
API应该怎么设计呢?
为了方便起见,咱们能够从下面的最简单的接口开始(仅举例,你的代码里可能没有这个函数):

int countChar(File *file)

这个函数表示输出一个文件指针,返回这个文件的字符数。
假设咱们用Core封装了这个接口,那么咱们的测试程序能够是这样:

File *in = fopen("input.txt","r");
int count = 100;
Assert(countChar(in) == count);

固然,这样的测试程序并不充分,但愿你们测试时不要像这样偷懒。

4、测试须知

组织目录

助教在测试时,将运行自动测试程序编译源文件并运行,进行批量测试,所以请保证项目的组织目录符合要求.

Java

对于使用Java语言的项目有如下两点要求:

  1. 【以学号为名的文件夹中】的目录下必须有src文件夹
  2. 在src目录下必须有名为Main.java文件,且Main.java中包含 public static void main(String[] args) 方法

一个Java项目的示例组织目录以下所示:

031602111 (文件夹名字为学号)
|- src
  |- Main.java(主程序,能够从命令行接收参数)
  |- lib.java(包含其它自定义函数,能够有多个,对名字不作要求)

C++

对于使用C++ 语言的项目有如下两点要求:
【以学号为名的文件夹中】的目录下必须有src文件夹,在src文件夹中是可在VS2017下编译运行的解决方案,解决方案的名字必须为 WordCount,一个C++工程示例组织目录以下所示:

031602111 (文件夹名字为学号)
|- src
   |- WordCount.sln
   |- WordCount
       |- stdafx.cpp
       |- stdafx.h
       |- WordCount.cpp
       |- WordCount.vcxproj

助教在测试时,将自动按照指定编译环境编译源代码,并利用命令行进行批量测试。

错误处理

本次自动测试会加入各类各样出错状况的测试,要求开发者程序不能崩溃,而且可以尽量精确报错。你能够有“容错性”的出错设计,但必须输出必要的提示或说明。

5、评分规则

博客评分规则

  1. 在文章开头给出你所Fork的同名仓库的Github项目地址。(1')
  2. 在开始实现程序以前,在下述PSP表格记录下你估计将在程序的各个模块的开发上耗费的时间。(5')
  3. 计算模块接口的设计与实现过程。 设计包括代码如何组织,好比会有几个类,几个函数,他们之间关系如何,关键函数是否须要画出流程图?说明你的算法的关键(没必要列出源代码),以及独到之处。(20')
  4. 计算模块接口部分的性能改进。 记录在改进计算模块性能上所花费的时间,描述你改进的思路,并展现一张性能分析图(由VS 2017/JProfiler的性能分析工具自动生成),并展现你程序中消耗最大的函数。(3')
  5. 计算模块部分单元测试展现。 展现出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路。并将单元测试获得的测试覆盖率截图,发表在博客中。(5')
  6. 计算模块部分异常处理说明。 在博客中详细介绍每种异常的设计目标。每种异常都要选择一个单元测试样例发布在博客中,并指明错误对应的场景。(4')
  7. 在你实现完程序以后,在附录提供的PSP表格记录下你在程序的各个模块上实际花费的时间。(2')

6、附录

1. Fork项目并建立文件夹

  • 打开连接,点击Fork按钮,将仓库 personal-project 拷贝到本身的同名仓库中,以下图所示:
  • 拷贝成功后,能够看到本身已经拥有了一个同名仓库
  • 在对应语言下建立以学号为名的文件夹,确保全部本地的改动都已 push 后,能够在本身的仓库中向源仓库(personal-project)发起Pull Request:
  • 点击Create pull request,提交请求,此后只需等待仓库主人经过审核后,你的代码就能够成功合并进源仓库(personal-project)
  • 如在发起 pull request 后代码发生新的变化,可重复发起 pull request ,助教将合并最新的修改到源仓库

2.PSP表格

PSP是卡耐基梅隆大学(CMU)的专家们针对软件工程师所提出的一套模型:Personal Software Process (PSP, 我的开发流程,或称个体软件过程)。

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划
· Estimate · 估计这个任务须要多少时间
Development 开发
· Analysis · 需求分析 (包括学习新技术)
· Design Spec · 生成设计文档
· Design Review · 设计复审
· Coding Standard · 代码规范 (为目前的开发制定合适的规范)
· Design · 具体设计
· Coding · 具体编码
· Code Review · 代码复审
· Test · 测试(自我测试,修改代码,提交修改)
Reporting 报告
· Test Repor · 测试报告
· Size Measurement · 计算工做量
· Postmortem & Process Improvement Plan · 过后总结, 并提出过程改进计划
合计

一个功能完备的程序不是一蹴而就的。经过将词频统计的需求划分为4个部分,可将一个大任务划分为可操做的小任务,同时最好按照任务难度或紧急程度指定各个任务的完成次序。所以,在动手开发以前,要先估计将在程序各模块开发所需耗费的时间,以及完成整个项目所需的时间,将这个[估计值]记录下来,写成PSP 的形式。
PSP的目的是:记录工程师如何实现需求的效率,和咱们使用项目管理工具(例如微软的Project Professional,或者禅道等)进行项目进度规划相似。
有关PSP的更多内容,请自行阅读邹欣老师的博客:现代软件工程讲义 2 工程师的能力评估和发展

3.Github

请阅读邹欣老师的博客:源代码管理,了解源代码管理的10个实践问题。
本次做业要求使用Github进行源代码管理,代码有进展即签入Github。签入记录不合理的项目会被助教抽查询问项目细节。
对代码签入的具体要求以下:根据需求划分功能后,每作完一个功能,编译成功后,应至少commit一次。本例中,至少应区分基本功能和扩展功能,即分别针对基本功能、扩展功能,编译成功后,总共至少应commit两次。具体的功能划分,请自行定义,并在撰写博客时体现出来,遵循本身对需求的功能划分来提交代码便可。
对Commit不是很熟悉的话,请阅读阮一峰的博客:Commit message 和 Change log 编写指南,了解更多细节。

4.单元测试

请根据本身以往积累的测试经验,在编码完成以后,提交产品以前,设计测试用例,并编写单元测试,对本身的项目进行测试。
首先,至少应采用白盒测试用例设计方法来设计测试用例,其余测试方法不限。其次,要设计至少10个测试用例,确保你的程序可以正确处理各类状况。最后,结合测试评估的要求,对本身的测试设计进行评价,这些测试用例能知足该程序测试的要求吗?
另外一个重要的措施是要把单元测试自动化,这样每一个人都能很容易地运行它,而且可使单元测试天天都运行。每一个人均可以随时在本身的机器上运行。团队通常是在每日构建中运行单元测试的,这样每一个单元测试的错误就能及时被发现并获得修改。
推荐阅读邹欣老师的博客:现代软件工程讲义 2 开发技术 - 单元测试 & 回归测试

相关文章
相关标签/搜索