软件工程实践2020_作业2

软件工程2020寒假作业2

这个作业属于哪里 2020春丨W班 (福州大学)
这个作业的要求在哪里 作业要求
这个作业的目标 创建熟悉使用Github,完成提交疫情统计程序
作业正文 ...
其他参考文献 https://www.cnblogs.com/hengyumo/p/12276133.html
Github仓库地址 https://github.com/XTG-L/InfectStatistic-main

Github仓库地址

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 30
Estimate 估计这个任务需要多少时间 10 5
Development 开发 8*60 10*60
Analysis 需求分析(包括学习新技术) 30 20
Design Spec 生成设计文档 30 30
Design Review 设计复审 30 10
Design Standard 代码规范(为目前开发指定合适的规范) 10 5
Design 具体设计 20 30
Coding 具体编码 8*60 9*60
Code Review 代码复查 2*60 60
Test 测试(自我测试,修改代码,提交修改) 2*60 2*60
Reporting 报告 2*60 3*60
Test Report 测试报告 60 60
Size Measurement 计算工作量 500行 600行
Postmortem & Process Improvement Plan 60 60
合计 1630 1660

解题思路

需求分析

  1. 读取指定路径下所有格式为YYYY-MM-dd.log.txt的日志文件,统计日志文件的信息并输出到指定的文件
  2. 支持处理命令行参数

设计思路

  1. 实现CmdArgs类,用于处理命令行输入的命令(包括分析命令,获取参数及其值,判断命令是否符合规范等)

  2. 实现CmdList类,用于处理list命令(包括实现具体命令需要的变量,函数等)

  3. 实现Log类,用于实现对日志文件的判断和处理(包括选择需要读取的日志文件,判断是否为注释行等)

  4. 实现Region类,用于将日志文件内容转换并保存为Region类并做接下来的处理(包括对地区的排序,人数统计等)

     命令从命令行被读取后先由CmdArgs类进行命令的判断,然后进入具体的命令类执行命令
     CmdList类中,会调用Log类及其内部Region类进行日志文件的读取和转换
     经过Log类和Region类的处理后,Cmdlist会将处理后的数据输出到指定的文件中覆写
    

流程图

实现过程

    InfectStatistic类中的main()函数用于接受并传递参数给CmdArgs类
    CmdArgs类中的action()函数用于开始执行具体命令
        isAssign()函数用于判断一个地区是否为指定地区
        isLegal()函数用于判断读入的命令是否符合规范
        readLog()函数用于从指定路径下的文件中读取日志文件
        regionToLine()函数用于将一个Region类转换为一行要输出的结果
        outLog()用于向指定文件覆写结果
    Log类中的logToRegion()函数用于将Log类的数据转换为Region类
        isIgnore()用于判断日志文件中的一行是否为注释行
        rmAfter()用于移除读取队列中指定日期之后的日志文件
        sumAll()用于统计全国地区的数据
    Region类中的equals()用于判断两个地区对象是否相等
        indexOfRegion()用于获取指定地区在动态数组中的下表
        RegionToInt()用于统计地区类中存储的动态数组中的数据
        sort()用于对地区类进行排序

类图

代码说明

关键函数

  • 执行命令
    void action() {
        try {
            readLog(this.logPath, this.files, this.logs);
            Log.logToRegion(this.logs, this.regions);
            outLog(this.outPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 读取日志文件并储存在logs里,然后调用logToRegion将日志文件转换并保存
  • @param logPath
  • @throws IOException
static void readLog(String logPath, String[] files, ArrayList<String> logs) throws IOException {
        BufferedReader br = null;
        String line = null;
        for (String name : files) {
            if (name.equals("")) continue;
            FileInputStream fis = new FileInputStream(logPath + name);
            InputStreamReader isr = new InputStreamReader(fis, "utf-8");
            br = new BufferedReader(isr);
            while((line = br.readLine()) != null)
                if(!Log.isIgnore(line))
                    logs.add(line);
            br.close();
        }
    }
  • 将日志文件转换为地区类并储存
  • @param logs
static void logToRegion(ArrayList<String> logs, ArrayList<Log.Region> regions) {
        for (String log : logs) {
            String[] items = log.split("[\\s]+");
            int index = Log.Region.indexOfRegion(regions, items[0]);
            int num = 0;
            for (String item : items)
                if (item.endsWith("人"))
                    num = Integer.valueOf(item.replace("人", ""));
            Log.Region region = regions.get(index);
            switch (items[1]) {
            case "新增": {
                if (items[2].equals("感染患者"))
                    region.ip.add(num);
                else if (items[2].equals("疑似患者"))
                    region.sp.add(num);
                break;
            }
            case "感染患者": {
                if (items[2].equals("流入")) {
                    region.ip.add(0 - num);
                    Log.Region another = regions.get(Log.Region.indexOfRegion(regions, items[3]));
                    another.ip.add(num);
                }
                break;
            }
            case "疑似患者": {
                if (items[2].equals("确诊感染")) {
                    region.ip.add(num);
                    region.sp.add(0 - num);
                } else if (items[2].equals("流入")) {
                    region.sp.add(0 - num);
                    Log.Region another = regions.get(Log.Region.indexOfRegion(regions, items[3]));
                    another.sp.add(num);
                }
                break;
            }
            case "治愈": {
                region.cure.add(num);
                region.ip.add(0 - num);
                break;
            }
            case "死亡": {
                region.dead.add(num);
                region.ip.add(0 - num);
                break;
            }
            case "排除": {
                region.sp.add(0 - num);
                break;
            }
            default: {
                break;
            }
            }
        }
    }
  • 向指定路径输出结果
  • @param outPath
  • @throws IOException
void outLog(String outPath) throws IOException {
        Log.Region.sort(regions);
        FileOutputStream fos = new FileOutputStream(outPath);
        OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
        Log.Region all = Log.sumAll(regions);
        osw.write(regionToLine(all) + "\n");
        osw.flush();
        for (Log.Region region : regions)
            if(isAssign(this.province, region)) {
                osw.write(regionToLine(region) + "\n");
                osw.flush();
            }
        osw.close();
    }

单元测试及代码覆盖率截图

单元测试

单元测试

class InfectStatisticTest {
	@Test
	void testList() {
		String[] str = {"list",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt"};
		InfectStatistic.main(str);
	}
	
	@Test
	void testLog() {
		String[] str = {"list",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt"};
		InfectStatistic.main(str);
	}
	
	@Test
	void testDate() {
		String[] str = {"list",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt",
				"-date", "2020-01-25"};
		InfectStatistic.main(str);
	}
	
	@Test
	void testType() {
		String[] str = {"list",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt",
				"-type", "ip", "sp"};
		InfectStatistic.main(str);
	}
	
	@Test
	void testProvince() {
		String[] str = {"list",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt",
				"-province", "北京", "福建"};
		InfectStatistic.main(str);
	}
	
	@Test
	void testErrorList() {
		String[] str = {"errorlist",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt"};
		InfectStatistic.main(str);
	}
	
	@Test
	void testErrorType() {
		String[] str = {"list",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt",
				"-type", "errorType"};
		InfectStatistic.main(str);
	}
	
	@Test
	void testTypeProvince() {
		String[] str = {"list",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt",
				"-type", "ip", "sp",
				"-province", "北京", "福建"};
		InfectStatistic.main(str);
	}
	
	@Test
	void testDateProvince() {
		String[] str = {"list",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt",
				"-date", "2020-01-25",
				"-province", "北京", "福建"};
		InfectStatistic.main(str);
	}
	
	@Test
	void testDateType() {
		String[] str = {"list",
				"-log", "C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\log\\",
				"-out",	"C:\\Users\\97680\\Documents\\GitHub\\InfectStatistic\\221701127\\result\\ListOut.txt",
				"-type", "ip", "sp",
				"-date", "2020-01-25"};
		InfectStatistic.main(str);
	}
}

代码覆盖率及优化思路

代码覆盖率
1. 尽量使用正则表达式,避免直接使用固定的字符串
2. 尽量细化函数功能,降低程序粒度,提高代码覆盖率

代码规范

代码规范链接

心路历程

  1. 在进行代码编写之前,先根据需求,确定工作流程,确定整体的框架,之后再编写代码,这样能过减少修改代码结构的次数和时间,减少不必要的工作。
  2. 在进行测试前,可以编写用于进行测试的函数,方便日后或者是他人的测试
  3. 代码完成后,还要进行代码优化和覆盖率测试,减少不必要的运行开销
posted @ 2020-02-16 20:22  XTG  阅读(247)  评论(1编辑  收藏  举报