【老物】再探,结对编程! (下)

项目 内容
这个作业属于哪个课程 2021春季计算机学院软件工程(罗杰 任健)
这个作业的要求在哪里 结对项目-第三阶段
我们在这个课程的目标是 和团队开发真正的软件,一起提升开发与合作的能力
这个作业在哪个具体方面帮助我们实现目标 通过结对编程学习协作设计与编码、代码复审、CI使用等
成员介绍
项目 内容
结对项目第一阶段的Gitlab仓库地址 Pair Programming
二人的学号后四位
博客地址 MadokaHomura(朱正阳), zixfy(赵子轩)
前情回顾

初见,结对编程!(上)

磨练,结对编程! (中)

一、结对项目实践反思

1.问题分析

针对前面两个阶段中出现的问题,分析问题的特征、产生的根源和对质量的影响程度

测试的不充分

在第一阶段的测试中,过分地追求代码测试的覆盖率,然而忽略了单元测试的局限性,即1. Junit对于你应该写而没有写的代码是无能为力,测不出来的。2. 当前某一条语句被测试代码覆盖了,并不代表这条语句对应的行为逻辑是完备的,你可能忽略掉输入数据为极端数据的情况而不知情。第一阶段中产生的几个bug皆源自此类原因,说明我们测试的片面与朴素。在第二阶段中,指导书部分指令的语义复杂程度很高,要求比较繁多,因此捋清指导书需求并对每个分支展开测试其实成了一大挑战,此阶段中产生的唯二Bug出于一种异常错误信息的格式错误与一个两人对指导书mv/cp覆盖文件时共同的理解偏差,因此在代码变得有些复杂时考虑程序所要处理的各种边边角角的情况其实也变成了一个挑战

2.需求分析

总结结对项目中的需求分析实践体会,并分析哪些bug是因为需求分析不足而带来的

这两阶段的需求分析严格意义上来说是分析指导书要求实现的功能。需求分析对于编程和测试都是起决定作用,重要性不言而喻。但是在这两阶段两人都是在简单通读指导书,理解指导书的大致内容之后便进行了架构设计,开始编码。这导致编码与需求分析实际上是在同步进行的,对需求的不完全分析也导致了后期的许多修改,编码效率下降。

例如第二阶段对于mv/cp中对于“覆盖”的理解既成为了实际开发中纠结的地方,也在强测中出现了问题。尽管#issue35中在最后有同学提出了疑问并得到了助教的解答,但由于此时已经是结束的前一天晚上,第二阶段项目已经进入收尾阶段(当天下午我们进行了对issue区提到的各种情况进行了测试),这个讨论就被两个人都忽视掉了。

其实这也引发了我的思考:要怎样才能在需求分析阶段就能及时检查自己对于需求的理解是否是正确的呢?此次的指导书相较于真实的需求分析,对于需求的要求是相对明确的,但是实际的需求分析不确定性更高~~(甲方奇妙的“五彩斑斓的黑”)~~此时需求分析有绝对的标准吗?怎样才能更好的进行需求分析?

3.架构设计

总结结对中的架构设计实践体会,描述通过改进设计来提高程序的性能改进的思路和方法,并分析哪些bug是因为架构设计不足(特别的,需求变化)而触发的bug

架构方面第一阶段中的文件系统实现的完全是物理意义上的文件系统,即文件内容
与单个文件一一对应,但此设计多处于自身的感性认知,导致此架构设计缺乏深入的调研与复审,在第二阶段遇到新的需求(软硬连接时)无法快速优雅地进行增量开发

因此在第二阶段中,我们对于linux文件系统模型进行了一定程度上的调研与分析,在上述架构的基础之上进行了修改,根据"一切皆文件"的核心思想将文件间的逻辑关系信息与管理内容解耦开,将各功能模块的功能清晰划分如下

幸运地是,没有遇到过因为架构设计不足而产生的bug,但由于从架构一到架构二的转变并不平滑,这其中牵扯出一些第一阶段中没有深入思考的具体细节问题,它们在阶段二最后进行mv/cp功能开发时爆发出来,(详见相关博文2、3楼),在最后发布时,代码实际是未经过重构的版本,因为当时弱测已通过,再次变更代码有一定风险

至于架构引发的Bug,其实也没有啦..一二阶段强测产生的Bug都出在逻辑细节上

关于改进设计来提高程序的性能改进的思路和方法,上文UML图中未包括PathManager,一种我们在第一阶段设计的解析路径的迭代器,事实证明这个工具类解耦得比较成功,它只负责路径格式解析而与文件系统无关。而且作为迭代器得设计使它可以灵活复用于mkdir -p/ln等索引文件方式有区别得指令中,而且迭代器不用在可能产生异常时完全解析完路径,降低了程序复杂度

另一个主要的优化方向是避免递归,有两个可能产生递归操作的地方:1.删除目录时 2.移动目录时 都可能需要递归更新子目录/文件相关的属性。我们使用了懒更新策略,删除目录时可能需要递归解除所有硬链接(普通文件)同inode的链接,但我们考虑到在本文件系统中删除操作是永久删除,因此在删除目录时仅设置其父目录为null

同时我们在文件内容更新时遍历每一个与其链接的硬链接,每个硬链接自底向上更新,若在抵达根目录之前遇到null则说明此文件在之前已被删除,此时再解除硬链接同inode与文件内容的链接,这样复杂度理论上会小于等于暴力递归删除

同时牟哥提到可以给目录/文件加时间戳来在移动目录时懒更新文件修改时间,但是我们考虑到绝对/相对路径处理比较麻烦,故在第三阶段没有进行类似的优化(摸了)

还有上篇总结中提到的不存储绝对路径,这样使得程序不需要额外考虑指令操作对路径的影响,而且一条指令至多输出一条真实的绝对路径,因此不存储绝对路径程序总复杂度也不见得会更高

4.进度、质量与沟通管理

总结结对过程中的进度、质量和沟通管理实践体会,并分析哪些哪些bug是因为两个人的理解不一致而导致

  • 进度管理:
    进度管理这方面在整个结对编程过程中做的都不算太好。由于指导书的不断更改以及对项目难度的把握不足,在实际开发过程大部分精力投入在开发中,进度管理缺乏投入,很难保持预期进度。而且结对过程中一个主要问题是时间的碎片化,我们只有周一有相对长的时间进行结对,其他时间段被课程分割,以致有时还需线上交流,一定程度上影响了进度跟进。不过我们也会在每日结束时进行一次总结,既保证进度不会太慢,又方便下一次的编程不会遗忘一些历史问题。

  • 质量管理:
    每一阶段代码在初步写完时都会进行单元测试、回归测试以及代码复审来保证代码的质量,同时在完成代码覆盖率测试后也会展开特殊输入数据的测试。遇到一些问题时也会选择进行局部重构来保证代码的鲁棒性。

  • 沟通管理:
    整个结对编程过程中,基本都是在线下进行的,沟通无障碍。同时也利用Code with me中“follow me/full sync”的功能更快地定位交流对象的位置,减少了不必要的沟通时间花销

由于线下交流时间长,许多步骤都是经过两人多次交流确认之后才进行的开发,因此没有出现因为两个人理解不一致而导致bug,但因此也确实存在两人理解一致的bug(笑)。

5.建议

提出建议:根据三个阶段的结对项目的实践经验,对如何更好的实施和管理结对项目提出自己的建议

  • 需求分析阶段的交流是必要的,一个人很容易看漏一些需求,而两个人相互交流能解决很多理解上的问题两人都理解错了怎么办
  • 合理利用一些软件帮助实施和管理结对项目(例如Code with me以及助教在第一阶段博客中提到的gitlabmilestonesIssues功能等)
  • 在两人出现分歧的时候,不要陷入死循环,理性地、有理有据地说服对方能提升开发效率

二、CI体验感想

通过这次结对编程,你对CI的使用体验如何?你对这一工具有何认识?

通过这次结对编程,实际上我们还是对CI进行了真正的入门吧,虽然我们作业中使用的yaml脚本比较简单,只有编译、测试(再次感谢牟哥的配置神贴)与提交或者查分这几个固定的操作,但使用CI后首先可以对一版代码进行自动化的测试以及可能的部署,其次可以增强团队成员对代码的知情权,了解到当前代码的质量,及时进行复审。CI还有milestone/issue跟进进度的功能,milestone适用于定期进行集成,并发布阶段的新版本,这一功能或许在后续团队敏捷开发中会很实用

三、结对编程感想

1.结对形式

描述你们结对的方法、结对过程中遇到的困难与收获,结合自己的结对经历,说明结对编程的优点和缺点,分享可以推广的结对妙招。

我们结对时绝大多数时间是线下一起进行编程,结对场地包括wings,新北超商还有学六食堂

zzy:

我遇到的最大的困难其实是如何说服自己与队友进行“平等的交流”。在最初接触zzx的时候,我就意识到了自己与zzx之间各方面的差距,欣喜 ~~(能抱大腿)~~的同时,更多的是一种无力以及愧疚感,这种负面情感让我在最初的时候只会点头同意,没有提出任何建设性的建议。第二阶段身份互换之后,才逐渐放开自己。(感谢不嫌弃我的zzx)

我的收获同样也有很多。认识了一个很棒的队友;之前从来不敢再issue区发声的我首次发声提问(总是害怕是自己看的不够仔细,或者想着等待他人提问);以及对于架构设计和测试的全新认识;首次使用maven以及Code with me等都是很好的体验与收获。

对于结对编程的评价

  • 优点:
    • 是团队项目之前一次很好的预热,提前体验了与他人共同完成一次开发的全过程
    • 两人之间的交流相比团队能够更加充分
    • 两人相互辅助,能在一定程度上减少错误发生的概率
  • 缺点:
    • 实际效率不一定大于1+1
    • 两人之间的磨合需要时间
zzx:

虽然说阶段三如果还有迭代开发任务的话,我可能会肝死罢,但我还是想再结对一次啊。没能完整做完这个小项目其实有些可惜,我们的架构刚经过重构比较清晰了,我与zzy快要走完结对的磨合阶段了。啊啊啊好像证明我们可以出色完成用户权限相关的开发啊。

关于结对编程本身,我还是不能肯定它的性价比有多高,只能说合作得越久,两人开发的效率才可能更高吧。要说结对的推广,建议课程组大力安利一下Code with Me,这么适合结对的工具我们早了解到就好了

2.互评

评价你的队友,使用汉堡点评法评价你的结对伙伴,务必给TA 提改进意见。

zzy To zzx

能力很强,对于架构设计、编码、测试等态度也很认真;交流态度很好,也不嫌弃菜鸡的我;有时有些自谦过度,给我一种妄自菲薄的感觉,但是实际交流问题的时候很自信。总之是一名非常可靠的队友!

zzx To zzy

就像我在个人博客中所说的,我本人其实具有相当鲁莽的编码风格,喜欢边敲代码边想思路(老重构怪了)。但zzy相对我而言就是那种比较喜欢多思考,做事交流比较严谨,二人可以说是有种森林冰火人的感觉(?)。zzy比我更能考虑到细节与编码背后可能带来的问题,感谢他在第二阶段中一步步帮懵圈的我理清了新需求的N中抛异常的情况、提出无数代码中的细节问题等等等.. 其次一点zzy对待工作真的很认真,结对过程中从没有向我显露过疲态,实际上每天都是我想摸了的时候才会提醒他收工,做事相当踏实仔细。

我对zzy的改进意见是可以在以后的coop中都可以更加从容地显示与发挥自身的能力,同时可以坦诚指出同伴的不足啊。或也有我的问题,在这次结对中因为我的带点表现欲的主动,其实我在交流中一直在抢占话语权,甚至显得有些咄咄逼人。但实际上我与zzy的实力相近,而且我的一些想法与代码也没有zzy那样周全,我也为我在第一阶段近乎垄断了整体架构思路感到错了,事实证明那是个失败的设计😂 。zzy完全可以相信自己的实力,思路慎密,学习能力也比较强,做起精细的工作肯定是分靠谱,加油!

3.开发工具

描述在本次结对编程的过程中,你们使用了哪些软件工具,是如何应用于实践的。

具体使用工具:

  1. Code With me:在第二阶段的结对中引入了JetBrainsIDE自支持的Code With Me,一款用于在线协作编辑、运行、测试代码的插件。相比于git,Code With Me在协作中的实时性更强,更方便不同模块的同时编写与代码复审
  2. Maven/Junit4.12:Maven用于整个项目的管理与配置,同时我们使用Junit同时进行单元测试与集成测试
  3. Jacoco: Jacoco类似于Cobetura,需要配合JunitMaven使用,可以统计代码的行数覆盖率与分支覆盖率(精确到语句级),为一次测试自动生成网页或csv形式的测试报告
  4. Git Bash/Ubuntu 16.04:第二阶段中涉及到了Ubuntu相关指令执行的细节,因此我们在Linux环境下展开了相关的实验,对于较为模糊的情况,先在Linux环境下复现一遍,并比较与指导书的异同之处
  5. Processon/HedgeDoc: 文字相关工作中所用的工具,前者为常用的在线协作绘图工具,后者是一个便捷的在线协作编辑markdown的网站,我们用于博问的撰写

4.吐槽与建议

描述通过本次结对编程的感悟和体会,对本次作业的有哪些想吐槽的,觉得本次结对作业内容可以在哪些方面做出改进?

  • 指导书的部分已经有很多同学吐槽过了,确实由于指导书里的一些问题我们也吃了很多苦头
  • 其次是对于issue区的管理。尽管助教在最后发了一个总结帖来总结各个issue的内容,但是整个issue区管理上还是比较乱,获取有用信息的效率不高