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


作业基本信息

摘要

这个作业属于哪个课程 课程链接
这个作业要求在哪里 作业链接
这个作业的目标 阅读《构建之法》并提问,完成词频统计个人作业,撰写博客
作业正文 ...
其他参考文献 csdn 百度

任务一:阅读《构建之法》并提问

提问

  1. 书中7.2.4的表7-1 MSF团队模型和关键质量目标里面提到的“出口条件”是什么意思?比如开发的出口条件是:我们是否按照功能说明完成了各项功能。
    答:上网查没有查到,我的理解是开发做到了这一点他的任务就完成了。
  2. 书上8.8.3提到了一个软件团队一开始预计每次天做30小时工作量,做到一半时每天做15小时工作量。我自己在之前的软件编写和大作业上也常常有这样的烦恼。做到后面就要做大量的测试工作,很劳累。和针对测试出的错误修正并确保正确,又很心累。除非快到死线,不然效率都很低。有什么改进的办法吗?
    答:我自己做完这次作业想到的是大概按照估计划分时间,比如说预计解决IDEA的git无法push这一bug估计花20分钟,如果给的时间多了就让自己休息一下。如果给少了就再加班加点做完。这样不会有太多的心理障碍。
  3. 12章的用户体验让我想到了微信。作为被广泛用于社交,办公的软件。他限制了大文件只能在200Mb以下,朋友圈发的图片和视频画质压缩严重。这两方面跟书上说的好的用户体验背道而驰。这是否说明软件发展到一定阶段用户体验反而不太重要了。
    答:我觉得微信这种软件,用户群体如此庞大,骂的人多也正常。最重要还是明确自己的产品定位,做好自己优势的功能,其他功能在与同类产品比较差不多就行。
  4. 15章中提到了在时间不够,功能不能实现时候去砍掉功能。我之前就有一次比赛中一个队友说他想到了一个他刚学会,性能很好的一个方法,做出来肯定二等奖以上。但是3天的比赛我们花了一整天还没有实现,最后只好放弃,而那个队友接下来的时间基本就是在罢工的状态,偶尔还偷偷去做他的功能……遇到这种傻子队友怎么办?
    答:我事后想的最好的办法自然是远离傻子队友。要是下一次还遇到,至少除了他以外的人不要被他所影响,也不要指望他能迷途知返。
  5. 第二章说到单元测试不适合用随机数来做,但应该集成到自动测试框架中,把我有点绕晕了。那自动化单元测试到底是什么?
    答:我查了java运行自动化单元测试的资料。在Theories测试中,用户只需给定了一些数据,JUnit自动利用这些数据组合出各种各种可能的组合来执行测试。

任务二:完成词频统计个人作业

Github项目地址

项目链接

PSP表格

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

解题思路描述

看到题目之后,就想着大概是用java中的文件类File类来读写文件,字符串处理用String类。经过百度查到文件的读取要用到IO类的BufferedReader。大概就知道要百度什么资料。要求要分成三个模块我就先写一个main函数和在Lib中的函数。根据作业要求也提前看了java使用命令行运行,单元测试,github使用等的知识。

代码规范

项目链接

计算模块接口的设计与实现过程

项目有两个类:WordCount类和Lib类。
WordCount类中是Main函数
Lib类中是方法函数,有:

  • countChars
  • countWords
  • countMost
  • isPartOfWord
  • isPartOfAlphaWord
  • countLines
    关键函数的关系:
    Main函数中包含countChars,countWords,countLines,countMost。countWords和countMost中单词判断的部分包含isPartOfWord和isPartOfAlphaWord。关键函数中较为复杂的就是countMost中读取单词后要用HashMap<String, Integer>来存储单词,再用List存储Map,自己重写List的compare方法来实现排序。
    关键代码:
  1. 统计文件的字符数
    只统计ASCII码,所以逐个字符读取并判断。使用reader.read()来实现逐字符读取
int tempchar;
            while ((tempchar = reader.read()) != -1) {
                if (tempchar <= 127 && tempchar >= 0) { //判断是否是ASCII码
                    charnumber++;
                }
            }
  1. 单词按出现次数和字符序排序
    重写compare方法来排序。
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(wordarray.entrySet()); //转换为list
            list.sort(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 o2.getValue().compareTo(o1.getValue());  //判断出现次数大小,大的在前面
                    else
                        return o1.getKey().compareTo(o2.getKey());  //判断字符序大小
                }
            });

3.统计行数
一行行读取,再去除空白行。

while (null != (strLine = bufferedReader.readLine())) {
                for(int i=0;i<strLine.length();i++)
                {
                    if(strLine.charAt(i)!='\t'&&strLine.charAt(i)!='\r'&&strLine.charAt(i)!=' ') { //空白字符判断要依次判断\t,\r和空格。readline已经省略\n就不用判断了
                        lineCount++;
                        break;
                    }
                }
            }

4.Main函数中判断输入是否合法

if (args.length == 2) {  //只能有两个参数
            inputfilename = args[0];
            outputfilename = args[1];
            //其他代码
}
else {
            System.out.println("命令输入错误!");
            System.exit(0);
        }

性能改进

avatar
使用约200,000KB的txt来测试。可以看出程序主要在处理char类和String类。
优化方向以这两个类的IO,处理为主。我更多考虑程序的正确性,暂时没有什么具体的改进想法。

单元测试

部分代码展示:
WordCountTest

public void testMain() throws Exception { 
//TODO: Test goes here...
    String[] files={"D:\\java\\data.txt","D:\\java\\output.txt"};
    WordCount.main(files);
}

    public void testMainWrong() throws Exception {
//TODO: Test goes here...
        String[] files={"D:\\java\\datawrong.txt","D:\\java\\output.txt"};
        try{WordCount.main(files);}
        catch (Exception e) {System.out.println("应该出错了");}

    }

LibTest

public void testIsPartOfWord() throws Exception { 
//TODO: Test goes here...
    Lib lib=new Lib();
    boolean result1=lib.isPartOfWord('a');
    Assert.assertNotNull(result1);
    Assert.assertTrue(result1);
    boolean result2=lib.isPartOfWord('1');
    Assert.assertNotNull(result2);
    Assert.assertTrue(result2);
    boolean result3=lib.isPartOfWord('\n');
    Assert.assertNotNull(result3);
    Assert.assertFalse(result3);
}

public void testCountWords() throws Exception { 
//TODO: Test goes here...
    Lib lib=new Lib();
    lib.countWords("D:\\java\\data.txt","D:\\java\\output.txt");
    lib.countWords("data.txt","outputTCW.txt");
} 

测试截图
avatar
avatar
使用命令行运行
avatar
读取的文件
avatar
运行结果
avatar

心路历程与收获

本来觉得做软件作业的重点是把代码写完,其他的很快就做完了。做到后面发现做单元测试,代码bug的修复,各种异常状况的处理比想象中花的时间更多。
还有就是不要害怕自己没有做过的事情,毕竟做软件有很多可以查到的资料。看完资料后对改怎么做,大概花多少时间就心里有了底。
之前java课程中也有想过用github管理代码,但做了一段时间就不了了之。而这次作业让我学到了很多github、单元测试的知识,让我懂得了有高的目标才更有完成目标的行动动力。

posted @ 2021-03-05 10:14  dqcx  阅读(138)  评论(4编辑  收藏  举报