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

这个作业属于哪个课程 班级链接
这个作业要求在哪里 作业链接
这个作业的目标 完成项目
作业正文 本页
其他参考文献

Github

本项目使用Python3.7

https://github.com/Mauue/InfectStatistic-main


PSP表格

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

解题思路

由于需求文档足够清晰,看完之后我就把项目大致规划为三个部分

1.解析命令行参数

该项因为之前没写过,所以单独列出来。刚开始查阅资料后,找到了个看似可以的模块 getopt模块。但是仔细阅读需求文档发现,需求是解析list子命令,getopt好像不能解析子命令,查阅了官方文档也没看见。不过官方文档里给出了另一条路:

The getopt module is a parser for command line options whose API is designed to be familiar to users of the C getopt() function. Users who are unfamiliar with the C getopt() function or who would like to write less code and get better help and error messages should consider using the argparse module instead.

于是就采用了argparse模块
之后对着文档操作了一波,能顺利执行下去,此部分暂告一段落。

2.解析日志文件

对txt日志文件进行解析

该日志中出现以下几种情况:
1、<省> 新增 感染患者 n人
2、<省> 新增 疑似患者 n人
3、<省1> 感染患者 流入 <省2> n人
4、<省1> 疑似患者 流入 <省2> n人
5、<省> 死亡 n人
6、<省> 治愈 n人
7、<省> 疑似患者 确诊感染 n人
8、<省> 排除 疑似患者 n人

看的这段话后第一反应就是用正则,想了想应该是可行的,此部分就先这样。

3.计算并输出具体数据

将上一部分的解析结果存储起来,按照要求输出出去,因为两个部分都不难,所以放在一起写。


设计实现过程

按照上一部分的内容,设计出以下逻辑图


代码说明

程序的关键是对日志进行处理。

首先设计数据结构

    def _new_province(self, province):
        self.data.update({province: {"ip": 0, "sp": 0, "cure": 0, "dead": 0}})

数据按照省份的四项数据进行存储

之后是数据处理函数

    def _add_people(self, province, num, _type, _sub=False):
        num = -int(num) if _sub else int(num)
        if province not in self.data:
            self._new_province(province)
        self.data[province][_type] += num

操作的最小步骤为某一省份的某一数据增加或减少一定数量,所以设计了以上函数来处理。

解析日志的函数如下

    def _parse_line(self, line):
        if line.startswith('//'):
            return
        _patterns = [
            ('(.*?) 新增 感染患者 ([0-9]+)人', (((1, 2), 'ip', False),)),
            ('(.*?) 新增 疑似患者 ([0-9]+)人', (((1, 2), 'sp', False),)),
            ('(.*?) 感染患者 流入 (.*?) ([0-9]+)人', (((1, 3), 'ip', True), ((2, 3), 'ip', False))),
            ('(.*?) 疑似患者 流入 (.*?) ([0-9]+)人', (((1, 3), 'sp', True), ((2, 3), 'sp', False))),
            ('(.*?) 死亡 ([0-9]+)人', (((1, 2), 'dead', False), ((1, 2), 'ip', True))),
            ('(.*?) 治愈 ([0-9]+)人', (((1, 2), 'cure', False), ((1, 2), 'ip', True))),
            ('(.*?) 疑似患者 确诊感染 ([0-9]+)人', (((1, 2), 'sp', True), ((1, 2), 'ip', False))),
            ('(.*?) 排除 疑似患者 ([0-9]+)人', (((1, 2), 'sp', True),)),
        ]
        for _pattern, _args_list in _patterns:
            result = re.match(_pattern, line)
            if result:
                for _args in _args_list:
                    index, _type, _sub = _args
                    province, num = result.group(*index)
                    self._add_people(province, num, _type, _sub)
                return

通过匹配正则表达式来解析日志的数据,若之后出现其他的日志格式也可以直接在这添加语句。

拼音排序部分参考了这篇文章

其他部分个人认为较为简单,不再说明。


单元测试

我设计了16种测试用例,覆盖了不同的参数出现可能和可能发生的错误。

测试结果如下:


覆盖率和性能测试

  • 覆盖率
    除主程序入口和解析参数外 其余代码全部覆盖。

  • 性能测试

    • 时间

      耗时最多的的函数是

      • <built-in method _locale.setlocale> 耗时最多的是locale模块的设置语言环境,用于拼音排序,只调用了一次。
      • <built-in method io.open> 打开文件
      • <built-in method nt.stat> 这个查阅资料后发现此函数是用于获取文件信息的,调取log文件时要根据文件名筛选正确格式的日志文件,所以这个函数的调用次数取决于log目录下的文件数 量。
    • 调用次数

      主程序运行部分集中在图的上半部分左侧,运行较多的主要是正则模块相关部分。


代码规范

链接


心路历程与收获

有一说一,这次的作业不难,甚至还没开始设计,我都想好了代码会长什么样,该怎么写。
开发速度还是很快的,完成全部功能大概就两个小时,剩下的都是对需求细节的调整。

收获主要是单元测试和性能分析。

单元测试我以前也写过一点,但是写的不多,因为觉得太麻烦了。但是这次作业我认真的写了十几种测试用例后,尤其是对于接下来的性能分析,测试结果对我的代码帮助真的很大,以后可能会写的多一些。

性能分析这一块,因为pycharm的单元测试机制和其他各种原因,这块的报告我写了四次,每次写到一半发现有些函数根本不知道是在哪调用的,然后发现都是各种原因引入了与主程序无关的函数,导致的错误。摸索挺久算是找到个合理的解决方案,也是不容易。


5个仓库

    • 名称:Tinode Instant Messaging Server
    • github地址: https://github.com/Mauue/chat
    • 简介:即时消息服务器后端,由go开发,一个大型的开源项目,支持gRPC等技术,一个值得去学习的项目。
    • 名称:kratos
    • github地址: https://github.com/Mauue/kratos
    • 简介:bilibili开源的一套Go微服务框架,包含大量微服务相关框架及工具。
    • 名称:Archery
    • github地址: https://github.com/Mauue/Archery
    • 简介:Python项目,定位于SQL审核查询平台,旨在提升DBA的工作效率,支持主流数据库的SQL上线和查询,同时支持丰富的MySQL运维功能,所有功能都兼容手机端操作
    • 名称:git-webhook
    • github地址: https://github.com/Mauue/git-webhook
    • 简介:一个使用 Python Flask + SQLAchemy + Celery + Redis + React 开发的用于迅速搭建并使用 WebHook 进行自动化部署和运维系统。
posted @ 2020-02-09 13:59  Ertyunm  阅读(513)  评论(2编辑  收藏  举报