2021春软件工程实践|S班 (福州大学)

  1. 班级首页
  2. 作业列表
  3. 详情

软工实践寒假作业(2/2)


Q&A:【腾讯文档】第二次寒假作业


为了不遗漏作业内容,这里有一份checklist方便同学们快速检阅。应该注意的是,checklist虽然有顺序,你在完成时可以并列进行;例如,可以在重新阅读《构建之法》之间穿插git的学习。

  • [ ] 详细阅读作业要求
  • [ ] 任务一:阅读《构建之法》并提问
    • [ ] 阅读教材
    • [ ] 参考作业要求以及关于如何提问的链接,提出你仍然不懂的5到10个问题
    • [ ] 时间充裕则完成附加题
  • [ ] 任务二:完成词频统计个人作业
    • [ ] 学习使用git以及github
    • [ ] 记录PSP表格
    • [ ] 制定自己的代码规范
    • [ ] Fork项目到自己的仓库
    • [ ] 分多次commit代码,完成项目
    • [ ] 代码性能分析改进
    • [ ] 学习并进行单元测试
    • [ ] 发起Pull Request
  • [ ] 撰写博客
    • [ ] 包含作业描述和目录
    • [ ] 核对评分标准

任务一

前一次作业要求不够详细,部分同学阅读《构建之法》提出的问题过于浅显,没有对提出的问题进行深入思考,因此在本次作业中额外添加了重新阅读《构建之法》并提问这一任务,并布置了更详细的要求。

一、基本要求

一、快速看完整部教材(教材开学会发,可以先看邹欣老师的博客园讲义),列出你仍然不懂的5到10个问题,发布在你的个人博客上。如何提出有价值的问题? 请看这个文章,以及在互联网时代如何提问题。 还有这些要点:

  1. 在每个问题后面,请说明哪一章节的什么内容引起了你的提问,提供一些上下文。
  2. 列出一些事例或资料,支持你的提问 。
  3. 说说你提问题的原因,你说因为自己的假设和书中的不同而提问,还是不懂书中的术语,还是对推理过程有疑问,还是书中的描述和你的经验(直接经验或间接经验)矛盾?
    一个模板可以是这样:

    我看了这一段文字(引用文字),有这个问题(提出问题)。我查了资料,有这些说法(引用说法),根据我的实践,我得到这些经验(描述自己的经验)。 但是我还是不太懂,我的困惑是(说明困惑)。
    【或者】我反对作者的观点(提出作者的观点,自己的观点,以及理由)。

大学生应该能写出自己的思考, 而不是摘抄书本内容。
提示: 编程经验不多的同学,建议看16章“创新”,提出自己的问题。

二、附加题

大家知道了软件和软件工程的起源,请问软件工程发展的过程中有什么你觉得有趣的冷知识和故事?

冷知识和故事的例子:

在 Dijkstra 决定成为一个程序员后,他尽快完成了学业,因为以他的话说,他在大学里不再受欢迎了:物理学家们觉得他是逃兵,而数学家们也看不起他和他做的事,因为在当时的数学文化里,你的课题必须和 ∞ 有关才会受尊重。那个时候程序设计没有成为一个职业,没有人能说出这个行业的基础知识体系是什么,而这些都会被 Dijkstra 改变。1957 年,他结婚的时候在申请的职业一栏写上了「程序员」,结果被政府拒绝,因为当时荷兰没有这个职业。
http://www.techug.com/post/edsger-wybe-dijkstra.html

三、自我小结

在本次课程结束后回顾,你对你提出的问题是否有了新的理解?在实践的过程当中,你用到了哪些知识?(本次作业不要求回答,等课程后期会有一次关于提问回顾的作业)

四、评分标准

  • 提问30分

    1. 问题重述【2'】:要求具体指出哪一章节的什么内容引起了你的提问,提供一些上下文。
    2. 资料或事例【4'】:列出一些事例或资料,支持你的提问 。
    3. 提问原因【8'】:说说你提问题的原因,你说因为自己的假设和书中的不同而提问,还是不懂书中的术语,还是对推理过程有疑问,还是书中的描述和你的经验(直接经验或间接经验)矛盾?
    4. 问题质量【8'】:最好是结合自身经历,结合相关知识,充分阅读他人观点后,对于某些内容提出自己的疑问。尽量不要提一些简单浅显或者网上已有相关回答的问题,如果所提问题已被前人充分讨论,请根据前人的回答总结出自己的答案。
    5. 自问自答【8'】:不能仅仅提出问题,还需给出自己对于问题的见解。要求给出自己的思考,而不仅仅是摘抄书本内容。
  • 附加题5分

    1. 资料引用:应当适当引用资料,不能全部复制网络上的回答。
    2. 个人见解:回答要有自己的理解,并谈谈你对故事的认识。
    3. 不笼统,有意义,符合真实情况

任务二

在大数据环境下,搜索引擎,电商系统,服务平台,社交软件等,都会根据用户的输入来判断最近搜索最多的词语,从而分析当前热点,优化自己的服务。首先当然是统计出哪些词语被搜索的频率最高啦,请设计一个程序,能够满足一些词频统计的需求。

〇、前置要求

1、github初使用

为了保证你的代码能够帮助更多的人,并且能得到有效的管理和开源共享,请先学习git以及github的使用:

  1. 注册github账号,在博客中提供github链接
  2. 下载Git和Github Desktop
  3. 学习基础Git命令、Github Desktop使用,参考 [附录2 Git以及Github]
  4. 本次作业提交采用github,首先fork项目示例结构到自己的仓库,完成基本需求,并至少进行10次以上的commit修改,并将最终程序以pull request的方式提交到主仓库

    代码有进展即签入Github。签入记录不合理的项目会被助教抽查询问项目细节。对代码签入的具体要求如下:根据需求划分功能后,每做完一个功能,编译成功后,应至少commit一次。具体的功能划分,请自行定义,并在撰写博客时体现出来,遵循自己对需求的功能划分来提交代码即可。

  5. 对于非仓库要求的代码,如编译器生成的项目文件、输出文件、class、jar包、exe等,应该使用.gitignore进行忽略,并确保不会提交到github上,参考[附录3]

2、代码规范制定

为了其他同仁可以轻松的阅读你的代码,请制定属于你的代码规范,要求不能偏离主流代码规范:

请参照《码出高效_阿里巴巴Java开发手册》/《腾讯c++代码规范》/《Python PEP8》,从以下几个角度制定你的编程规范,并撰写成markdown文件,添加到git仓库里。请牢记你制定的编码规范,并在此次作业中严格执行。

  • 缩进
  • 变量命名
  • 每行最多字符数
  • 函数最大行数
  • 函数、类命名
  • 常量
  • 空行规则
  • 注释规则
  • 操作符前后空格
  • 其他规则

一、编码要求

  1. 根据你选择的编程语言,选择Fork下面两个项目中的一个到自己的仓库,然后在根目录中新建一个学号为名的文件夹。

    https://github.com/kofyou/PersonalProject-C
    https://github.com/kofyou/PersonalProject-Java

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

二、博客撰写要求

  1. 给出作业描述和目录
  2. 在文章开头给出Github项目地址
  3. 在开始实现程序之前,在下述PSP表格记录下你估计将在程序的各个模块的开发上耗费的时间。
  4. 解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的过程。
  5. 给出你的代码规范的链接,即你的仓库中的codestyle.md
  6. 计算模块接口的设计与实现过程。 设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?说明你的算法的关键(展示出项目关键代码),并解释思路,以及独到之处。
  7. 计算模块接口部分的性能改进。 展示出项目性能测试截图并描述;记录在改进计算模块性能上所花费的时间,描述你改进的思路。
  8. 计算模块部分单元测试展示。 展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路。并将单元测试得到的测试覆盖率截图,发表在博客中;如何优化覆盖率?
  9. 计算模块部分异常处理说明。 在博客中详细介绍每种异常的设计目标。每种异常都要选择一个单元测试样例发布在博客中,并指明错误对应的场景。
  10. 在你实现完程序之后,在附录提供的PSP表格记录下你在程序的各个模块上实际花费的时间。
  11. 结合在构建之法中学习到的相关内容,撰写解决项目的心路历程与收获

三、需求

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

1、实现基本需求

假设有一个软件每隔一小段时间会记录一次用户的搜索记录,记录为英文。

输入文件和输出文件以命令行参数传入。例如我们在命令行窗口(cmd)中输入:

//C语言类
WordCount.exe input.txt output.txt

//Java语言
java WordCount input.txt output.txt

则会统计input.txt中的以下几个指标

  1. 统计文件的字符数(对应输出第一行)

    • 只需要统计Ascii码,汉字不需考虑
    • 空格,水平制表符,换行符,均字符
  2. 统计文件的单词总数(对应输出第二行),单词:至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写

    • 英文字母: A-Z,a-z
    • 字母数字符号:A-Z, a-z,0-9
    • 分割符:空格,非字母数字符号
    • :file123是一个单词, 123file不是一个单词。file,File和FILE是同一个单词
  3. 统计文件的有效行数(对应输出第三行):任何包含非空白字符的行,都需要统计。

  4. 统计文件中各单词的出现次数(对应输出接下来10行),最终只输出频率最高的10个。

    • 频率相同的单词,优先输出字典序靠前的单词。

      例如,windows95,windows98和windows2000同时出现时,则先输出windows2000

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

然后将统计结果输出到output.txt,输出的格式如下;其中word1word2 对应具体的单词,number为统计出的个数;换行使用'\n',编码统一使用UTF-8。

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

2、接口封装

如果现在我们要把这个功能放到不同的环境中去(例如,命令行,Windows图形界面程序,网页程序,手机App),就会碰到困难:代码散落在各个函数中,很难剥离出来作为一个独立的模块运行以满足不同的需求。

这些代码的种类不同,混杂在一起对于后期的维护扩展很不友好,所以它们的组织结构就需要精心的整理和优化。

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

  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);

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

3、单元测试和性能分析

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

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

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

四、测试须知

1.组织目录

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

Java

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

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

C++

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

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

2.错误处理

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

3.文件读写

本次作业涉及文件路径、文件读写等的问题,请自行查阅资料学习。文件路径既可以使用绝对路径,也可以使用相对路径。

在执行程序时,通过读入命令行指定的测试文件路径,在程序中给文件路径赋值。总之请确保你的程序可以在助教的电脑上运行,例如请不要在程序中使用你自己电脑上的绝对路径通过硬编码的方式给文件路径变量赋值。

五、评分规则

由于任务二占70分,实际评分规则有100分,最终记分按70%折算。

1.博客评分规则(45‘)

  1. 在文章开头给出Github项目地址。(1')
  2. 在开始实现程序之前,在下述PSP表格记录下你估计将在程序的各个模块的开发上耗费的时间。(2')
  3. 解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的过程(3')。
  4. 给出你的代码规范的链接,即你的仓库中的codestyle.md
  5. 计算模块接口的设计与实现过程。 设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?说明你的算法的关键(展示出项目关键代码),并解释思路,以及独到之处。(20')
  6. 计算模块接口部分的性能改进。 展示出项目性能测试截图并描述;记录在改进计算模块性能上所花费的时间,描述你改进的思路。(3')
  7. 计算模块部分单元测试展示。 展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路。并将单元测试得到的测试覆盖率截图,发表在博客中;如何优化覆盖率?(5')
  8. 计算模块部分异常处理说明。 在博客中详细介绍每种异常的设计目标。每种异常都要选择一个单元测试样例发布在博客中,并指明错误对应的场景。(4')
  9. 在你实现完程序之后,在附录提供的PSP表格记录下你在程序的各个模块上实际花费的时间。(2')
  10. 结合在构建之法中学习到的相关内容,撰写解决项目的心路历程与收获。(5')

2.程序评分规则(40')

  • 正确性(30')
  • 性能(10')
  • 当程序的正确性评分大于25分时才可以参与性能评分环节,所以请各位同学务必保证自己程序的正确性。
  • 性能评分将采取档级评分制度,助教将根据同学们的程序跑同一数据耗费的时间长度将程序分为若干档,每一档的同学得到的分数为 10/档级数

3.代码规范评分规则(15')

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

六、附录

1.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.Git以及Github

git是版本控制系统,而github提供托管git仓库的服务。或许你可以先在各大视频网站找一些git&github介绍,对此有一个总体上的了解,再深入进行学习。

git

  1. 可以阅读邹欣老师的博客:源代码管理,了解源代码管理的10个实践问题。
  2. 廖雪峰的git教程
  3. 关于commit message的编写:可以阅读阮一峰的博客:Commit message 和 Change log 编写指南,了解更多细节。

github

  1. github简单教程
  2. .gitignore配置语法完全版
  3. gitDesktop、多人协作教程

本次作业将使用到的fork/commit/pull request:

  1. github fork 与pull request
  2. github中fork分支和pullrequest的最佳实践
  3. GitHub Pull Request入门

3.gitignore

.gitignore配置语法完全版

七、格式&规则

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

务必包含以下大标题:(标题含义近似即可,你可以个性化自己的标题)

  • part1:阅读《构建之法》并提问
  • part2:WordCount编程
    • Github项目地址
    • PSP表格
    • 解题思路描述
    • 代码规范制定链接
    • 设计与实现过程
    • 性能改进
    • 单元测试
    • 异常处理说明
    • 心路历程与收获

2、为了方便其他学校的老师或者助教了解课程实况,请大家在作业开头添加格式描述:(必做)

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

markdown代码

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

3、提交规则

  • 在deadline前交,得实际得分 * 100%;
  • 补交:在deadline 后两天内提交视为补交,得实际得分 * 50%;
  • 缺交:在deadline 之后两天未补交视为博客缺交,分数为0分;
  • 作业抄袭:当助教发现两篇博客文字/图片/代码过于相似时,判定两篇博客都为抄袭,分数都为-100%(注意是倒扣!);
  • 伪造提交:虽然作业博客没有完成,但是先提交到作业占位置,判定为伪造提交,分数得0分;

(忘记提交作业和补交扣分一致)

4、注意事项

  • 微信班级群如果发布相关通知也是作业要求一部分,请及时查看群通知;
  • 若需要在微信群填写相关信息,未能在deadline之前完成填写的,扣实际得分的50%;
  • 如对作业存在疑问,请在deadline之前三天在班级群提出;
  • 若助教对作业要求有修改,会在群内公告,请务必查看并按新的要求完善作业;
  • 请及时回复老师或助教的点评并作出相应修改
  • 要求同学们分10次签入自己的代码,每次写文档描述自己这次签入实现了什么功能。每次嵌入都要有足够多的新代码,不能一次签入绝大多数代码,其他的嵌入只是小修改。 独立的两个人最后的代码可能类似,但每次签入不可能雷同!

4、疑惑解疑

若有对题意不清或者有不理解的地方,可在该博客下方留言,或者在微信群中直接提问。


提交: 0 人,未提交: 74 人
未提交名单: 陈修庆    梁扬新    硅硅键    星夜的风    HannahShaw    wuhan18    AgCl9    Starlite    dqcx    mybky2021    MEating    散落de回忆    邹洋艺    121黄炜    谢语涵    郑麟轩    fujiangfer    头壳康康    福贵的老牛    我的叶绿体    t0p1Crayon    羊羊羽    戊子年    YellowBean    H2J_黄志杰    gz丶    心动`    明月何时有    谷雨yu    _Hans    nafup    Gaoann    阮宫筱白    Chutiiing    昵称就为空    Caighter    hjqColbert    LittleShy    宋大帅    郑开心    _ChangLee    一只离离离    linhuaiying    li666    221801222郑茂基    本多猪四郎    蒲公英吹啊吹    丫比是丫比    Rr2    coding曼巴    Srr    entsjtsmf    spiritcsk    ccreater    kksnz    小思理    221801233陈鹏桢    zzong    猫滴舞步    sady哇哈哈    肥浩啊    Weirdo*    硅与神经键    -ways-    風迹    骑着摩托车的小螃蟹    黄伟为    夜空晨    137-扎亚巴根    0lll    boynextdoor♂    Tarsss    可爱的小美酱    S灬J