结对编程_stage1

项目 内容
这个作业属于哪个课程 2021春季软件工程(罗杰 任健)
这个作业的要求在哪里 结对项目-第一阶段
我在这个课程的目标是 从实践中学习软件工程相关知识(结构化分析和设计方法、敏捷开发方法、软件测试、软件项目管理、软件开发工具和环境等),培养合作开发能力
这个作业在哪个具体方面帮助我实现目标 实践结对编程,学习在 CI 中进行单元测试
GitLab 项目地址 2021_Minyi_Xiao-Yulong_Xu_pair_work
学号后四位 3377 3436

一、结对编程感受

结对现场:

3436:

本次结对编程主要在宿舍和新主楼公共区域线下进行,使用一台电脑完成了设计、编码和单元测试的编写。

设计阶段,首先对代码风格进行了沟通和统一,包括缩进,分支的{}书写,变量命名的规范(约定所有类使用 Pascal 形式,属性、变量和方法使用 Camel 形式)。我觉得这种约定不仅可以让代码风格统一美观,还能够让 “领航员” 更容易发现 “驾驶员” 的问题。在单元测试阶段满足覆盖率要求的过程中,我感受到合理的抽象和代码复用能够极大便利正确性的验证。

特别地,我觉得结对编程中两个人的沟通,有助于保持两人持续的专注,消减编码时期的枯燥,避免摸鱼从而提高效率。

3377:

结对编程虽然只能够使用一台设备进行编程,看似编码效率只有常规方式的一半(甚至达不到一半,因为在结对编程的编码过程中有更多的讨论、修改),但是从项目整体耗时来看,在我的体感中,结对编程比常规方式效率不会差太多。我觉得可能是因为结对编程能够极大地减少团队的沟通成本,具体来说,能够减少撰写和阅读文档、传递代码复审意见、消除理解分歧上耗费的时间。在本次系统实现中,我们没有对每个方法都书写非常细致的文档,只对总体设计撰写了一个粗糙的框架,不过当项目规模增大时,可能文档还是必要的,避免出现一段时间以后自己看不懂自己代码的情况。

在整体耗时几乎不会增加的前提下,结对编程得到的代码质量和可靠性却有了显著的提高。在编码过程中,队友就指出了我随手写下的一些 bug。

在具体编码的过程中,我们交替担任 ”驾驶员“ 和 ”领航员“,我从队友身上学到了一些良好的代码书写习惯。

二、项目总体设计和实现思路

先上 UML 类图:

本次作业主要抽象出 DirFile 两个类,分别管理文件夹和文件的属性和方法,此外构造自己的 MyFileSystem 类以实现官方包中的 FileSystem 接口。Dir 类不仅管理自己的基本信息,为了能够灵活进行目录间切换等功能,还需要存储一个父目录的引用变量。

算法实现上主要有一下难点和设计:

  • 目录 size 属性的计算,我们采取了缓存式的设计,避免每次访问时都需要重新递归计算,那样可能会耗费大量的时间。具体来说,就是在每次对文件进行写入、修改时,更新上层目录的大小。这里在具体实现上还要注意不能够无脑递归,否则在极限情况下会爆栈,更合理的做法应该是使用循环获取上层目录并且完成更新,这点会在压力测试 中详细阐述。
  • 绝对路径的获取:原始的设计是在每个 DirFile 中存储一个绝对路径,但是在极限深度下,会出现 JVM 堆空间不够的情况。因此,考虑在整个文件系统层面维护一个当前路径的变量,在需要输出绝对路径时,将当前路径和相对路径进行拼接即可。
  • 路径解析:构造了一个 FileSearchStatus 类,封装逐层解析时的各个状态变量。

压力测试

对于目录 size 属性的计算,尽管我们认识到了应该采用记忆化的方式存储size,但是对于 size 的更新处理非常粗糙,具体来说,某个目录大小变化时,递归更新上层目录的 size。我们采用以下测试代码对其进行压力测试:

@Test
public void pressureTest() throws FileSystemException {
    int max = 1024;
    StringBuilder path = new StringBuilder();
    for (int i = 0; i < max; i++) {
        path.append("b/");
    }
    for (int i = 0; i < 100; i++) {
        mfs.makeDirectoryRecursively(path.toString());
        mfs.changeDirectory(path.toString());
    }
    mfs.touchFile("tt");
}

在运行过程中我们发现了爆栈的现象。通过 JProfiler 粗略看出 updateSize()方法调用树层次过深。

因此我们修改更新 size 的方法,将递归更新改为循环寻找父目录并更新。我们对修改后的代码再次测试,并没有爆栈;查看调用树,可以发现已经没有 updateSize() 了。

三、PSP 表格记录

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

总体来说,编码上的进展出乎意料的快,但是后续测试修改花费了比预期多很多的时间,大体是由于撰写设计文档和设计复审阶段思考不够,对压力测试的挑战认知不清,导致后续小规模重构。此外,单元测试的经验不足也大大增加了测试耗时。

posted @ 2021-03-25 21:33  潜行的蚂蚁  阅读(110)  评论(2编辑  收藏  举报