这是一个填坑博客,负责把之前挖坑博客里面所挖的坑填满,以及一个学习软件工程课的心得。
项目 | 内容 |
---|---|
课程:北航2020春软件工程 | 博客园班级博客 |
作业:提问回顾与个人总结 | 提问回顾与个人总结 |
提问博客 | 软工个人博客作业1 |
疑问解答
问题一:测试
在之前的面向对象设计的课程中,我初步地尝试了使用JUnit对自己的单元进行测试。但是对于测试的对象、粒度和测试的样例数据,我还是不能很好的把握。测试的粒度可以从小到大,从函数、方法到类再到模块,循序渐进。但是测试的样例数据方面,是否存在比较合理而且固定的方法,能够固定地按照一个流程去分析自己的应用,做到不重不漏,覆盖到所有的分支和情况?还是说单纯依靠代码的编写者去“我觉得,这个地方可能存在问题”这样的直觉和经验呢?
覆盖所有分支肯定是不太可能的,每个模块的输入和输出变化非常大,这也是为什么说“测试需要写代码的人做”的原因。但是其中我们当然可以使用一些工具比如分支覆盖率工具,在给定输入的情况下检查代码的覆盖率。在结对编程和团队工作的过程中,我的测试方法主要分为两种:
- 人工制造数据,分别检测“一般情况”和“边界情况”,并同时利用分支覆盖率工具来检查代码的正确性
- 通过随机生成函数,批量制造随机输入数据和对应的期望输出,然后挂机让电脑自己测试
问题二:结对分配
过程中,我想知道结对编程过程中,是否会发生两者的贡献不匹配的情况。作为领航员,工作较为多元但是在代码数量方面的贡献不如驾驶员大,是否会出现领航员碌碌无为的情况?领航员在工作中更多是提出问题的一方,单从审阅文档进度、考虑测试覆盖的角度来看,领航员和甲方的区别在哪里?
其实不会。结对编程的过程中,不是说领航员吃干饭,在工作时必须对驾驶员的代码进行审查和思考,及时发现可能的错误。工作的贡献度也不能只通过代码量来体现,bug发现、文档等都可以算工作量,加上这些的话其实领航员的负担并不比驾驶员要轻。
领航员在二人的工作中,并不能算是甲方,两者差别还是非常大的。领航员需要深入实现细节,并同时检查软件是否符合需求,相当于代码和甲方的中间人,需要兼顾上下级。
问题三:敏捷团队
看完这一段,我越来越觉得敏捷开发对于团队的要求是很高的。不仅仅是团队成员各自的优势长处要互补,覆盖组织、研发、开发、测试、审查等各个方面,而且团队的熟练度必须很高,经历过一段时间的磨合;团队成员各自的积极性也要得到保证。没有这样的团队,很有可能会出现某个任务无人认领、每日例会浮于形式、工作效率不达标等现象。所以敏捷开发的效率似乎并不一定比按其他开发思想的效率高?同时考虑到需求的不断变动性,敏捷的乙方似乎会为了不断地满足甲方而承担更多的工作量?
团队最重要的一点是凝聚力,即大伙都想把软件做好。有了这样的出发点,组织、研发、开发、测试、审查等各个方面都是人人关心的,自然也会有人想把它做好。某个任务无人认领的情况其实很好办,大家为了绩效肯定会先抢简单的做,剩下的需要PM对有能力者进行强制分配即可。个人感觉每日例会浮于形式的情况在敏捷团队中出现概率不大,因为小团体相对来说人际关系更加紧密,小部门的工作粒度也更小,各自部门的工作和问题非常容易得到汇报和暴露,团队间的信息沟通其实是非常细微而且频繁的,例会一定有干货可讲,而整体工作进度和部门间的协调则需要PM把握和控制。
问题四:新人
在一个团队中,肯定有熟练者和不熟练者,因为最后采取的方案和开发工具很可能并不是所有人都熟悉的,同样的任务熟练者很快完成,但初学者需要花费很多时间来熟悉。那么作为一个PM,遇到这样的矛盾,如何去安排工作,使得初学者也能够得到认同和满足?
这就涉及到工作分配的粒度问题。如果PM把项目一股脑泼在新人头上,新人肯定不想去看,项目太大而自己却毫无头绪。这时候需要工作的细粒度就很重要,越细的粒度对新人来说就越容易。将小任务分配给新人,并且提供一些类似的材料供其模仿,比如前端需要实现一个按钮及其点击后的操作,PM或者熟练者可以将一个已有的实现提供给新人供其模仿,既能避免熟练者花费过多时间在重复劳动上,也能让新人在学习知识的同时有归属感。以前在做项目的时候并没有意识到小粒度工作的重要性,总是喜欢把一大堆东西都丢给新人,期望他们能够静下心一点一点读,结果却是新人压力巨大,进度缓慢。
问题五:bug负责人
在实际的运行过程中,用户可能会反映很多不同类型的bug,但是用户对于bug的描述肯定不会非常全面具体。那么此时,在这样一个背景下,是谁负责去复现这个bug并试图找出原因? 如果遇到用户说不清道不明的情况(现实中常常会遇到),是否只有通过地毯式排查才能复现bug?
在我们团队的工作中,遇到bug反馈时, 是由相关的直接负责人进行负责,复现这个bug并试图找出原因,比如该功能的实现者或者最近的修改者。遇到用户说不清道不明的情况,则需要通过PM来进行沟通来确定可能的问题根源。
问题6:merge冲突
在多个成员并行开发的过程中,可能遇到需要合并分支的情况(merge),那么在合并的时候如果发生了冲突,是否需要两个人都在场以便沟通冲突的部分如何取舍?我在之前的合作作业中,也经常遇到merge冲突的情况,当时我是通过回避冲突部分,把冲突部分单独另外提交的方式来规避问题;但是遇到对对方代码不熟悉的情况下,我如何去统一冲突呢?
如果工作的粒度足够细的话,出现严重冲突的概率是非常小的,因为每个人都异步地进行着自己的工作,对代码的修改是局部的。在小粒度工作分配中,出现冲突的主要是对共享的代码进行的修改,这种涉及全局的代码修改需要经过更加严格的审查,以确保通过迭代测试,此时就必须双方或者多方负责人进行检查;当然这种对局部代码的修改影响到全局的情况需要尽量避免。所以为了减少merge冲突,需要将任务划分得足够细,并将类似的工作交付给同一个人完成,以确保代码逻辑上的一致性。
学习到的新知识
需求阶段
需求阶段分析了项目的NABCD,主要是学习了如何具体分析需求、做法、好处、竞争、推广。一个软件的成功必须有明确的目标人群,可能是将软件用的很“专”的一个小众群体,也可能是对功能需求越来越大的口味越来越挑剔的大众人群。切中目标人群的痛点,是一个软件拥有用户基础的前提。
设计阶段
我在第一个团队里,扮演了策划的决策,在确定了做游戏之后,对游戏的主题进行了多方面的比较。在小组头脑风暴中,将不同游戏主题的优缺点列出来,找到每个主题的核心竞争力和致命缺陷,通过末位淘汰的方式选择最终主题。在这个过程中,尝试了采用末位淘汰的方式筛选出最佳的方案,最终效果很不错,能够得到一个令所有成员都相对满意的选择。
设计阶段是集众人之所长的阶段。在头脑风暴中,我不断地整合不同成员的想法,捕捉他们点子中令人眼前一亮的地方。同时也需要大量地体验市面上已有的类似产品,将其作为模板,将其优秀的地方吸收进自己的设计中,通过大量借鉴学习充实自己的设计方案,并且不断地与代码编写人员交流,确保其可行性。这个阶段主要学习到的是对产品优缺点的提炼和信息的整合能力。
实现阶段
在第二个团队中,我担负起了前端的开发工作。在实现过程中,学习到的更多是技术栈,尤其积累了很多css的样式。为了实现一些特殊的效果,我花费了一些时间和css作斗争,在层级嵌套和继承这两块地方给自己挖了很多坑,又花费不少时间爬出来。为了在不使用插件的前提下实现前后端的交互,还研究了通信的底层异步逻辑及数据缓存的机制。总的来说,实现阶段大部分的知识是技术方面的。
测试阶段
第二个团队中,我学会了使用tslint进行规范typescript的代码和使用enzyme进行react测试。以前我以为前端的测试只是进行地毯式地检查功能的正常运作,但是有了enzyme的帮助之后,业务逻辑方面的测试可以更加深入和彻底。
发布阶段
使用hook将代码自动同步到服务器以实现敏捷发布,在个人的体验中,是一种有效而且方便的手段,同时也便于软件快速的迭代。
维护阶段
维护阶段主要是出现了几次紧急的bug,需要马上修复,其主要原因还是由于服务器网络连接不稳定。在这个过程中,我了解了一个简洁的bug描述的格式以及学习了快速定位bug原因的经验,基本上能够在初次发现bug的半个小时内解决问题。
心得
相比个人项目和结对项目,两个团队项目给我带来了更丰富的体验和经历。在第一个项目组中,我担任的是游戏策划,因此把绝大多数的时间用在了同类游戏分析和具体关卡设计上,甚至都不太能算得上是典型的“软件工程”。针对儿童编程游戏的几大要点:简洁的画风、活泼的人物、吸引人的机制设计、编程思想的提取、循序渐进的教程、向标准化编程的引导,我从大量的同类作品中汲取灵感,同时进行再创造和整合;工作看似轻松,但却需要大量的时间来思考游戏的核心竞争力在哪里。这份工作,摆脱了编码的束缚,体验了一次全新的职业,让我认识到了团队领航员的重要性,同时让我有精力去对小组的代码质量、提交规范进行监督。同时在项目组中,体会到了很多以往没有遇到过的问题,比如项目仓库超载、素材匮乏、成员伤退等意外情况,提高了自己对意外情况的抗风险能力。
第二份工作接触的就全是代码了。最大的感受就是在面对微软OCR-Form-Tools这样一个项目的时候,体会到了前端的另一种写法。微软的这种写法更加复杂,但是也更加规范和整齐,大量的接口规范了每一个模块的输入输出和内部变量,使用工厂来规范化地创建对象,使用enzyme进行前端的模拟操作和业务逻辑测试……有种成熟项目的稳重感和充实感。这份工作给我带来最大的改变就是代码风格:更加喜欢使用大量的接口,更加喜欢使用类而不是函数,更加喜欢将东西封装地妥妥当当,更加喜欢在核心代码的基础上增加测试增加辅助代码,来使得代码更加可读更加安全。
致谢
感谢老师助教对项目的指点以及所有合作小伙伴的帮助