这个作业属于哪个课程 | <2021软件工程实践> |
---|---|
这个作业要求在哪里 | <软工实践寒假作业(2/2)> |
这个作业的目标 | 学会使用git、gthub,学习《构建之法》有所感悟 |
其他参考文献 | 《构建之法》《廖雪峰的git教程》 |
作业描述
- 任务一:阅读《构建之法》并提问
前一次作业要求不够详细,部分同学阅读《构建之法》提出的问题过于浅显,没有对提出的问题进行深入思考,因此在本次作业中额外添加了重新阅读《构建之法》并提问这一任务,并布置了更详细的要求。 - 任务二:完成词频统计个人认任务
在大数据环境下,搜索引擎,电商系统,服务平台,社交软件等,都会根据用户的输入来判断最近搜索最多的词语,从而分析当前热点,优化自己的服务。首先当然是统计出哪些词语被搜索的频率最高啦,请设计一个程序,能够满足一些词频统计的需求。- 需求:
假设有一个软件每隔一小段时间会记录一次用户的搜索记录,记录为英文。
输入文件和输出文件以命令行参数传入。- 统计文件的字符数(
- 统计文件的单词总数
- 统计文件的有效行数
- 统计文件中各单词的出现次数,最终只输出频率最高的10个。
- 需求:
任务一:阅读构建之法并提问及附加题
阅读并提问
- 文中说列举了结对编程的好处,其中有“结对编程能够提供更好的设计质量和代码质量,两个人合作能有更强的解决文通的能力。”……后文又说“任何一段代码至少被两双眼睛看过,两个脑袋思考过。”
- 问题:大多数人的思维方式是不一样的,一个问题解决也有多个解决方法,两个人结对编程过程中自己在解决问题,同时也在看对方解决问题,思维在自己和对方的解题思路中不断跳跃,这样花费的时间不会更多吗?怎样才能找到适合结对编程的搭档呢?怎么和搭在合作中达到1+1>2的效果呢?关于如何结对编程有相关的理论方法吗?比如如何达到高效合作。
- 书中介绍了很多开发流程的方式比如:写了再改、瀑布模型、瀑布的各种变形等。
- 问题:一个刚组成的软件开发团队,彼此都还不是很了解,如何选择适合的开发流程呢?这几种开发方式有比较低风险的吗?如果在团队合作过程中,发现一开始的方式有问题,但内部的调动又会消耗大量的精力,这值得半途换开发流程模式吗?
- 文中写道“自己最喜欢的一个项目是微软学术搜索,尽管许多用户觉得它的UI不错,它仍有很多可以改进的地方,一个叫西乔的同学就给提出了下面的建议:建议采用不同的样式,将submit按钮突出,Cancel按钮样式弱化,降低用户丢失操作的可能性。”
- 问题:我联想到,如果存在这样希望降低用户损失(但不是很大的影响)更改界面,但是会使界面变得不美观的情况,应当如何选择?
- 文中说“光看用户的表面语言或者行动是不够的。我们还要找到用户语言行动背后的动机!”
- 问题:文中列举了好几个例子,可以看出,在这阶段也投入了大量的时间和精力,软件开发每一个阶段都很重要,我想到,那在实际项目中,整个团队在每个阶段的时间怎么分配才合理呢?哪个阶段的时间应该花最多的时间和精力。
- 文中说现代软件工程,其实还是人的问题,其中说到“林子大了,什么鸟都有,作为万物之灵的人类,是不能满足于仅仅只有三种花样的。很快,我们可以看到第四,第五类人的出现”。
- 问题:团队里出现‘不做事’、‘不让别人做事’等之类的人,应该怎么办呢,是耐心的沟通交流,还是粗暴的踢出。
附加题
Therac-25事件(来源网络):
Therac-25是一台于1985年制造的放疗设备,一台用来给癌症病人做放射性治疗的设备。由加拿大原子能公司(AECL)制造。它核心的软件程序是用来控制放疗的辐射量。 这台机器的投入使用的短短18个月内,因为软件的重大bug,造成了4人死亡,2人重伤,震惊了软件界。迫使软件工程进行巨大的改进,制定了软件测试标准。
任务二:词频统计个人作业
Github地址
PSP表格
PSP2.1 | PersonalSoftware Process Stages | 预估耗时 | 实际耗时 |
---|---|---|---|
Planning | 计划 | ||
• Estimate | • 估计这个任务需要多少时间 | 10min | 10min |
Development | 开发 | ||
• Analysis | • 需求分析(包括学习新技术) | 24h | 24h |
• Design Spec | • 生成设计文档 | 120min | 60min |
• Design Review | • 设计复审 | 60min | 40min |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 30min | 40min |
• Design | • 具体设计 | 30min | 20min |
• Coding | • 具体编码 | 240min | 300min |
• Code Review | • 代码复审 | 60min | 60min |
• Test | • 测试(自我测试,修改代码,提交修改) | 60min | 120min |
Reporting | 报告 | 120min | 100min |
• Test Repor | • 测试报告 | 30min | 20min |
• Size Measurement | • 计算工作量 | 10min | 5min |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 60min | 90min |
合计 | 37.8h | 38.4h |
解题思路描述
- 首先学了作业博客中提供的廖雪峰的git教程,学习了git的使用,也看了些git和GitHub的介绍,了解了git和GitHub的作用
- 然后粗略的复习了java知识,就开始编程了,后来发现了这样做的缺点,没有根据最优方法解题
- 首先将功能分成四大块:
- 统计字符数
- 统计单词数
- 统计单词频数
- 统计行数
- 每个大功能封装为一个方法,后实现命令行运行程序和写入文件
- 认真看了邹欣老师的博客,学习《构建之法》,阅读并思考后提出了5个问题
代码规范定制链接
设计与实现过程
- 主要功能分别封装在四个方法中
-
CharCount (BufferedReader bufferedReader)实现文件中字符统计
不考虑中文,只统计ASCII码,空格和水平制表符换行符都算字符,通过判断符号的ASCII码值来统计,方法返回有多少个字符。while ((ch=bufferedReader.read()) != -1){ if (ch <= 127 && ch >= 0){ num++; } }
-
WordsCount(BufferedReader bufferedReader)方法实现统计文件单词数
先将单词分解出来:if(ch>='a'&&ch<='z' || ch>='0'&&ch<='9' || ch>='A'&&ch<='Z'){ str += ch; }
然后判断单词是否合法,通过IsWord方法判断,合法则计数
if(str != null && IsWord(str)) { num++; }
-
FileLines(BufferedReader bufferedReader)方法实现文件行数统计
只统计有单词或字母数字的行数,若是空白行则不统计while ((line = bufferedReader.readLine()) != null) { String temp = line.replaceAll("\\s*",""); if (line.length() != 0) { rows++; } }
-
WordsNum(BufferedReader bufferedReader,int n)方法实现单词频数统计
统计文件中各个单词的出现次数,最终只输出频率最高的10个,频率相同的单词,优先输出字典序考前的单词,这个函数核心代码如下:if (!IfSame(words , temp , counts) && j<words.length) { words[j] = str; counts[j]++; j++; }
涉及方法及关系如下(在一些方法下还有一些小方法未在此体现出):
-
同时有IsWord()方法判断单词是否合法;IfSame()方法判断是否有相同的单词;WordChange()方法将单词全部转换成小写;SortWords()方法根据单词出现频数排序;
-
性能改进
- 使用BufferReader作为输入
- 计划使用map,应该会提高性能
单元测试
- 主要测试Lib.java中的方法,WordCount.java中只有main方法,其中是其他方法的使用。部分单元测试代码:
@Test
public void sortWords() {
String[] words = {"hello","he"};
int[] counts = {1,1};
Lib lib = new Lib();
lib.SortWords(words,counts);
String[] word = lib.GetWords();
String[] rightWords = {"he","hello"};
for (int i=0; i<2; i++) {
assertEquals(rightWords[i],word[i]);
}
}
@Test
public void ifSame() {
String[] words = {"hello"};
int[] counts = {0};
assertEquals(true,new Lib().IfSame(words,"hello",counts));
}
测试结果:
覆盖率:
- 测试用例及结果:
- 空文件情况:
- 少量单词:
- 十个以上单词:
- 大量数据:
- 空文件情况:
异常处理说明
- 对BufferReader操作或写文件等操作会产生异常的,用try-catch捕获:
try{
//代码块
} catch (Exception e) {
//处理
}
心路历程与收获
- 刚开始看这个作业的要求时,除了任务一之外明白了,其他的大半作业要求都觉得看不懂。内心开始有点抵触。
- 后来认认真真研究了作业要求,才理解要怎么做。脑子里大概总结了一下这次作业的步骤,然后开始动手。之前一直用的eclipse,这次换了idea,才开始用也研究了一下idea。
- 看了很多教程,包括作业中提供的和自己找的,勉勉强强学会了git和GitHub的使用,现在还不熟练,开始学这个的时候感觉模模糊糊的,看了很久才有了大致的概念。
- 由于之前代码基础较弱,写代码前也只是构思了代码的大概框架,导致没有写出优质的代码,只是实现了作业要求的功能,并且绕了很多弯路,深刻认识到平时的积累很重要。
- 后来写博客的时候整理了一下自己的代码思路,发现比一边写代码一边想下一步该怎么写简单很多,而且比较严谨不会出错。以后一定要多多写代码提升自己的能力。
- 写代码过程中遇到很多bug,改代码的过程很自闭,一直在反思自己的代码能力为什么这么弱。之前一直在做与代码关系不大的事情,意识到在学习其他东西的时候也要学习好自己的专业知识,拥有牢靠的专业基础知识。
- 总结的时候觉得自己收获良多,学会了git和GitHub的使用,也认识到了自己的很多不足之处,心态也改变了很多。