软件工程实践第二次作业---文件读取

助教-陈俊琦 助教 2023-02-18 22:42:28

恭喜你已经完成了软工实践的第一次作业,并将逐步迈进到第二次作业的能力提升中。本次作业将聚焦于澳大利亚网球公开赛的赛事项目,期待各位同学大展身手哦!
为了不遗漏作业内容,这里有一份checklist方便你快速查阅

  • 在文章开头给出新建的Gitcode项目地址
  • 详细阅读作业要求
  • 完成代码编写并进行测试
  • 撰写博客
    • 描述解题思路
    • 设计实现过程
    • 关键代码展示
    • PSP表格
    • 核对作业评分标准
  • 在deadline之前,在社区中提交作业

0. 任务

完成对澳大利亚网球公开赛相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序

1. 编码要求

  1. 根据你选择的编程语言,从下面两个项目中Fork一个到自己的仓库,然后在根目录中新建一个学号为名的文件夹。
    https://gitcode.net/weixin_46376442/project-c
    https://gitcode.net/weixin_46376442/project-java
    
  2. 复制example下的目录结构到你新建的目录下;不要修改example文件夹和根目录下的README
  3. 语言支持:
    1. Java:Java8,推荐使用Java开发
    2. c/c++:gcc/g++ 6.3
    3. 换行使用'\n',编码统一使用UTF-8
  4. 在开始实现程序之前,在PSP表格[附录1]记录下你估计在程序开发各个步骤上耗费的时间,在你实现程序之后,在PSP表格记录下你在程序的各个模块上实际花费的时间。
  5. 使用GitCode[附录2]来管理源代码,代码有进展即签入GitCode,至少进行10次以上的commit修改。签入记录不合理的项目会被助教抽查询问项目细节。
  6. 请制定自己的代码规范并撰写成markdown文件,随代码一起上传至GitCode仓库中。可以参照《码出高效_阿里巴巴Java开发手册》/《腾讯c++代码规范》等主流代码规范来制定你自己的编程规范。编码要求项目代码的风格要符合你制定的代码规范。
  7. 除了目录组织说明提及的文件,其它自己产生的文件都应该在.gitignore忽略,如编译器生成的项目文件、输出文件、class、jar包、exe等,确保不会提交到GitCode上,参考 [附录3]。
  8. 进行性能分析和改进
  9. 使用单元测试对项目进行测试,并使用插件查看测试分支覆盖率等指标;并写出至少10个测试用例确保你的程序能够正确处理各种情况。
  10. 在完成项目后,deadline之前,请正确发起一个Pull Requet [附录2],并确保自己的代码最终成功签入。(如果成功签入会在原始项目主页看到自己学号为名的文件夹)

2. 博客撰写要求

  1. 在文章开头给出Gitcode项目地址
  2. 给出PSP表格
  3. 解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的过程。
  4. 设计与实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?说明你的算法的关键(展示出项目关键代码),并解释思路,以及独到之处。
  5. 程序性能改进。记录在改进程序性能上所花费的时间,描述你改进的思路。
  6. 单元测试展示。展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路。将单元测试得到的测试覆盖率截图,发表在博客中;描述应该如何优化覆盖率?
  7. 结合在构建之法中学习到的相关内容,撰写解决项目的心路历程与收获

3. 需求

实现一个命令行程序,不妨称之为AOSearch
本次作业所需数据均爬取自澳大利亚网球公开赛官网【该爬取行为仅用于课程教学】

3.1 实现基本功能

假设有一个软件可以输出2023年澳大利亚网球公开赛的选手信息和比赛结果。
输入指令和输出文件以命令行参数传入。例如我们在命令行窗口(cmd)中输入:

//C语言类
AOSearch.exe input.txt output.txt
 
//Java语言
Java -jar AOSearch.jar input.txt output.txt

功能1:输出所有选手信息

当input.txt的内容为

players

则会输出参与澳洲网球公开赛的所有选手信息output.txt,输出格式如下:其中full_name对应选手全名,gender为选手性别, nationality为国籍。换行使用'\n',编码统一使用UTF-8。

输出格式:

full_name:string
gender:string
nationality:string 
-----
...

输出样例:

full_name:Radu Albot
gender:male
nationality:Moldova 
-----
full_name:Marcelo Arevalo
gender:male
nationality:El Salvador
-----
...

功能2:输出正式赛每日结果

当input.txt的内容为

result 0116

则会输出1月16日的所有比赛结果到output.txt,输出格式如下; 其中time对应比赛实际开始时间,winner为比赛胜利者姓名缩写,如为团体比赛请列出获胜团体所有成员姓名缩写。格式如'menber1 & menber2'score表示比赛中每一轮双方的比分,每一轮的格式如'score1 | score2'

输出格式:

time:hh:mm
winner:string
score:string
-----
...

输出样例:

time:00:14
winner:C. Gauff
score:6:1 | 4:6
-----
time:04:13
winner:B. Krejcikova & K. Siniakova 1
score:6:4 | 6:3
-----
...

附加功能:输出资格赛结果
当input.txt的内容为

result Q1

则会输出澳大利亚网球公开赛第一赛季的所有比赛结果到output.txt,输出格式如下; 其中time对应比赛实际开始时间,winner为比赛胜利者姓名缩写,如为团体比赛请列出获胜团体所有成员姓名缩写。格式如'menber1 & menber2'score表示比赛中每一轮双方的比分,每一轮的格式如'score1 | score2'

输出格式:

time:hh:mm
winner:string
score:string
-----
...

输出样例:

time:00:14
winner:C. Gauff
score:6:1 | 4:6
-----
time:04:13
winner:B. Krejcikova & K. Siniakova 1
score:6:4 | 6:3
-----
...

补充说明:
对于input.txt,有可能会出现多行输入的样例,例如:

players
result 0116
result 0116
players

此时的输出文件output.txt中的内容为:

full_name:Radu Albot
gender:male
nationality:Moldova 
-----
full_name:Marcelo Arevalo
gender:male
nationality:El Salvador
-----
...
-----
time:00:14
winner:C. Gauff
score:6:1 | 4:6
-----
time:04:13
winner:B. Krejcikova & K. Siniakova 1
score:6:4 | 6:3
-----
...
-----
time:00:14
winner:C. Gauff
score:6:1 | 4:6
-----
time:04:13
winner:B. Krejcikova & K. Siniakova 1
score:6:4 | 6:3
-----
...
-----
full_name:Radu Albot
gender:male
nationality:Moldova 
-----
full_name:Marcelo Arevalo
gender:male
nationality:El Salvador
-----
...
-----

其中,每个指令的输出紧贴上一个指令的输出,无需空行
假如输入无法处理的指令,例如:

  1. 无法识别的指令,则输出Error
  2. result后的日期不符合以下要求,则输出N/A
    • 在澳大利亚网球公开赛期间 (1月16日-1月29日)
    • Q1、Q2、Q3、Q4中的一个

input.txt样例:

player
Players
result0116
result 1312
result sss
result 116
result 0130
result Q5
players

output.txt输出:

Error
-----
Error
-----
Error
-----
N/A
-----
N/A
-----
N/A
-----
N/A
-----
N/A
-----
full_name:Radu Albot
gender:male
nationality:Moldova 
-----
full_name:Marcelo Arevalo
gender:male
nationality:El Salvador
-----
...
-----

3.2 接口封装

如果现在我们要把这个功能放到不同的环境中去(例如,命令行,Windows图形界面程序,网页程序,手机App),就会碰到困难:代码散落在各个函数中,很难剥离出来作为一个独立的模块运行以满足不同的需求。
这些代码的种类不同,混杂在一起对于后期的维护扩展很不友好,所以它们的组织结构就需要精心的整理和优化。

我们希望把基本功能里的:

  1. 输出所有选手信息
  2. 输出每日比赛结果

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

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

把计算核心在单元测试框架中做过完备的测试后,我们就可以在算法层级保证了这个模块的正确性。
但我们知道软件并非只有计算核心,实际的软件是交付给最终用户的软件,除了计算核心外,还需要有一定的界面和必要的辅助功能。
这个Core模块和使用它的其他模块之间则要通过一定的API来交流。那么API应该怎么设计呢?

为了方便起见,我们可以从下面的最简单的接口开始(仅举例,你的代码里可能没有这个函数):

int countChar(File *file)

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

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

当然,这样的测试程序并不充分,希望大家测试时不要像这样偷懒。

3.3 单元测试和性能分析

请根据自己以往积累的测试经验,在编码完成之后,提交产品之前,设计测试用例,并编写单元测试,对自己的项目进行测试。
首先,至少应采用白盒测试用例设计方法来设计测试用例,其他测试方法不限。其次,要设计至少10个测试用例,确保你的程序能够正确处理各种情况。最后,结合测试评估的要求,对自己的测试设计进行评价,这些测试用例能满足该程序测试的要求吗?

另一个重要的措施是要把单元测试自动化,这样每个人都能很容易地运行它,并且可以使单元测试每天都运行。每个人都可以随时在自己的机器上运行。团队一般是在每日构建中运行单元测试的,这样每个单元测试的错误就能及时被发现并得到修改。

  • 请阅读邹欣老师的博客:单元测试和回归测试,编写程序的单元测试
  • c++可以使用vs2017。对于博客任务中的单元测试、性能分析(Studio Profiling Tools),vs2017有相应的功能。
  • java可以使用idea。也可以自行查找使用其他工具。

4. 测试须知

4.1 组织目录

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

4.2 Java

对于使用Java语言的项目有以下要求:

  1. 【以学号为名的文件夹中】的目录下必须有src文件夹
  2. 在src目录下必须有名为且AOSearch.java文件,且AOSearch.java中包含 public static void main(String[] args) 方法
  3. 请将Java代码打包成jar
  4. 除此之外的文件都不需要提交到Gitcode仓库;一个Java项目的示例组织目录如下所示:
xxxxxxxxx (文件夹名字为学号)
|- src
 |- AOSearch.java(主程序,可以从命令行接收参数;确保文件名一致、区分大小写)
 |- Lib.java(包含其它自定义函数,可以有多个,对名字不做要求)
 |- data(文件夹,存放程序的数据)
|- AOSearch.jar
|- README.md
 描述你的项目,包括如何运行、功能简介、作业链接、博客链接等
|- codestyle.md
 描述你之前定的代码风格

4.3 C++

对于使用C++ 语言的项目有以下要求:

  1. 【以学号为名的文件夹中】的目录下必须有src文件夹
  2. 在src目录下必须有名为AOSearch.cpp文件,且AOSearch.cpp的main函数可以接收命令行参数(如int main(int argv, char** argc)
  3. 请将代码编译为exe
  4. 除此之外的文件都不需要提交到Gitcode仓库;一个C++项目的示例组织目录如下所示:
xxxxxxxxx (文件夹名字为学号)
|- src
  |- AOSearch.cpp(主程序,可以从命令行接收参数;确保文件名一致、区分大小写)
  |- Lib.cpp(包含其它自定义函数,可以有多个,对名字不做要求)
  |- Lib.h(包含其它自定义函数,可以有多个,对名字不做要求)
  |- data(文件夹,存放程序的数据)
|- AOSearch.exe
|- README.md
  描述你的项目,包括如何运行、功能简介、作业链接、博客链接等
|- codestyle.md
  描述你之前定的代码风格

4.4 错误处理

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

5、评分规则

5.1 博客评分规则(50')

  1. 在文章开头给出你们的Gitcode项目地址。(2')【覆盖课程目标1】
  2. 在开始实现程序之前,在附录提供的PSP表格中记录下你估计将在程序的各个模块中耗费的时间。(3')【覆盖课程目标2】
  3. 记录模块接口的设计与实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?说明你的算法的关键(不必列出源代码),以及独到之处。(22')【覆盖课程目标2】
  4. 计算模块接口部分的性能改进。(8')【覆盖课程目标2】
  5. 计算模块部分单元测试展示。(8')【覆盖课程目标1】
  6. 计算模块部分异常处理说明。(4')【覆盖课程目标2】
  7. 在实现完程序后,在附录提供的PSP表格中记录下你在程序的各个模块中实际花费的时间。(3')【覆盖课程目标1】

5.2 程序评分规则(40')【覆盖课程目标3】

  1. 完成功能1(10')
  2. 完成功能2(15')
    • 能输出1月16日-1月22日的正式赛的赛程(10')
    • 能输出1月23日-1月29日的正式赛的赛程(5')
  3. 性能(10')
    当程序 (不包含附加功能) 的正确性评分大于等于25分时才可以参与性能评分环节,所以请各位同学务必保证自己程序的正确性。
    性能评分将采取档级评分制度,助教将根据同学们的程序跑同一数据耗费的时间长度将程序分为若干档,每一档的同学得到的分数为10/档级数
  4. 完成附加功能(5')

5.3 代码规范评分规则(10')【覆盖课程目标1】

  1. 囊括要求部分(2')
  2. 符合主流,制定合理,详细(3')
  3. 项目代码符合代码规范(5')

5.4 提交注意事项

  • 按时间完成并提交——正常评分
  • 晚交一周以内——0分
  • 晚交一周以上或不交——倒扣本次作业分数
  • 抄袭——倒扣2倍本次作业分数 【严禁代码与博客等一切形式的抄袭!】

5.5 疑惑解答

若有对题目不理解的地方,可在QQ群中直接提问。

6. 附录

1. PSP表格

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

PSPPersonal 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. Gitcode

请阅读邹欣老师的博客:源代码管理,了解源代码管理的10个实践问题。
本次作业要求使用GitCode进行源代码管理,代码有进展即签入GitCode。签入记录不合理的项目会被助教抽查询问项目细节。
对代码签入的具体要求如下:根据需求划分功能后,每做完一个功能,编译成功后,应至少commit一次。具体的功能划分,请自行定义,并在撰写博客时体现出来,遵循自己对需求的功能划分来提交代码即可。
如果对Gitcode的内容不熟悉,可以点击《git入门》进行学习

3. 单元测试

请根据自己以往积累的测试经验,在编码完成之后,提交产品之前,设计测试用例,并编写单元测试,对自己的项目进行测试。以下是对测试的几个具体要求
首先,至少应采用白盒测试用例设计方法来设计测试用例,其他测试方法不限;
其次,要设计至少10个测试用例,确保你的程序能够正确处理各种情况;
最后,结合测试评估的要求,对自己的测试设计进行评价,这些测试用例能满足该程序测试的要求吗?
另一个重要的措施是要让单元测试自动化,这样每个人都能很容易地运行它,随时在自己的机器上运行,并且可以使单元测试每天都运行。团队一般是在每日构建中运行单元测试的,这样每个单元测试的错误就能及时被发现并得到修改。
有关单元测试的更多内容,推荐阅读邹欣老师的博客:单元测试和回归测试

7. 格式与规则

7.1 为了方便其他学校的老师或者助教了解课程实况,请大家在作业开头添加作业的基本信息:(必做)

这个作业属于哪个课程<班级的链接>
这个作业要求在哪里<作业要求的链接>
这个作业的目标<写上具体方面>
其他参考文献...
  • markdown代码:
|这个作业属于哪个课程|<班级的链接>|
|--    |--    |
|这个作业要求在哪里|<作业要求的链接>|
|这个作业的目标|<写上具体方面>|
|其他参考文献|...    |

7.2 为了方便读者阅读以及助教评分,请大家在博客开头给出博文目录,作为内容的索引

  • 务必包含以下大标题: Gitcode项目地址、PSP表格、解题思路描述、接口设计和实现过程、关键代码展示、性能改进、单元测试、异常处理、心得体会(标题含义近似即可,你可以个性化自己的标题,如心路历程、性能测试)
  • 可以使用markdown的语法,根据标题设置自动生成目录:
[toc]
作业基本信息...
## Gitcode项目地址
## PSP表格
## 解题思路描述
### 问题1
### 问题2
...
## 接口设计和实现过程
...
## 关键代码展示
...
## 性能改进
...
## 单元测试
...
## 异常处理
...
## 心得体会
...
  • 也可以结合html生成目录
作业基本信息...
## 目录:
1. [Gitcode项目地址](#1)
2. [PSP表格](#2)
3. [解题思路描述](#3)
4. [接口设计和实现过程](#4)
5. [关键代码展示](#) 
6. [性能改进](#) 
7. [单元测试](#) 
8. [心得体会](#) 
## <span id="1">1. Gitcode项目地址</span>
### 问题1
### 问题2
### ...
## <span id="2">2. PSP表格</span>
...
## <span id="3">3. 解题思路描述</span>
...
## <span id="4">4. 接口设计和实现过程</span>
...
## <span id="5">5. 关键代码展示</span>
...
## <span id="6">6. 性能改进</span>
...
## <span id="7">7. 单元测试</span>
...
## <span id="8">8. 异常处理</span>
...
## <span id="9">9. 心得体会</span>
...
...全文
2831 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
0人已提交
完成率0%
暂无数据
回复
切换为时间正序
请发表友善的回复…
发表回复

587

社区成员

发帖
与我相关
我的任务
社区描述
软件工程-2022-23学年(第二学期)
软件工程 高校
社区管理员
  • LinQF39
  • chennuo.
  • 异梦1
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧