2020寒假作业(2/2)疫情统计

这个作业属于哪个课程 2020春W班
这个作业要求在哪里 疫情统计
这个作业的目标 学习使用Git、Github、学会做单元测试
作业正文 作业正文
其他参考文献 《构建之法》...

一、GitHub仓库地址

GitHub

二、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 22
Estimate 估计这个任务需要多少时间 30 20
Development 开发 308 330
Analysis 需求分析 (包括学习新技术) 20 40
Design Spec 生成设计文档 20 25
Design Review 设计复审 15 26
Coding Standard 代码规范 (为目前的开发制定合适的规范) 12 12
Design 具体设计 40 46
Coding 具体编码 135 80
Code Review 代码复审 30 35
Test 测试(自我测试,修改代码,提交修改) 50 80
Reporting 报告 32 23
Test Report 测试报告 10 7
Size Measurement 计算工作量 8 5
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 10 11
合计 750 762

三、解题思路

首先看一下这道题的需求,接受形如$ java InfectStatistic list -date 2020-01-22 -log D:/log/ -out D:/output.txt的命令,处理日志文件,得到输出文件。
由此,这道题的程序流程如下:接受命令、检验命令合法性、读取文件、处理数据、得到输出文件
flowchart1

1.命令解析

命令形如:
$ java InfectStatistic list -date 2020-01-22 -log D:/log/ -out D:/output.txt

参数如下:

  • -log:指定日志文件的路径,该项必带。
  • -out:指定输出文件的路径和文件名,该项必带。
  • -province:指定需要在输出文件中必须列出的省份(可选),默认为日志文件中涉及的省份。
  • -type:指定输出文件中需要列出的感染类型(可选),默认为所有感染类型
  • -date:指定日期(可选),默认为日志文件中提供的最新日期。

由此,命令解析算基本完成了,也可以确定命令合法性检验函数了

2.日志文件

命令解析完,就该处理输入数据了,数据存在于日志文件中。所以我们要处理数据就需要知道日志文件的结构才好对症下药。
日志文件名形如:年-月-日.log.txt,文件名中的年月日为该日志文件记录的感染变化情况的日期,故命令中提供的-date参数不应大于最新日志文件的日期。
日志文件内容形如:

福建 新增 感染患者 23人
福建 新增 疑似患者 2人
浙江 感染患者 流入 福建 12人
湖北 疑似患者 流入 福建 2人
安徽 死亡 2人
新疆 治愈 3人
福建 疑似患者 确诊感染 2人
新疆 排除 疑似患者 5人

由上,我们可以把数据行分为六种类型:新增、流入、死亡、治愈、确诊感染、排除。
我们只需建立匹配模式,对其中的行进行匹配,就能获取我们想要的数据了

flowchart2

3.输出文件

最后,我们只需按拼音排序将要求省份的要求感染类型以如下形式写进命令要求的输出文件即可

全国 感染患者22人 疑似患者25人 治愈10人 死亡2人
福建 感染患者2人 疑似患者5人 治愈0人 死亡0人
浙江 感染患者3人 疑似患者5人 治愈2人 死亡1人

四、设计实现过程

我从需求中提取出命令和文件两个类,分别负责管理命令和管理文件。
命令类CommandHandler:检验命令参数合法性,获取需要处理的日志文件列表,接受文件处理类返回的数据行,匹配模式,提取数据,统计各类型感染数据,生成数据行交给文件管理类进行写入,获得输出文件。

文件管理类FileOperator:接受命令管理类传入地路径和数据行,对文件进行读写

classchart

这个题目的结构设计的相对简单

五、代码说明

程序的主函数相对简单,从命令中获取参数、检验参数合法性、获取输出文件

if __name__=="__main__":
    if sys.argv[1]!='list':
        print('Command Error')
        exit(1)

    #获取参数
    logPath=Lib.findInformation('-log')
    outPath=Lib.findInformation('-out')
    provinceList=Lib.findInformation('-province')
    infectTypeList=Lib.findInformation('-type')
    dateList=Lib.findInformation('-date')


    if len(logPath)!=0 or len(outPath)!=0:
        print('Command Error!')
        exit(1)

    #生成命令对象
    if len(dateList)==0:
        command=Lib.CommandHandler(logPath[0],outPath[0],provinceList,
                                   infectTypeList,None)
    else:
        command=Lib.CommandHandler(logPath[0],outPath[0],provinceList,
                                   infectTypeList,dateList[0])

    #检验参数合法性
    if not command.isArgsRightful():
        print('Args Error!')
        exit(2)

    #得到输出文件
    command.getOutputFile()

以下是CommandHandler类的结构

class CommandHandler:

    def __init__(self):
        ...

    def isArgsRightful(self):
        ...

    def getOutputFile(self):
        ...

    def getStaticList(self):
        ...

    def getFileList(self):
        ...

接下来是FileOperator类的结构:

class FileOperator:

    def __init_(self):
        ...

    def writeLine(self,strArg):
        ...

    def readLine(self)
        ...

    def close(self):
        ...

和两个用于获取参数和比较日期的函数:

def findInformation(informationName):
    list=[]
    args=sys.argv
    try:
        i=args.index(informationName)+1
        while i<len(args):
            if args[i][0]!='-':
                list.append(args[i])
            else:
                break
            i+=1
    except ValueError:
        return list
    return list

#比较datestr1和datestr2的大小
def dateCompare(datestr1,datestr2):
    time1=time.mktime(time.strptime(datestr1,"%Y-%m-%d"))
    time2=time.mktime(time.strptime(datestr2,"%Y-%m-%d"))
    return time1>=time2

六、单元测试

单元测试我用了十一个测试分别对不同参数组合,和输出文件的内容进行了测试,测试函数如下:
testFunction

七、单元测试覆盖率和性能优化

  • 单元测试
    单元测试结果如图(测试文件为example中的log文件)
    unittest
    单元测试覆盖率如下:
    coverage
  • 性能优化
    在对代码进一步思考后,发现在对信息进行匹配时每个省份、每个模式、每一个数据行都进行了交叉匹配浪费了很大的资源。于是对其进行了如下的优化:省份也作为提取对象从数据行中进行提取,而不是遍历列表,每个省份都匹配一遍。如:p+' 新增 (.+) (\\d+)人'->'(.+) 新增 (.+) (\\d+)人'

八、代码规范

codestyle.md

九、心路历程和收获

心路历程

一开始拿到这个作业,看到需求我是懵逼的,各种要求、各种文档、各种格式,看的我头昏眼花。还有GitHub、仓库、PSP表格、单元测试,各种各样没有接触过的东西。还有我自己个人原因决定用自学的python语言去完成这一项目,也给我带来了一些问题。语言问题、需求问题、代码组织问题交织在一起。但当我慢慢地分析需求下来,发现这个题目还是很简单的。于是开始着手写了起来,遇到问题,查找资料、思考、重新捋清需求、组织程序结构,终于写好了整个程序的雏形。到了单元测试的时候才是硬菜,由于用的是python,由于测试方法不同于Java,只能从网上找资料写测试程序。以前没有做过程序测试,不懂得如何去做测试数据,怎么测试程序的好坏,一切都是从零开始。

收获

虽然这次的作业花了很长的时间,但收获也很大。学会了使用注册了很久但是从没用过的GitHub、以前自学的python也真正地用了起来,学会了使用Unittest。积累了一些做团队做项目地经验,虽然说只是我一个人在做。

十、Github上的五个仓库

后端架构师图谱

一些后端开发题

个人博客前后端开发项目

运维笔记

Linux实战案列

猜你喜欢

转载自www.cnblogs.com/Striker-Lin/p/12322677.html