第四周作业之wcPro输出模块的实现

一、基本任务:代码编写+单元测试

小组github地址

https://github.com/SkateCloud/wcPro

PSP表格

PSP2.1 PSP阶段 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 60
Estimate 估计任务需要多少时间 30 60
Development 开发 180 150
Analysis 需求分析 20 30
Design Spec 生成设计文档 20 30
Design Review 设计复审 20 30
Coding Standard 代码规范 30 10
Design 具体设计 30 50
Coding 具体编码 30 40
Code Review 代码复审 30 40
Test 测试 50 10
Reporting 报告 70 240
Test Report 测试报告 30 100
Size Measurement 计算工作量 20 60
Postmortem 总结 20 80
  合计 340 450

接口设计

  • 接口描述

本人负责的是输出模块,即对结果以合理方式输出,将单词词频排序的结果输出到文件。

  • 设计思路

通过对单词词频排序的结果存入数组表,然后通过文件操作将数组表内容打印至指定文件内

  • 实现过程

由于外部存储机构使用的是Map.Entry,不便于操作,所以将map转化为List结构

List> list = new ArrayList<>();
        list.addAll(words.entrySet());//词组进入list表
        list.sort((lhs, rhs) -> { //比对排序
            int cmp = -lhs.getValue().compareTo(rhs.getValue());
            if (cmp != 0) return cmp;
            else return lhs.getKey().compareTo(rhs.getKey());
        });

然后将排序后的List结果做文件操作写入指定的result.txt文件中

try (FileWriter fout = new FileWriter("result.txt")) {
            int maxsz = Math.min(list.size(), 100);
            for (int i = 0 ; i < maxsz; ++ i) {
                Map.Entry item = list.get(i);
                fout.write(item.getKey());
                fout.write(' ');
                fout.write(item.getValue().toString());
                if (i != maxsz - 1)
                    fout.write('\n');
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

测试设计

测试用例设计思路:

保证设计的测试用例应至少覆盖函数中所有的可执行语句,同时主要空数组、最差情况、词频排序、字母排序、两者混合等各种情况设计测试用例。

第四周作业之wcPro输出模块的实现_第1张图片

单元测试

使用测试脚本进行单元测试,过程如下

第四周作业之wcPro输出模块的实现_第2张图片

单元测试效果良好,没有报错

小组贡献

我们小组齐心协力, 攻克难关,积极讨论,指出问题,我认为我的小组贡献分是0.3

二.扩展任务:静态测试

1. 代码规范

采用以下Java开发规范

1.1 命名规则

需遵守java基本命名规范,以下列举需要着重注意的地方和我们的一些规则。

l 统一采用驼峰标识。

l 不允许使用汉语拼音命名,特殊含义的除外。

l 遇到缩写如XML时,需全部大写,如loadXMLDocument()。

l 局部变量及输入参数不要与类成员变量同名(set方法与构造函数除外)

l 常量必须都是大写字母,名称包含多个词时,使用下划线来分割,并且保证命名有完整含义,比如PRODUCT_TYPE。枚举值也是常量,遵守该规则。

l 项目名与模块名之间,使用”-”隔开,不再使用”_”。区分代码和项目的命名规则。

l Package名必须全部小写,尽量使用单个单词。

l Interface名统一采用首字母为I。

l 注意单类中,变量名的一致性。例如,在一个service中的几个方法,都定义有useName变量,或者进行简写uname等,不论全写还是简写,前后方法对于同一变量的命名都需要保持一致,便于可读。

l 在同一个方法中,不建议一个变量表示多个意义不同的数值。

1.2 声明规则

1.2.1 修饰符顺序

修饰符应该按照如下顺序排列:public, protected, private, abstract, static, final, transient, volatile, synchronized, native, strictfp。

1.2.2 类定义顺序

类内容定义的顺序

l 静态成员变量 / Static Fields
l 静态初始化块 / Static Initializers
l 成员变量 / Fields
l 初始化块 / Initializers
l 构造器 / Constructors
l 静态成员方法 / Static Methods
l 成员方法 / Methods
l 重载自Object的方法如toString(), hashCode() 和main方法
l 类型(内部类) / Types(Inner Classes)

同等的顺序下,再按public, protected,default, private的顺序排列。

我的编程习惯与以上附录中所述规范大致相同,即使不同,我也会通过编辑器插件进行代码规范化。而在其他如代码审查等重要规范上有待提高。

2. 同组分析

我分析了组长16980的代码,缩进、断行风格整洁,命名简单明了,逻辑清晰易读,但在代码设计规范上,模块化不足,不易于进行团队的coding工作,经常在git操作上发生冲突.

最后决定将团队代码进行整合重构,重构任务由组长16980完成,故最终贴出组长的重构代码

public class wordcount {
    public static void main(String[] args) {
        long t1 = System.currentTimeMillis();
        new wordcount().start(args);
        long t2 = System.currentTimeMillis();
        long dt = t2 - t1;
        System.out.println(("Elapsed " + dt + "ms"));
    }

    private void start(String[] args) {
        HashMap words = new HashMap<>();
        String str = readFile(args[0]);
        {
            int state = 0;
            int beginIndex = -1;
            for (int i = 0; i <= str.length(); ++i) {
                char ch = i == str.length() ? ' ' : str.charAt(i);
                boolean isWordChar = ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ch == '-';
                if (state == 0 && isWordChar && ch != '-') {
                    beginIndex = i;
                    state = 1;
                } else if (state == 1 && !isWordChar) {
                    String word = str.substring(beginIndex, i).toLowerCase();
                    words.put(word, words.getOrDefault(word, 0) + 1);
                    state = 0;
                }
            }
        }

        List> list = new ArrayList<>();
        list.addAll(words.entrySet());
        list.sort((lhs, rhs) -> {
            int cmp = -lhs.getValue().compareTo(rhs.getValue());
            if (cmp != 0) return cmp;
            else return lhs.getKey().compareTo(rhs.getKey());
        });

        try (FileWriter fout = new FileWriter("result.txt")) {
            int maxsz = Math.min(list.size(), 100);
            for (int i = 0 ; i < maxsz; ++ i) {
                Map.Entry item = list.get(i);
                fout.write(item.getKey());
                fout.write(' ');
                fout.write(item.getValue().toString());
                if (i != maxsz - 1)
                    fout.write('\n');
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    private String readFile(String path) { // 读文件
        try {
            byte[] encoded = Files.readAllBytes(Paths.get(path));
            return new String(encoded, "UTF-8");
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

}

3. 静态代码检查工具

使用的是IDEA的插件Ant Build中的检错功能
Ant Build是一个Java自动化生成工具,其检错功能用来检查类或者jar文件,用来发现可能的问题。检测完成之后会生成一份详细的报告,借助这份报告可以找到潜在的bug.

检测范围

  • 常见代码错误,序列化错误
  • 可能导致错误的代码,如空指针引用
  • 国际化相关问题:如错误的字符串转换
  • 可能受到的恶意攻击,如访问权限修饰符的定义等
  • 多线程的正确性:如多线程编程时常见的同步,线程调度问题。
  • 运行时性能问题:如由变量定义,方法调用导致的代码低效问题

4. 扫描结果

第四周作业之wcPro输出模块的实现_第3张图片

检测结果在右上角,可以看出仅有少量警告,根据IDEA红线标注可发现大多是声明方式不是按照目前使用的java标准,没有发生内存泄露等问题.

5. 小组代码问题说明

  • 由于进行了整合重构,所以模块化程度降低,不易维护,但程序执行效率上升
  • 异常处理的不够全面,应该覆盖大部分的一场情况,以便于检查与调试

三. 高级任务:性能测试和优化

设计,评审,优化
选择10kb,50kb,182kb大小的txt文件进行测试,程序处理时长如下:

      输入输出:1ms,1ms,2ms

      单词统计:20ms,150ms,540ms

      词频排序:6ms,8ms,10ms

  单词统计时间与文件大小呈线性相关,其他两个模块占比较小,故程序性能主要受到文件大小影响。组内共同对代码结构和细节进行详细审查并与其他组程序对比,整理得到如下观点:

    1.整合重构是正确的,不仅增加了代码的可读性和规范性,还大幅增加了程序的性能

    2.将大部分功能模块聚集在一个类方法中,虽然会导致代码耦合度增高,不易于团队维护和再开发,但是减少了模块间相互调用的开销和随之产生的内存开销

小结

通过基本任务、扩展任务、到高级任务的完成以及中间遇到的许多困难,体现出了软件测试对于软件开发的重要性。在开发过程中,使用静态测试工具实时地检测自己的代码,可以改正自己不良的编程习惯,更能防患于未然,减少出现bug的可能;对自己的模块进行单元测试,可以保障自己代码的正确性,更是对其他开发成员和整个任务的负责,使软件开发能够一步一个脚印地稳定开展;对性能的分析与测试,能使软件的质量进一步提高,同事能总结开发经验,使自己设计的模块更加高效。

你可能感兴趣的:(第四周作业之wcPro输出模块的实现)