2020软件工程作业_02

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2020
这个作业的要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2020/homework/11167
这个作业的目标
  • 学会使用GitHub
  • 了解代码规范
  • 学会项目流程规划
  • 学会python统计分析方法
  • 学习项目的单元测试方法
学号 031802233

一. PSP表格

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

二. 解题思路

单纯做题,QQ传文件:

  1. 看到题目之后,下载示例测试数据,发现为json格式,之前学习python时了解到python对于这类文件的处理比较方便 ——> 复习python的json处理方法
  2. python对于一个文件夹下所有json文件的处理 ——> os模块复习
  3. 观察到格式要求为:
    python3 GHAnalysis.py <--init|-i> <path to data>
    
    python如何处理此类命令?
    了解到python有对应模块argparse ——> 学习对应模块argparse
  4. 单元测试学习:
    因为之前并没有接触过“单元测试”这个概念,所以对于我来说单元测试相对算是一个全新的内容。
    了解到python有对应模块 unittest 和 coverage ——> 学习对应模块 unittest、coverage
  5. 编写代码过程:
    学习python编码格式规范。

做完之后,GitHub传文件:

  1. git一大堆命令 ——> 学习git,掌握基本命令

    一开始是懵的,比如:

    • git 为什么要先 add 再 commit ?
    • 为什么删除不需要先 add 再 commit ?
    • 回退过程什么情况下不能够回退? ——任何情况下都能回退
    • 不同情况下回退的命令都是什么?
  2. 学习git和github连接

    • git 和 github 用 ssh 连接,为什么不用 http ?
    • 为什么要先 git init 再 git remote add ?
    • git clone 和 git pull 的区别是什么?
    • pull request 是什么意思?为什么取这么奇怪的名字?
    • pr是最后“交卷”,那一开始就pr和最后才pr的区别是什么?
    • 为什么使用 ssh协议,GitHub知道公钥就能验证我的身份?
    • 为什么我在宿舍生成的ssh密钥,用校园网就验证不了了?
    • ...

    push 的时候发生过各种各样奇奇怪怪的错误...
    最后谢谢各类博客和StackOverflow。

  3. 学习 GitHub 的自动化流程:

    • github的 Action 是什么?workflows是什么?
    • .yml 格式又是什么?
    • .gitignore 格式又又是什么?

三. 设计过程

四. 代码说明

添加命令行参数
def argInit(self):
    # 初始化参数
    self.parser.add_argument('-i', '--init')
    self.parser.add_argument('-u', '--user')
    self.parser.add_argument('-r', '--repo')
    self.parser.add_argument('-e', '--event')
命令解析,并根据命令执行 初始化/查询 过程
def orderAnalyze(self):
    # 初始化
    if self.parser.parse_args().init:
        self.data = Data(self.parser.parse_args().init, 1)
        return 0
    else:
        # 无数据重新加载
        if self.data is None:
            self.data = Data()
        if self.parser.parse_args().event:
            if self.parser.parse_args().user:
                # 查询某用户在某项目某事件
                if self.parser.parse_args().repo:
                    res = self.data.getEventsUsersAndRepos(
                        self.parser.parse_args().user, self.parser.parse_args().repo, self.parser.parse_args().event)
                # 查询某用户某事件
                else:
                    res = self.data.getEventsUsers(
                        self.parser.parse_args().user, self.parser.parse_args().event)
            # 查询某项目某事件
            elif self.parser.parse_args().repo:
                res = self.data.getEventsRepos(
                    self.parser.parse_args().reop, self.parser.parse_args().event)
            else:
                raise RuntimeError('error: argument -l or -c are required')
        else:
            raise RuntimeError('error: argument -e is required')
    return res
初始化过程
def __init__(self, dict_address: str = None, reload: int = 0):
    # 需要重新加载数据时
    if reload == 1:
        self.dataLoadIn(dict_address)
    # 数据地址为空且无加载数据时
    if dict_address is None and not os.path.exists('user.json') and not os.path.exists('repo.json') and not os.path.exists('user_repo.json'):
        raise RuntimeError('error: init failed')
    # 某用户的某事件数量
    x = open('user.json', 'r', encoding='utf-8').read()
    self.__4Events4PerP = json.loads(x)
    # 某项目的某事件数量
    x = open('repo.json', 'r', encoding='utf-8').read()
    self.__4Events4PerR = json.loads(x)
    # 某用户在某项目的某事件数量
    x = open('user_repo.json', 'r', encoding='utf-8').read()
    self.__4Events4PerPPerR = json.loads(x)

def dataLoadIn(self, dict_address: str) -> bool: 
    json_list = []
    # 遍历文件夹
    for root, dic, files in os.walk(dict_address):
        for f in files:
            # 处理目标json文件
            if f[-5:] == '.json':
                json_path = f
                x = open(dict_address+'\\'+json_path,
                            'r', encoding='utf-8').read()
                # json文件转换为数组, 元素为一行json格式的数据
                str_list = [_x for _x in x.split('\n') if len(_x) > 0]
                for _str in str_list:
                    try:
                        json_list.append(json.loads(_str))
                    except:
                        pass
    records = self.__listOfNestedDict2ListOfDict(json_list)
    self.__4Events4PerP = {} # 存 某用户某事件
    self.__4Events4PerR = {} # 存 某项目某事件
    self.__4Events4PerPPerR = {} # 存 某用户某项目某事件
    for i in records:
        if not self.__4Events4PerP.get(i['actor__login'], 0):
            self.__4Events4PerP.update({i['actor__login']: {}})
            self.__4Events4PerPPerR.update({i['actor__login']: {}})
        self.__4Events4PerP[i['actor__login']][i['type']
                                        ] = self.__4Events4PerP[i['actor__login']].get(i['type'], 0)+1
        if not self.__4Events4PerR.get(i['repo__name'], 0):
            self.__4Events4PerR.update({i['repo__name']: {}})
        self.__4Events4PerR[i['repo__name']][i['type']
                                    ] = self.__4Events4PerR[i['repo__name']].get(i['type'], 0)+1
        if not self.__4Events4PerPPerR[i['actor__login']].get(i['repo__name'], 0):
            self.__4Events4PerPPerR[i['actor__login']].update({i['repo__name']: {}})
        self.__4Events4PerPPerR[i['actor__login']][i['repo__name']][i['type']
                                                        ] = self.__4Events4PerPPerR[i['actor__login']][i['repo__name']].get(i['type'], 0)+1
    # 写入保存查询文件
    with open('user.json', 'w', encoding='utf-8') as f:
        json.dump(self.__4Events4PerP,f)
    with open('repo.json', 'w', encoding='utf-8') as f:
        json.dump(self.__4Events4PerR,f)
    with open('user_repo.json', 'w', encoding='utf-8') as f:
        json.dump(self.__4Events4PerPPerR,f)
    return True # 数据加载处理成功

五. 性能优化/测试

1. 性能测试截图

2. 性能优化

在数据规模量高达 10 Gb的情况下,加之python一直以来的“慢”,IO速度可能惊人,想到要做些什么改善性能。
了解到python可以利用 多线程+队列 同时读取多个文件改善IO速度,但这一部分代码看的有些模糊,暂未学会...

六. 代码规范

链接:https://github.com/2441461233/2020-personal-python/blob/master/CodeStyle.md

七. 总结

  • 通过这次的学习,高压之下用两三天就把之前学了大半年没学会的GitHub的基本使用学会了。
  • 学做一个项目是一个发散式学习的过程,一个不懂的问题可能引申出十个不懂的问题。
    eg:从一个报错 “Hi XXX! You've successfully authenticated, but GitHub does not provide shell access.” 到 ssh 协议的细节...
    ...
  • 做项目不能不分析,直接扎进去就会一头雾水。
  • 将项目拆解之后需要分开专注于各自的细节:利用“模块化”思维,不仅程序要模块化,项目流程也要模块化 —— 分步拆解、逐个解决。
posted @ 2020-09-17 12:32  izyow  阅读(274)  评论(3编辑  收藏  举报