阿拉伯人说的纳斯纳斯,亦即索马里人说的匈古夫——结对编程2
注:纳斯纳斯是阿拉伯传说里的半边人,匈古夫同理。标题暗示结对编程中两个人都发挥对等的作用且不可或缺,并且对一个事物的两种说法暗示了结对编程中两人需要通过沟通来确认彼此对同一个事物的看法。
项目 | 内容 |
---|---|
这个作业属于哪个课程 | 2021春季软件工程(罗杰 任健) |
这个作业的要求在哪里 | 作业要求 |
GitLab项目地址 | 2021_Ziming_Yang-Jingwen_Tian_pair_work |
学号后四位 | 3080 3420 |
我在这个课程的目标是 | 积累软件开发经验,提高工程能力 |
这个作业在哪个具体方面帮助我实现目标 | 体验结对编程,培养集体意识,提高开发能力 |
一、结对编程感受
这次,我们继续沿用第一次结对编程所使用的腾讯会议工具,因为它可以实现无障碍的语音交流与屏幕共享,个人感觉比两个人凑在一起看一台电脑能够达到更好的交流效果。以下是结对编程期间的截图
FROM TIAN
在本次结对编程的过程中,我们对于整个过程更加得心应手,在git同步、编程的交流上不需要像第一次那样花费许多时间,两个人的沟通质量也得到了更进一步的提高,比如第一次我还经常在思考”他为什么要这么写,这和我的习惯不一样“,从而忽略了代码正确率以及设计质量等更深一步的东西,但是第二次,我们已经可以在大部分跳过理解这步,直接进行设计上的沟通。
同样的,在对于结对编程的作用上,我也有了更进一层的真实体验。第一次的时候还会抱着“这个东西这么简单,就是麻烦了一点点,我自己也可以写的”想法,但是到了第二次,整个的体系虽然并不没有复杂多少,但是各种细节的处理上却是弯弯绕绕、令人头疼,所存在的问题也永远比发现的多,这也导致了我们花费大量的时间在测试上。这个时候,更能体现两个人结对的好处。对于所有问题的解决,都是经过我们共同讨论后的结果,这样明显能比一个人所考虑得更加全面,同时在讨论的过程中,也能进一步提高修改的正确性以及必要性。
FROM YANG
本次结对编程相比于上次的体验式,更接近于压力式(尽管这个压力式可能是指导书的全面性的缺失而导致的)。尽管本次指导书的内容较上次指导书内容较少且用户系统部分较简单,但是软、硬链接的出现,让目录树变成了目录图,mv和cp方法的出现,目录和文件在目录树中的位置不再是静态的了。这使得本次项目的边界情况多的令人发指,再加上“不再赘述”所导致的不能单纯看某指令的对应内容来编写该指令的代码,使得我在结对编程的过程中逐渐烦躁,且思路愈发混乱。好在有领航员及时帮我梳理思路,才不至于陷入泥淖无法自拔。
除了上面所说的感受,这次我们对结对编程的整体流程更加熟练,沟通效率更高,构建了了“1看指导书->2实现指令->3发现问题->4提出 issue->5解决问题->1”的 pipeline,实现了端到端的闭环流程。
二、设计实现思路
在完成本次的文件管理系统的增量开发前,我们首先对上次的设计进行了修改。一是异常抛出的位置,我们重新规定只能在MyFileSystem
和Parser
的方法中抛出异常,这样的规定能使我们的编码逻辑更加清楚,在调试的时候也不会出现忘记抛没抛出异常、在哪抛出异常的问题。二是我们重写了Parser
中的方法,更加确定了它作为解析类的作用,使其只完成解析工作且尽量解析完全。三是为了提高时间效率,我们将原来的先获取文件对象、后获取其上级目录对象的逻辑,改为先获取其上级目录对象,然后根据其目录对象直接在目录树中获取此文件对象。
对于本次的增量设计,我们了延续了上次的架构和思路,建立新的硬链接文件HardLinkEntry
类和软连接文件SoftLinkEntry
类,仍使FileSysEntry
类来作为目录类和所有文件类的父类,同时,考虑到新增要求,在其中添加统一属性(user_name、group_name、count),并使文件类的getCount
方法恒返回1。
对于硬链接和软链接的设计,我们采用”硬链接链接到文件,软链接链接到路径“的思想,分别在硬链接中存储所链接到的文件对象,在软链接中存储所链接到的绝对路径。对于它们的重定向操作,我们选择建立一个Redirectable
接口,使SoftLinkEntry
和HardLinkEntry
均需实现此接口的redirect()
方法。
此部分的UML图如下
对于redirect()
方法的实现,在硬链接中,直接返回其所链接到的文件对象;在软链接中,使用FileSysEntry
的find
方法根据其链接到的绝对路径在目录树中找到其对应的文件/目录,同时,为了在FileSysEntry
中访问目录树,我们将MyFileSystem
中存储的根目录设为公共静态变量。
同时,由于硬链接的size
实际存在,而fwrite
和fappend
会更改文件的大小,此时也应该通知链接到其的硬链接的上层目录更新size
,考虑到硬链接与文件多对一的关系,我们在文件类中新增hardLinks
列表,存储所有链接到其的硬链接,并在文件大小更新时通知列表中所有的硬链接。
对于用户系统的实现,我们新建了用户User
类和用户组Group
类,分别在用户和组类中设置公开静态root
对象,代表最初存在的root用户和其存在的主组。对于用户和组之间的多对多的关系,我们分别在User
类中存储其所在的groups
列表,在Group
类中存储其包含的users
列表,便于访问查询。
在MyUserSystem
类中,我们设置了groups
列表存储所有的已建组,同时,为了便于用户的查询,我们同样在其中存储了所有用户的users
列表。
此部分的UML图如下
对于用户系统和文件系统的交互,我们参考了issue区中所提供的方法(【讨论】用户系统和文件系统如何交互),利用单例模式,创建一个单例类Manager
,在其中设置myFileSystem
和myUserSystem
属性,在文件系统和用户系统的构造方法中分别为其赋值,这样,我们就能够通过SystemManager
在两个类中互相获取其方法/属性。同时,考虑到指令数变量的公有性,我们将其的位置也由FileSystem
改到了SystemManager
中,便于两个系统的调用。
这样,对于exit
命令中的获取上一次su
命令时用户所在的工作目录需求,我们就可以在进行su
操作时通过SystemManager
中的myFilesystem
获取当前工作目录的绝对路径,进行存储,并在执行exit
命令时,更新myFileSystem
中的当前工作目录。
同样的,对于文件系统中新建文件/目录时,需要的当前用户和其所在用户组的信息,也可以通过SystemManager
中的myUserSystem
获得。
此部分的UML图如下
对于异常的设置,为了设计架构的清晰性、便于调试,我们将过程中可能出现的异常做了区分,并对第一次的异常情况进行了适当调整,最后区分为MyFileSystemException
和MyUserSystemException
,分别继承课程组给出的异常抽象FileSystemException
类和UserSystemExceotion
类。
最终架构如下
三、PSP表格记录
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
· Estimate | · 估计这个任务需要多少时间 | 30 | 30 |
Development | 开发 | 770 | 1250 |
· Analysis | · 需求分析 (包括学习新技术) | 30 | 20 |
· Design Spec | · 生成设计文档 | 30 | 30 |
· Design Review | · 设计复审 (和同事审核设计文档) | 50 | 60 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 0 | 0 |
· Design | · 具体设计 | 60 | 120 |
· Coding | · 具体编码 | 360 | 360 |
· Code Review | · 代码复审 | 60 | 90 |
· Test | · 测试(自我测试,修改代码,提交修改) | 180 | 570 |
Reporting | 报告 | 90 | 110 |
· Test Report | · 测试报告 | 30 | 30 |
· Size Measurement | · 计算工作量 | 30 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 30 | 60 |
合计 | 890 | 1390 |