寒假作业(2/2)
软工实践寒假作业(2/2)
这个作业属于哪个课程|2021春软件工程实践|S班
:---😐:---😐:---:
这个作业要求在哪里|软工实践寒假作业(2/2)
这个作业的目标|提高对阅读之法的理解、熟悉github以及相关工具的使用、编写文件相关程序以及单元测试和性能分析
其他参考文献|CSDN、百度、知乎
一、阅读构建之法并提问
1、就结对编程之中的同学们的杂曰有一些疑惑?
讲义中提到有一些同学认为:编程从来就是一个人的活动。学校里这么教的,我们一直以来也是这么做的。两个人本来可以去做两个模块,现在一个模块两个人写是不是一种浪费(这可是两份工资哦)?首先在我学习的课程中,其实是很多实践课是有合作的,但是其实很多人在划水,但是毕竟有时候组队是难以避免的事情,就如同讲义上说的有些公司是有要求结对编程了,在大学的结课编程期间,如果有一些同学划水,但是我们为了课程的成绩,不得不要完成更多的工作量.我在知乎中看到有人说,在公司的结对编程之中,有一些同事有拖延(其实也是划水),把一个本来能几个小时能写完的代码,拖延了好几天,但是我没有查到具体的解决方案,所以想请教一下老师遇到这种情况应该怎么办?
2、就团队合作不同成员的投入我有一些疑惑?
在讲义之中提到团队成员的不同付出,猪的贡献就是全身心的付出.正常一个优秀的团队是要全面优秀,猪和鸡和鹦鹉都有,但是它也提到了一群猪全身心投入看似不错,但无论多么努力,猪没法下蛋。可是我的疑惑就是如果一群猪,都是很努力,现在软件工程这个行业,在我学习的认知中,大部分的事情其实都是只要你付出,认真查资料,在各个方面其实都可以做好,为什么一群努力的人没办法成为一个好的团队呢?
3、关于用户体验以及用户需求和公司需求的疑惑?
讲义中有提到用户界面那一章节中有提到一个微软学术搜索,有一个叫西乔的同学给它的界面提出了优化改进方案,将submit按钮突出,Cancel按钮样式弱化,降低用户丢失操作的可能性.前面还提到了让用户再次确认等等防止操作失误,但是我发现在我们生活中,比如我们卸载一个软件的时候,它经常弱化卸载软件,甚至多次确实,让我们在卸载的过程中造成了很大的麻烦.在用户的角度上我们肯定是希望卸载不要这么麻烦,一次次误导我们不去卸载,但是作为公司和开发人员的角度来说,肯定是希望用户不去卸载该软件,那当我们作为一个开发人员时,应该考虑用户的卸载体验,让他们不至于对该软件产生厌恶,还是考虑公司,诱导用户不去卸载呢?
4、关于PSP的问题?
在讲义中提到了一个软件工程师接到任务之后应该怎么办?说到了首先去PSP表,我认为PSP表里面的内容其实不是全然有用的,像是分析需求,设计文档这种东西,我认为是有用的,毕竟一个任务的开发首先要做好一个充足的准备,但是比如估算开发时间,特别是对于那种较大的项目,作为一个软件工程师,其实很容易在一个bug地方卡很久的,去估算这样的开发时间在我看来其实是意义不大的.
5、关于代码复审的问题?
就如果我们的代码由其他同事来复审,因为有些人的算法会比较特别,不想让人知道,或者说被别人复审会不会产生代码泄露的问题,然后最后背锅的是自己呢?
二、WordCount编程
1、Github项目地址
2、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
• Estimate | • 估计这个任务需要多少时间 | 530 | |
Development | 开发 | ||
• Analysis | • 需求分析 (包括学习新技术) | 100 | 180 |
• Design Spec | • 生成设计文档 | 20 | 30 |
• Design Review | • 设计复审 | 30 | 30 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 40 | 20 |
• Design | • 具体设计 | 40 | 40 |
• Coding | • 具体编码 | 200 | 300 |
• Code Review | • 代码复审 | 30 | 60 |
• Test | • 测试(自我测试,修改代码,提交修改 | 20 | 30 |
Reporting | 报告 | ||
• Test Repor | • 测试报告 | 25 | 30 |
• Size Measurement | • 计算工作量 | 10 | 15 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 15 | 30 |
• Size Measurement | 合计 | 530 | 765 |
3、解题思路描述
- 首先拿到题目的时候,我看到了需要统计单词数频率的前十,我就想到了java的Map,所以我就选择了使用java来编写这次的作业.
- 第一个要求是计算字符数,刚开始的思考就是把文件中读出来,一行一行读,再存入字符串来,由于换行是\n\r,每次换行就加2就行,再把\t用空格来替换直接计算长度就可以
- 第二个要求是计算有多少单词数,我的第一想法就是使用正则,也是一行一行读,先将单词利用正则分割,再利用正则判断是否为单词即可.
- 第三个要求是统计有效行数,也是一行一行读出来,然后利用正则来判断是否为非空白行
- 第四个要求就是统计频率前十的单词,首先我们在做第二个要求的时候已经写好了分割单词的代码,我又把所有单词转换成小写,再循环存入map之中,单词为key,单词数为value,如果单词已经存在的话,value+1,不存在的话就存入.最后用map的排序算法就行.
4、代码规范链接
5、计算模块接口的设计与实现过程
- 首先我写了两个类,一个类wordCount是主函数,用于编译运行,另一个类是Lib类,该类接受两个文件参数,可以用来对文件的处理.
- CalCharCount()用于计算多少字符数,用FileReader来打开文件,用BufferdReader来读取文件字符流.
while ((str = bufferedReader.readLine()) != null) {
s=str;
arrayList.add(str);
str = str.replaceAll("\t"," ");
count+=str.length();
count+=2;
}
if (!s.equals("")){
count-=2;
}
- CalWordCount()函数用来计算,首先我是将一行一行的字符串读取,利用正则分割单词,再判断该单词是否为一个正确的单词.
//CalWordCount函数
while ((str = bufferedReader.readLine()) != null) {
arrayList.add(str);
String[] parts = str.split("\\W");
for (int i = 0;i<parts.length;i++){
if (ifTrueWold(parts[i])){
count++;
}
}
}
- 关键函数ifTrueWold(String wold),[a-zA-Z]{4,}用于判定单词开头要有四个字母,([a-zA-Z0-9])*用于匹配四个字母之后的任意数字和字母.
String regex = "^[a-zA-Z]{4,}([a-zA-Z0-9])*";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(wold);
if (matcher.find()){
return true;
}
return false;
- CalMaxWord函数用于将所有单词存入map之中并且排序
Collections.sort(arrayList1, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> stringIntegerEntry, Map.Entry<String, Integer> t1) {
int result=t1.getValue().compareTo(stringIntegerEntry.getValue());
if (result!=0){
return result;
}
else {
return stringIntegerEntry.getKey().compareTo(t1.getKey());
}
}
});
- CalRows函数用于计算非空白行
for(String str : strArrayTrue) {
String regex = "[^\\s]+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
if (matcher.find()){
count++;
}
}
- PrintfFile函数用于将结果输入到文件当中
File fout = new File(outputFileName);
FileOutputStream fos = new FileOutputStream(fout);
OutputStreamWriter osw = new OutputStreamWriter(fos);
6、计算模块接口部分的性能改进
之前在统计字符频率的时候,我一开始是只用了sort算法去给map的value排序,排序完再手动排序map的key的字典序,后面改进为直接用compare对value和key同时排序
Collections.sort(arrayList1, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> stringIntegerEntry, Map.Entry<String, Integer> t1) {
int result=t1.getValue().compareTo(stringIntegerEntry.getValue());
if (result!=0){
return result;
}
else {
return stringIntegerEntry.getKey().compareTo(t1.getKey());
}
}
});
还有一个就是我之前从文件中读取字符串的时候我是先读出来放到ArrayList之中,然后全部取出之后再用toArray方法转换成字符串数组,这样的时间复杂度多了一倍,改进了之后会快一点.
7、计算模块部分单元测试展示
8、计算模块部分异常处理说明
文件的异常处理
try {
FileReader fileReader = new FileReader(inputFileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
} catch (IOException e) {
e.printStackTrace();
}
三、心路历程与收获
- 首先是这次我觉得难度对我最大的就是使用git,花了我不少的时间,所以说最大的收获应该就是使用git了,这也是我们以后工作所必须的东西.然后这次还有一个比较麻烦的事情就是关于编码,换行符的\n\r,也让我学习到了windows的一些编码方式.
- 然后其实我以前没有用过命令行的输入输出,这次一开始海没有注意到,直接用的普通的输入输出,以前都是用编译器自动帮我编译运行,这次也学到了手动编译代码.
- 以前其实写代码都有一个比较不好的习惯就是不喜欢在=号前后加空格,但是这次有强制自己要记得在=之类的前后加空格,以及一些其他的好的代码规范,强迫一下还是很有帮助的.
- 关于这次的具体代码,文件的输入输出其实以前都写过,主要的收获还是对于正则和map的使用吧,以前大部分都是用算法去拆字符串,这次用正则带来了很多遍历.