欢迎来到雷振康的博客

寒假作业(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的使用吧,以前大部分都是用算法去拆字符串,这次用正则带来了很多遍历.

posted on 2021-03-05 21:18  sady哇哈哈  阅读(93)  评论(7编辑  收藏  举报

导航