寒假作业2/2

这个作业属于哪个课程 2021春软件工程实践|W班(福州大学)
这个作业要求在哪里 寒假作业2/2
这个作业的目标 阅读构建之法并提问,完成词频统计个人作业
其他参考文献 CSDN

目录

Part1:阅读《构建之法》并提问

提问

1.在第一章“软件工程概论”开头就提到“有人抱怨学习数据结构与算法无用”.大部分大学生学习的目的,无非就是“考试要考、面试要考、增加竞赛经历”,很少能真正地去理解其内部性质、原理。

自己在开发的过程中,也有过这样的疑惑,自己是用的大部分类都可以通过库进行调用,自己也很少会去考虑内部实现,只要懂得怎么使用就可以了;它对不做算法工程师的人而言,是否处于相对不重要的地位呢?我在网上搜索资料得到的结论:如果要做深入的软件开发,数据结构是很重要的,它有利于了解API的层次结构,可以写出高效健壮的程序,从长远来看是很有好处的。但是我有一个疑问,他们都没说清楚数据结构到底应该掌握到哪种程度,所以想请教一下老师。

2.在第3章中,提到“分析麻痹”,但书中并没有提到如何解决“分析麻痹”。

我刚开始学习写代码的时候,也有这种感觉,总是想着在开始敲代码之前,先把可能会出现的问题想清楚,想好解决措施,再动手。但这样,过于追求完美,一旦程序没有按照自己的想法展开,就容易产生消极悲观的心理。我现在写程序也有一些“畏难情绪”,觉得需要学习新技术,学了又忘,导致没有积极性,那这部分问题该如何解决呢?

3.在“结对编程”中提到“什么样的人适合结对编程”,那是不是意味着结对编程就适用于那些人,比如保守内向的人就不适合结对编程,他们可能并不习惯被人盯着工作。在结对编程的过程中,两个人的思维方式都不相同,那有分歧的部分又该如何解决呢?如果是相互解释,那会不会浪费大量的时间?结对编程的同伴又该如何选取?我是觉得选择擅长方面不同的两人,这样就能各尽其长,互帮互助。但是现实中,可能别人都已经组好队,两个能力,领域差不多的人组到了一起,那该怎么办?

我认为,对于保守内向的人,更应该进行结对编程,这样更能提高团队的凝聚力;我查资料:结对编程需要磨合期,两个人意见方面有分歧是很正常的现象。那这个磨合期又是多久呢?过了这个磨合期,还是无法经常产生分歧,是不是就说明这两人不适合在一起结对编程呢?我还有一个疑问,结对编程开始角色互换,那会不会打乱原来两人的思路呢?这样会不会导致开发效率更低了?

4.在“设计和开发”章节中的“用户体验和质量”的讨论中,举了“GE公司”的例子,让我有所思考。用户体验和质量到底哪个更重要呢?

我赞同文中总裁的看法,在不要求太多精度的检查,应该将用户体验放在第一位。毕竟如果用户体验不好的话,用户也不想再一次尝试。但是在实际开发中,用户体验和产品质量又该如何权衡呢?这个部分是由程序员来决定吗?还是由其他人员决定?

5.在“IT行业的创新”一章中,提到“创新者甚至恨创新”让我觉得很迷惑,往下看才知,创新会损害某些人的利益,最终也损害了自身的利益。以前,中国基本是模仿国外的技术,缺少创新意识;现在,创新产品不断地在中国涌现。我记得,有的面试官在面试上会问“当一个新产品上市的时候,你能将他模仿出来吗”,我觉得这不应该是招聘的要求。那么在面试的时候,会将“创新纳入考虑范围吗”,“创新”本身就是一个很抽象的概念,只通过笔试面试能准确衡量一个人的创新水平吗?

我认为任何公司都不能停下创新的步伐,否则这家公司始终都是在原地踏步。创新应该纳入考虑范围,但我觉得仅仅通过笔试和面试得到的相关信息毕竟是有限的,那么入职之后公司是否可以以“缺乏创新”为由,辞职员工呢?如果当“创新”与“利益”发生冲突的时候,公司又该如何取舍呢?

附加题

404错误,想必大家都很熟悉了。是指用户浏览网页时,服务器因某种原因无法正常提供信息或无法回应所返回的页面,即「找不到该页面」,又被称为「互联网的最后一个页面」。

关于404说法的由来众说纷纭,其中有一种说法称,404源于「404房间」。

相传互联网的第一架服务器,架设在欧洲核研究组织的404号房。如果要打开网页,就得向404房的Berners-Lee提交申请,如果他没在房间内,就会出现「404 not found」。

参考链接

Part2:WordCount编程

GitHub

GitHub项目地址

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 20
• Estimate • 估计这个任务需要多少时间 10 20
Development 开发 420 525
• Analysis • 需求分析 (包括学习新技术) 20 30
• Design Spec • 生成设计文档 10 10
• Design Review • 设计复审 10 10
• Coding Standard • 代码规范 (为目前的开发制定合适的规范) 10 15
• Design • 具体设计 20 30
• Coding • 具体编码 300 360
• Code Review • 代码复审 20 20
• Test • 测试(自我测试,修改代码,提交修改) 30 50
Reporting 报告 60 70
• Test Repor • 测试报告 30 40
• Size Measurement • 计算工作量 10 10
• Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 20 20
合计 490 615

解题思路描述

需要运用java中的文件流来进行文件内容的读入和写出。
根据需求,需要实现以下几个功能:1.统计文件的字符数;2.统计文件的单词总数;3. 统计文件的有效行数; 4.统计文件中各单词的出现次数,最终只输出频率最高的10个。
具体实现:
Java中的缓冲流的性能要比非缓冲流的性能高;故使用BufferedReader和BufferedWriter分别进行文件的读写操作。
功能1:
  因为测试内容全是Ascii码,无需考虑汉字,故只需直接获取数据长度即可。
功能2:
  使用正则表达式进行单词判断、匹配。
功能3:
  使用正则表达式进行行数统计.判断空比判断非空更简单,一开始在想非空的条件,就卡了比较久
功能4:
  在实现功能1的过程中,对符合的“单词”使用map<String,Integer>来进行数量的统计(单词不区分大小写,所以统计之前需要对大写字母进行统一的小写转换);最后对map中的数据进行排序,选取前10个高频单词。排序需要用到List,将Map中的数据转移到List,重写List的compare(),

代码规范

codestyle.md

设计与实现过程

总共有两个类:
  Lib类:功能全都封装在这个类中。
  WordCount类:一个主函数,用于执行命令行程序。

使用缓冲流读取文件内容
设置一个变量储存文本内容,这样就不用多次读取内容

        StringBuilder fileBuilder = new StringBuilder();
        bufferedReader = new BufferedReader(new FileReader(readFileName));
        int c;
        while ((c=bufferedReader.read())!=-1)
        {
            fileBuilder.append((char)c);
        }
        return fileBuilder.toString();

直接通过length(),获取字符数

        charNum = fileContent.length();

使用正则表达式判断单词是否合法

        if (str.matches("[a-zA-Z]{4}[a-zA-Z0-9]*")){
            return true;
        } else{
            return false;
        }

正则表达式分割文本,对单词进行判断,合法则单词数+1并且加入到map中

 String[] contents = fileContent.split("[^a-zA-Z0-9]");
        for (String content:contents)
        {
            if (isWord(content)){
                wordNum++;
                String word = content.toLowerCase();
                Integer count = wordMap.get(word);
                if (count==null){
                    count = 1;
                } else {
                    count++;
                }
                wordMap.put(word,count);
            }
        }

正则表达式判断是否是空行

        charNum = fileContent.length(); 
        if (line.matches("\\s*")){
            return false;
        }
        else {
            return true;
        }

计算空行

        String[] lines = fileContent.split("\n");
        for (String line:lines)
        {
            if (isLine(line))
            {
                lineNum++;
            }
        }

排序单词

    list = new ArrayList<Map.Entry<String,Integer>>(wordMap.entrySet());
    Collections.sort(list, new Comparator<Map.Entry<String,Integer>>() {
        @Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
        //如果词频相同,则按字典序输出
        if (o2.getValue()==o1.getValue()){
            return o1.getKey().compareTo(o2.getKey());
        }
            return o2.getValue().compareTo(o1.getValue());
}

性能改进

  1. 使用缓冲流BufferedReader来进行文件的读写
  2. 使用StringBuilder 代替String/StringBuffer 来提高效率、节约时间
  3. 第一次读入文件是在“字符数统计”,可以设置一个变量来存文本内容,这样只需要读一次文件,节省了时间成本。

70W字符运行速度

avatar

单元测试

测试单词合法性

avatar

测试行合法性

avatar

测试字符数

avatar

测试单词数

avatar

测试行数

avatar

测试结果

avatar

测试单词排序

avatar

排序结果:正确

avatar

测试单词数超过10

avatar

测试结果:正确

avatar

覆盖率

avatar

异常处理

在Lib类遇到IO异常时会抛出给主函数,由主函数catch后输出文件不存在!
当命令行运行时没有两个参数会输出there are not 2 parameters needed!

心路历程

  1. 学会正则表达式的基本使用,比起运用if判断要简洁高效许多
  2. 复习了文件的读写操作
  3. 制定了代码规范,以后都需要按照这个规范来执行,以前写代码的时候没有重视这部分,使用自己熟悉的规范,不仅自己再看时简洁,对于别人也是一样
  4. 第一次使用单元测试,以前测试都是通过输出语句来确认。现在意识到,单元测试很重要,能够更快地发现bug。
  5. 学会了使用Github,来对代码进行签入。
  6. 在编程之前,使用PSP表格,对该项任务进行预估;也说明了在编程前,早期的准备与思考同样很重要,这样写出来的程序更有条理性,更易于维护
posted @ 2021-03-04 21:58  _QAQ_wmz  阅读(141)  评论(3编辑  收藏  举报