结对编程#3
结对编程#3
项目 | 内容 |
---|---|
课程 | 2021春季软件工程(罗杰 任健) |
GitLab项目地址 | 项目地址 |
队员1学号 | 3567 |
队员2学号 | 3018 |
结对项目实践反思
针对前面两个阶段中出现的问题,分析问题的特征、产生的根源和对质量的影响程度;
-
第一阶段的作业较为简单,架构以及所实现的功能都不是非常复杂,在和队友一起浏览指导书并且迅速分配任务后就开始埋头编码了,分头行动的效率还是挺高的,因此产生问题的部分是代码合并期间,有以下几个问题。
-
可读性。分头行动产生的代码可以说不算是结对编程的成果,除了大致的框架一致外,队友之间的代码风格差异很大,导致在合并选手工作时,由于一定程度的强迫症和对oo代码风格进行传承的执念进行了大规模的重构,除了基本的命名、空格符合规范外,对一些方法也进行了修改,(或许)降低了耦合度,代码风格不同导致的代码可读性较差问题只需要找到合适的标准进行规范即可,问题产生的根源还是队友之间对代码风格没有提前的商量,这也表明这个问题很容易被忽视,当修改完毕后代码的可读性明显增强,质量也有所提高。
-
需求分析工作不足,bug太多导致测试时间较长。在进行代码合并时由于进行了重构,导致原先处理的细节以及实现的功能被ljj同学懵懵懂懂地忽略了,在合并之后接踵而至的便是bug的修复,而bug实在是太多了,例如需要补充对
.
、..
、/
、file/
云云特殊情况的处理,在lxy同学精准的测试下逐个击破。产生这么多细节上的问题,产生的根源是对指导书的理解不够清晰,在结对编程的过程中,我们解决问题的方式是等待问题的出现,再经过讨论去达成一致,这样的方式造成我们在遇到极其简单的问题时也花费了一部分精力来讨论,而这是没有必要且降低效率的。
-
-
第二阶段的作业架构突然复杂了起来,不仅要修改第一阶段遗留的原子性问题,还增加了令人摸不着头脑的链接文件,我们在任务分配完毕后,花了很多时间在指导书的分析上,在issue区还未成长的时候,ljj同学一度处于😵以及极度恐惧的状态,不过好在迭代开发并不困难,在盲目对照指导书实现了基本功能后,尝试性地WA了弱测的部分测试点,然而接下来bug修复的过程是十分痛苦的,究其根本是心态问题。
-
ljj同学经历了一天一夜(大概)的黑暗时光,在不断发现bug并修复bug的过程中,细节不断被完善,但是在最后仍然过不了WA了的那俩测试点,于是我们逐渐萌生了一个黑暗的想法:放弃弱测。然而,虽然嘴上说算了算了,我们仍然在不断尝试(
尝试寻求助教学长的帮助),仔细看issue,重新读指导书,根据WA的原因是行数过多推测出产生了多余的异常或报错,最后还是没能顺利解决问题。但在这个时候,ljj同学的背后传来了神的声音,是my!于是ljj同学在my的帮助下一起分析,三下五除二恰好就测出了WA的两个bug,ljj同学也以迅雷不及掩耳之势跟lxy同学商讨并把bug修复了(直到他走进梦乡都能听见他口中不断说着一句话:my,我的超人!)。 -
心态问题是极其可怕的,面对一个困难,最容易的选择就是放弃,当队伍成员都试图放弃,就不可能完成任务。而这次问题产生的根源不是由于困难不可克服,而是我们缺乏心态的调整,在自闭的气氛中我们没有足够地去鼓励对方,形成团队,而是各自埋头测试,改进代码质量,缺少沟通的情况下,很难找到代码的锅到底在哪,形成恶性循环。不过好在我们都坚持了下来,成为了ddl选手,在截止前终于达成了目标。
-
总结结对项目中的需求分析实践体会,并分析哪些bug是因为需求分析不足而带来的;
我们两次作业的需求分析都十分粗糙,或许是因为我们都比较倾向于在实践的过程中解决问题,而忽视了通过需求分析来避免一些简单的问题。在结对项目的需求分析过程中,我们主要是通过阅读指导书来明确一个目标,具体的细节都是在编码过程中再考虑,产生如链接文件的modifyTime
错误、忽略路径长度最大限制、特殊目录的处理、file/
类型等bug。
总结结对中的架构设计实践体会,描述通过改进设计来提高程序的性能改进的思路和方法,并分析哪些bug是因为架构设计不足(特别的,需求变化)而触发的bug;
在架构设计的过程中,我们首先统一了基本类的声明、使用树的数据结构、设计部分常使用的基本方法等。
阶段一我们实现了文件类、目录类,都是以名字来查询而非绝对路径,而路径的解析都在文件系统类通过 find
型方法实现。在设计的改进上,主要体现于目录大小的计算,我们从起初的询问时再递归计算,更改为每次改变即递归修改的大小计算方法,这样极大地提高了size
的计算效率。
在通过路径寻找目标文件或目录时,我们设计了两种常用的find
型方法,找到目标目录findDir
以及找到目标目录或文件的上层目录findDirThatHasDirOrFile
,这两个方法在我们的迭代过程中进行了改进,并且使用频率极高,在编码的过程中善于使用这两个方法,可以极大地提高编码效率,并且不容易出错。
无论是在Dir
类还是在File
类中,我们都提倡方法的嵌套,降低代码的耦合度,以及提高代码的复用性。在阶段二中,我们没有额外增加链接文件类,而是在文件类中增加linkflag
来判断文件类型,并根据文件是软链接、硬链接或普通文件类型来创建方法的分支,在测试与debug过程中也很容易发现错误。但是,这也导致修改较为繁琐,一个错误需要对每个方法的分支都进行检查与修改,容易出现遗漏造成新的bug。
当需求变化时,需要做到对架构十分清楚,否则在增加需求时容易忽视细节,导致这也是架构设计过于复杂的弊端。我们使用了较多方法,也定义了很多属性,有些是为了修复bug而盲目增加的,而没有经过仔细的设计与分析,在增加链接文件后,路径的get
方法有两种,而在修改时并未考虑之前的调用是否合理,在之后需要get
路径时也忽视了使用哪种才是正确的,于是随意调用,导致路径错误、抛出异常等bug。
总结结对过程中的进度、质量和沟通管理实践体会,并分析哪些bug是因为两个人的理解不一致而导致;
对于进度管理,我们在每一次开始编码之前都会协商一个进度规划。下面是我们两次作业的PSP以及进度规划。
PSP2.1 | Personal Software Process Stages | 第一次预估耗时(分钟) | 第一次实际耗时(分钟) | 第二次预估耗时(分钟) | 第二次实际耗时(分钟) |
---|---|---|---|---|---|
Planning | 计划 | ||||
Estimate | 估计这个任务需要多长时间 | 10 | 10 | 10 | 10 |
Development | 开发 | ||||
Analysis | 需求分析(包括学习新技术) | 40 | 70 | 50 | 80 |
Design Spec | 生成设计文档 | 30 | 25 | 30 | 25 |
Design Review | 设计复审(和同事审核设计文档) | 20 | 20 | 20 | 20 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 30 | 40 | 10 | 10 |
Design | 具体设计 | 90 | 120 | 90 | 120 |
Coding | 具体编码 | 360 | 480 | 600 | 480 |
Code Review | 代码复审 | 60 | 120 | 300 | 540 |
Test | 测试(自我测试,修改代码,提交修改) | 180 | 300 | 480 | 600 |
Reporting | 报告 | ||||
Test Report | 测试报告 | 30 | 30 | 30 | 30 |
Size Measurement | 计算工作量 | 15 | 15 | 15 | 15 |
Postmortem&Process Improvement Plan | 事后总结,并提出过程改进计划 | 20 | 25 | 20 | 30 |
合计 | 885 | 1255 | 1655 | 2320 |
第一次作业 | 第二次作业 | |
---|---|---|
编码 | 2天 | 3天 |
弱测+单元测试 | 1天 | 1天 |
强测+博客 | 2天 | 1天 |
这样的进度规划是在我们实现了框架构思后,根据编码难度、作业目标等情况共同协商确定的。第一次作业编码难度较低,所以编码时间短,而预留给强测的时间长,希望可以减少代码的bug;第二次作业编码难度大,所以编码时间长,而牺牲了一些强测时间。通过这个项目,我感受到一个合理的进度规划可以合理安排时间,可以起到良好的督促作用,还可以让两个人的工作同步起来,减少很多麻烦。
代码质量方面,我们非常注重代码风格的规范,同时单元测试以及CI支持的回归测试也在很大程度上帮助我们提升代码质量。在代码初步编写结束后我们会有同伴复审,这样可以有效避免在理解题目时的思维惯性或是个人编码习惯导致的错误。
在沟通方面,一开始场所、时间等方面限制对我们的沟通影响挺大的,所以我们选择了多种线上途径进行交流,同时保持着在架构构思阶段的线下交流,在线上线下的沟通中找到平衡。同时,代码也是一种很好的沟通工具,代码命名规范、注释清楚都在很大程度上帮助我们看懂对方的代码和意图。
在代码架构方面在前期有充分的沟通,两个人理解不一致导致的bug主要体现在一些处理细节上,有对路径字符串的处理、特殊目录./..的处理。这些bug在代码合并的时候被发现,然后我们会及时沟通,统一一种思路。
提出建议:根据三个阶段的结对项目的实践经验,对如何更好的实施和管理结对项目提出自己的建议。
- 每个人在写代码的时候都应该注意代码规范,降低代码耦合度,写清注释,commit时写清更改内容
- 结合团队各个队员的实际情况做好合理的时间规划,可以利用PSP等方式
- 认真对待代码复审,因为真的能找出很多不足的地方
CI体验感想
通过这两次结对编程,初步了解和使用了CI。我们利用CI实现了自动化测试,每次提交代码都可以自动执行代码中的单元测试,在我们专注于更新功能而没有对更改后的代码进行全面测试时,可以起到一个自动”回归测试“的效果。除了实现CI的一些基础功能,我们还增加了在issue看到的在CI中使用maven cobertura进行覆盖率的检查,并将覆盖率结果用artifacts导出,my的issue真是太棒啦。
总体来说,虽然在编写yml文件时遇到一些麻烦,但是在单元测试和提交代码中也感受到了极大的便利性,希望在团队项目中可以用到一些更高级的功能。
结对编程感想
描述你们结对的方法、结对过程中遇到的困难与收获,结合自己的结对经历,说明结对编程的优点和缺点,分享可以推广的结对妙招。
评价你的队友,使用汉堡点评法评价你的结对伙伴,务必给TA 提改进意见。
lxy:我和ljj同学算是互补型的队友,无论是对整个题目还是对某个问题,他都可以很快的理清思路,提出一个方案,也很热心为一片混沌的我讲解思路。同时,他的代码写的非常规范,变量、函数都使用驼峰命名,并且命名非常清楚,基本可以从命名中推出变量或者函数的用途,并且代码的耦合度很低,反而我因为之前都是单人作业,本着”自己看懂就可“的原则,代码风格非常随意,ljj同学也很热心的帮我修改代码,在两次作业中,我也在慢慢学习了ljj同学的代码风格。
但是,ljj同学敏捷的思维和编码也会导致一些细节方面的不足,有时候在实际编码时没有考虑到算法的时间成本和代码优化。在沟通方面,希望队友可以注意及时的反馈,有时候队友已经完成了但是没有跟我说,我就会以为队友还在做,会产生很多等待时间。
总体来说,我和队友的合作还是非常顺利和愉快的,还算顺利的完成了这次魔鬼作业,我也从我的队友身上学到了一些自身不足的地方。
ljj:和lxy同学合作的过程十分顺利,lxy同学的学习态度极其认真,工作也十分靠谱。她能够合理地安排时间、分配任务,让我体会到了时间观念的重要性。并且,lxy同学对于细节的处理特别到位,每次测试的过程中她都能够找出许多我的代码的不足之处,让我受益良多,还提出了静态存储目录大小的改进方式,提高了代码性能。
lxy同学的代码风格个性十足,合并过程的修改有些麻烦,不过之后就调整了,可读性好了很多。
总的来说,在这次结对编程中收获了许多,也领会到了不足,结果还是顺利的,坚持就是胜利!
描述在本次结对编程的过程中,你们使用了哪些软件工具,是如何应用于实践的
maven是一款很好用的Java项目管理工具,用maven分开管理源代码和测试代码,编写pom.xml用来实现对于Junit的项目依赖,用于管理源代码、配置文件,以及开发者的信息等。
单元测试使用Junit4,在本地用IDEA自带的功能测试覆盖率,在CI中用cobertura测试覆盖率。
用git实现版本控制,实现版本管理以及两个人之间代码的同步。
描述通过本次结对编程的感悟和体会,对本次作业的有哪些想吐槽的,觉得本次结对作业内容可以在哪些方面做出改进?
通过这次结对编程,体验到一种新的团队合作模式,思路、编码速度、代码准确率、代码风格等方面确实提高了不少,但是由于时间、场地的限制,并没有实现真正意义上的结对编程,所以我认为课程组可以再考虑一些别的形式来让同学们体验结对编程。
指导书的描述要是能够直观一些就好了,一些例如“不再赘述”等描述不作省略,以及“覆盖”、“视作修改一次”如果能够明确定义并且明确会改变哪些变量就更好了。