2020寒假作业(2/2)

2020寒假作业(2/2)

这个作业属于哪个课程 软件工程
这个作业要求在哪里 作业要求
这个作业的目标 完成一个疫情统计的项目
作业正文 此页
其他参考文献 博客园,csdn,构建之法

Github地址

点击进入

PSP表格

psp各个阶段 预估时间
(分钟)
实际记录
(分钟)
明确需求和其他因素并预估时间 35 30
需求分析(包括学习新技术、新工具) 60 90
生成设计文档 30 20
设计复审 15 10
代码规范(为目前的开发制定合适的规范) 30 25
具体设计 30 20
具体编码 300 380
代码复审 45 25
测试(自我测试,修改代码,提交测试) 45 50
测试报告 20 30
计算工作量 15 10
事后总结, 并提出过程改进计划 40 30
总计 665 710

解题思路阐述

  • 一开始时命令行的解析

    这次作业主要是考虑命令行的输入输出和用文本的处理对于命令有如下要求:

    list命令 支持以下命令行参数:

    -log 指定日志目录的位置,该项必会附带,请直接使用传入的路径,而不是自己设置路径
    -out 指定输出文件路径和文件名,该项必会附带,请直接使用传入的路径,而不是自己设置路径
    -date 指定日期,不设置则默认为所提供日志最新的一天。你需要确保你处理了指定日期之前的所有log文件
    -type 可选择[ip: infection patients 感染患者,sp: suspected patients 疑似患者,cure:治愈 ,dead:死亡患者],使用缩写选择,如 -type ip 表示只列出感染患者的情况,-type sp cure则会按顺序【sp, cure】列出疑似患者和治愈患者的情况,不指定该项默认会列出所有情况。
    -province 指定列出的省,如-province 福建,则只列出福建,-province 全国 浙江则只会列出全国、浙江

    思路分析

  • list 命令

由于list命令 作为命令有多个参数,其中log,out参数为必须参数,只要在输入的参数中进行检验,而对于date参数,则需要进行日期的判断和缺省时的日期默认设置,对于province和type参数,由于是多参数,我们引入下列数据结构处理多参数时对参数的处理和数据的访问和输出

private final List PATIENTS_TYPE=new ArrayList(Arrays.asList("ip","sp","cure","dead"));
private final List PATIENTS_STATUS=new ArrayList(Arrays.asList("感染患者","疑似患者","治愈","死亡患者"));
private final List PROVINCE_STR=new ArrayList(Arrays.asList("全国", "安徽","北京", "重庆", "福建","甘肃","广东", "广西", "贵州", "海南","河北", "河南", "黑龙江", "湖北", "湖南", "吉林","江苏", "江西", "辽宁", "内蒙古", "宁夏", "青海", "山东", "山西", "陕西", "上海","四川", "天津", "西藏", "新疆", "云南", "浙江"));

同时我们在命令输入之后对命令行的参数进行解析,能在进行日志文件的处理前很好的确定要做的事情

本部分采用命令模式,主要用Invoker和Command接口实现,一个命令者可以发出多条命令,而命令的具体执行交由接口派生的ListCommand类进行实现。

  • 日志文件

    日志文件的命名:应遵循对应的日期规范:格式:yyyy-mm-dd 采用SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");对日志格式进行约束

    日志文件的解析:我采用文本的正则表达式的格式对日志文本读入行进行数据处理,主要正则表达式为"(\S+) 新增 感染患者 (\d+)人"格式

    日志数据的提取:通过 Matcher.group(index) 对读入行的数据进行解析,同时运用ArrayList结构的内部数据匹配并得到index进行输出

  • 数据处理

    根据不同的指令,将之前数据处理的解析结构存储计算,然后按照输出文件的要求进行输出,这方面的问题并不难。

设计实现过程

2020寒假作业(2/2)_第1张图片
设计过程主要时命令解析 日志处理 数据输出 和测试复审四个过程,这是主要的逻辑视图,而对于各部分的相关说明,已在上部分的思路解析中详细说明。

代码说明

//常量定义
private final List PATIENTS_TYPE = new ArrayList(Arrays.asList("ip","sp","cure","dead"));
private final List PATIENTS_STATUS = new ArrayList(Arrays.asList("感染患者","疑似患者","治愈","死亡患者"));
private final List PROVINCE_STR = new ArrayList(Arrays.asList("全国", "安徽","北京", "重庆", "福建","甘肃","广东", "广西", "贵州", "海南","河北", "河南", "黑龙江", "湖北", "湖南", "吉林","江苏", "江西", "辽宁", "内蒙古", "宁夏", "青海", "山东", "山西", "陕西", "上海","四川", "天津", "西藏", "新疆", "云南", "浙江"));

这部分主要时其中对province和type等多参数的处理的基础,因为ArrayList内部有许多api能对命令中的省份和感染类型进行比对,如get() indexof()等,能很好的简化后期对日志文件的输出

//ListCommand类 配合Invoker类进行命令模式的使用
public static class ListCommand implements Command{}

//命令的参数化函数

public void list(String logPath, String outPath, String date, List province, List type) {
    if(isTrueCommand()) {
        try {
            readFromLogPath(this.logPath);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    try {
        outLogLine(outPath,province,type);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }

//执行命令
@override
public void execute() {
    list(logPath,outPath,date,province,type);
}

这部分主要对命令的参数化进行相关处理,在ListCommand类中,我们有存储对Invoker提出的某条命令的相关变量进行区分,同时,对继承自Command接口的execute进行实现,实现对list命令的执行。

//处理感染患者
public void handleIp(String line) {
    if(Pattern.matches("(\\S+) 新增 感染患者 (\\d+)人", line)) {
        String pattern1="(\\S+) 新增 感染患者 (\\d+)人";
        Pattern r1 = Pattern.compile(pattern1);
        Matcher m1=r1.matcher(line);
        if(m1.find()) {
            data[PROVINCE_STR.indexOf(m1.group(1))][0]+=Integer.parseInt(m1.group(2));
            data[0][0]+=Integer.parseInt(m1.group(2));
        }
    }
        
    if(Pattern.matches("(\\S+) 感染患者 流入 (\\S+) (\\d+)人", line)) {
        String pattern2="(\\S+) 感染患者 流入 (\\S+) (\\d+)人";
        Pattern r2 = Pattern.compile(pattern2);
        Matcher m2=r2.matcher(line);
        if(m2.find()) {
        data[PROVINCE_STR.indexOf(m1.group(1))][1]+=Integer.parseInt(m1.group(2));
        data[0][1]+=Integer.parseInt(m1.group(2));
        data[PROVINCE_STR.indexOf(m2.group(2))][0]+=Integer.parseInt(m2.group(3));
        }
    }
}

对感染患者的相关处理,结合上部分说的ArrayList和相关指令的参数,对ArrayList内部的数值进行提取,并存储于data二元数值中,有助于之后outLogLine的输出。

单元测试

2020寒假作业(2/2)_第2张图片
2020寒假作业(2/2)_第3张图片
2020寒假作业(2/2)_第4张图片

覆盖率测试

2020寒假作业(2/2)_第5张图片
2020寒假作业(2/2)_第6张图片

代码规范

如下:

codestyle

心路历程和收获

通过本次的疫情统计程序的编写,我收获了很多

  • github使用

    接触了许多天的git,我对如何使用命令行有了一定的了解,其中的相关add,commit,push都进行了许多遍的尝试,也理解了git中关于缓冲区和代码仓库的相关知识,使用git进行版本管理和协作开发是真的好用。

  • java模式的学习

    由助教的引导分析,我去学习了java开发中的设计模式中的命令模式和状态模式,对于其中一些地方还是不怎么清楚,但是自己有在此处作业中实验了命令模式的使用,确实使整个代码的耦合度降低了,也有助于理解和编写。
    再有就是正则表达式的学习了,正则表达式处理文本是真的NB,但是现在的我只是学到了点皮毛,我认为之后我可以多用正则表达式处理文本,提升自己相关方面能力。

  • 单元测试

    junit4 的单元测试让我感觉到了程序员对自己代码编写过程的尽可能简化和提高效率,单元测试极大的减少了在自己编写的类中大量繁琐的log和printf。不过,由于本次作业的流程较晚单元测试,所以进行的测试也较少,还是有好多都是由log进行测试,下次仍需改善。

代码仓库

仓库名 仓库地址 简介
servlet3示例 servlet3-showcase 总结并梳理了亿级流量网站高可用和高并发原则,通过实例详细介绍了如何落地这些原则
仿淘宝的B2C商城项目 B2CWeb 项目使用SSH框架和MySQL数据库。实现Spring对Hibernate和Struts的整合
CS-Notes CS-Notes 内部包括很多java基础知识和java并发相关知识
电商系统 macrozheng /mall mall项目是一套电商系统,包括前台商城系统及后台管理系统,基于SpringBoot+MyBatis实现,采用Docker容器化部署。
Spring Boot基础教程 Spring Boot基础教程 通过综合案例学习Spring

你可能感兴趣的:(2020寒假作业(2/2))