难遇伯乐,幸得钟期——提问回顾与个人总结
项目 | 内容 |
---|---|
这个作业属于哪个课程 | 2021春季计算机学院软件工程(罗杰 任健) |
这个作业的要求在哪里 | 提问回顾与个人总结要求 |
我在这个课程的目标是 | 提升工程能力和团队意识,熟悉软件开发的流程 |
这个作业在哪个具体方面帮助我实现目标 | 总结学期所得与所感 |
阅读提问
阅读提问博客链接:传送门
结对总结博客链接:传送门
团队博客链接:传送门
问题一:单元测试一定要作者写吗
当局者迷,旁观者清。如果让一个并不熟悉这一部分代码的人来编写单元测试,他就有更大的概率突破作者本身的思维定式,而对于一些***钻的边界情况进行处理,这种边界情况不仅仅包含输入输出内容,还包括调用位置、调用时机等等多个方面。
先说结论:我现在认为,单元测试并不一定需要作者自己写,重要的是对于功能的覆盖程度、对于文档的适应性和错误处理的覆盖面要广,也就是编写测试的人要非常明确自己在测什么、明确自己需要覆盖什么情况,而这种人往往是作者本人。
当时@宝玉老师在博客下面的指导在当时就令我大致明白了这个问题的答案:
是不是作者写不过是不同的手段,甚至单元测试本身也是手段。
但是软件工程的方法论不就是讨论通过何种手段达到目的的吗?
对,但是不要错把手段当目的
是的,单元测试无非只是一个保证迭代开发的稳定性、保证处理逻辑的条理性、保证处理范围的广度的一个手段而已,我们做单元测试不是为了达到多少覆盖率而去做测试。类似地,至于是谁作为测试者编写单元测试,那更是实现单元测试的一个手段而已。
不管黑猫白猫,能捉老鼠的就是好猫。
只要手段能够达到目的,则是好手段,要抓的是主要矛盾。至于能否达到目的,需要具体情况具体分析。
很巧,本学期在结对编程和组队项目中,我有幸体验了“测试员”的角色。
结对项目中对于边界情况的要求较多,对于各种特殊情况的处理难以进行全面覆盖性的测试,由于我本人参加过一些算法竞赛,对这方面数据的构造有一定经验,同时担任了驾驶员的角色,因此“单元测试”自然而然的由我进行编写。对于代码的了解和对于样例构造的表格记录,同时在测试时不考虑自己实现的细节而专注于进行全面覆盖性的测试,极大地保证了代码的正确性和鲁棒性,这可能就是作为代码编写者本人进行测试的一个优势所在。
组队项目中,我负责后端的单元测试。组队项目与结对项目中的待测代码可谓天壤之别,大相径庭。组队项目的待测代码主要是没有什么疑问的 API 功能实现,如从数据库中读一些东西返回给前端,前端传来点东西扔进数据库,有极高的重复率;最可能出问题的单词推荐算法部分也大部分是由本人执笔的。因此,我仅对于部分较有代表性的代码进行了覆盖性的单元测试,测试的过程中确实发现了一些实现方面的细节问题;但在仅仅达到 70% 的单元测试覆盖率后,我们在后续操作的测试中就没再发现问题了。
虽然确实如果还有充足的时间,我会尽量将更多的情况进行覆盖性测试,70% 的覆盖率确实有些低了;但是由于需要进行前后端对接、新算法实现以及作为 PM 的团队规划,进行较为全面的覆盖性测试不现实,因此仅仅使用了性价比最高的、忽略重复无意义操作测试的方案;但从此也可以看出,在软件工程中对于目的和手段的主次需要进一步明确。
私以为,从这里就可以看出,敏捷开发最关注的可能就是所做事物的性价比。因此,我有一个新的疑问提出:
如果明知一个事情是对的,但是对不对的权利不掌握在你手中(比如老板),而且他执着坚定地、甚至可能先入为主地认为,这个事情并不对。这时,是否应该选择性价比更高的妥协?
我不知道。希望我将来也不需要知道。
问题二:结对编程的应用性如何
结对的一个主要目的便是让代码出错的概率降低、每一行代码都有其存在的意义,不留浑水摸鱼的机会,但书中提到过的代码复审也能够达到类似的目的,而且能够多人参与,声音来源更广,在当下
github gitlab
等代码交流社区的pull request
也十分便捷。事实上,了解过的部分周围公司也都因为种种原因没能开展结对编程。结对编程最早也是源自两个程序员赶DDL
不得不做的一个“创举”,仅仅是契合当时的事件背景的一种解决方案。结对编程在当下的应用性究竟如何?
在经历过结对编程之后,我对这种编程方式在真实公司里存在的应用性存疑。
真正能够稳定轻松进行下来的组别,在我看来,少之又少。这大概是因为一方面需要两人的水平不可差异太大,另一方面需要有一个细心全面的领航员和一个果断规范的驾驶员,才能让飞行的过程中保持清晰的头脑,清楚地知道自己每一行代码在写什么,从而才可以进行有序稳定的推进。
据观察了解,还有一个较为严重的阻碍,就是大部分同学不习惯被人盯着写码,虽然不太理解,但这或许是大部分组别没有真正进行一人驾驶一人领航的“结对编程”,而是在进行一种小团队分工合作形式的“项目编程”的原因。其实终究说来,还是这种分工合作形式相对真正的结对编程能够以较高的性价比完成任务。因此,就敏捷说来,结对编程貌似不是一个优的选择。
问题三:课程中例会是否仍要“每日”
敏捷开发中,频繁的小会是为了及时同步全局信息,让团队清楚个人的进度情况、困难之处,同步信息的主要目的在于增加整个团队的效率,即通过队友的进度、压力、困难来
push
每一个人。我相信我们的组员都不会习惯于浑水摸鱼,但人的精力是有限的。在这种课程压力下,在例会会占掉课余时间一大块蛋糕时,同步信息的例会是否还有必要保持“每日”?如果适当地增大例会之间的间隙,并适当规定每个人的贡献与任务,是否也能够在给组员足够压力的同时允许我们自主安排其他课程与软工项目的时间?
确实不需要,尤其是在我们本学期专业课压力较重的环境下。
团队项目中,队伍基本两天一会,在 Beta 阶段压力更大的情况下,才在最后冲刺阶段进行一天一会,进行看板、议题商定以及集成测试。
两天一次的例会已经足够同步全局信息了,在某些会议上前端进度较多,后端就会让前端慢下来先写 API 让后端进行实现,然后继续进行前端工作;后端内部也可以更加合理地进行数据获取、API 实现与测试、数据库设计实现以及服务器和域名配置等任务的分配,每一次“每两日例会”之后对于全局信息的同步总结都极大地促进了团队的执行效率。
我们团队其实在会议后进行联合开发,没有其他事干扰的队友们聚在一起进行快乐开发,感觉非常愉悦,也不会码到一半犯困,这也就是我们对于问题的解决为什么不局限于 issue,而是首先使用看板法,这还是一个性价比的问题。在集体开发后存疑的部分,为了防止忘记和遗漏,我们会在 gitlab 上新建一些 issue 或者 comment 进行记录。
问题四:NABCD 模型是否变为 BD 模型
观察这几个软件的做法,扩大用户量的主要因素就在一内因(B)一外因(D)。满足用户基本需求的 N,在 QQ 那时或许是一种开创性的做法(其实当时也不算基本需求了),在现下已经是一种企业生存的必需要求了,单单满足这一需求是无法谈论竞争力的。而这些软件之所以能够取得如此规模用户量,更多的其实是满足用户“兴奋需求”的 B,以及市场推广或者捆绑的手段 D。同样地,许多被腾讯推广的游戏,其设计、内容等都远远落后于同类型其他游戏,但无论是用户量还是知名度往往都能够吊打其他游戏。所以其实 NABCD 模型在当下是否转化成了 BD 模型?软件的成功到底是软件工程还是市场营销?
经过一个学期的学习,我仍旧对此没有得到一个较好的答案。
但可以肯定的是,D 是一个很重要的考虑因素。
Alpha 阶段,团队项目“近取 Key”进行了详尽完备的 NABCD 需求分析,无论是从基本需求、方案设计还是竞品对比,都做了比较全面的分析,但是我们当时主要的考虑点在于能够实现这么一个东西,而并非将其进行大规模的宣传,因此 D 阶段没有下大功夫,而是在功能完备性上下了大功夫。这其实在工程量和宣传上做了一个衡量规划,我认为是合理的。
Beta 阶段,增加了一些宣发力度的同时,需要做的任务和内容也并不少于 Alpha 阶段,因此实际上对于宣发的力度做的还是没有全力以赴,而是在追求一个现在看来似乎有些画蛇添足的 B ——社区。因为...似乎没有人在用这个功能。当然,产品的 N 和 B 基本需求和兴奋需求确实非常有效——因为有很小一部分用户已经在真正使用本软件在背单词了,而且每天都能收获到用户的新反馈。但似乎众多受众背单词党们并没有被吸引到,可能是宣发的力度有限导致的。其实也没有什么特别好的方法,毕竟多数在背单词用户都是在移动端碎片化地背,导致对于真正的受众用户被屏蔽掉了。
阻碍我们产品拥有较高活跃度的除了受众占比低、难宣传之外,还有两个因素:一是平板适配,二是登录方式。平板适配由于技术原因没有做到非常完备,尤其是进行测试设备的不够多,对于各种大小的屏幕无法做到全部能够适应。登录方式由于微信登录需要较昂贵的一笔开销,因此选择了暂时不考虑;同时由于词图限制,无法做手机端,因此无法做小程序,在登录方面给用户设置了一些屏障。
当然,还可以进一步分析一下这个产品的杀手级功能。A4 纸背单词法,是一个我们之前也经常使用的一种背单词方式,但由于每次对于一个单词不知道含义的时候都需要花大量的时间去翻字典重新记忆,导致了效率的一定程度降低。因此,我们考虑如果能通过软件来自动实现,那将有多好。这并不是一个臆想的需求,只是受众较少;而电脑端背单词软件仅仅是附庸于 A4 纸背单词需要大屏的一个结果而已,并非什么需求与配置。
值得考虑的是,如何才能够找到小众需求对应的受众?目前宣传结束后,日活大概能够维持在 20 人,而且 B 站视频播放量也在逐渐稳步增加,似乎这是一种较好但转化率较低的宣传方式;如果有更好的如知乎、微博等更多方面的渠道进行宣传,或许能够拉到更多有需要使用电子版 A4 纸背单词法的用户吧。那个做的感觉明显很垃圾的竞品小程序能做到几万播放,感觉甚是奇怪,可能这就是快节奏时代宣传的方式?我不知道。
问题五:设计文档如何平衡严谨性与复杂性
因此,设计文档应该如何平衡严谨性与复杂性?真实软件工程中,是否用到了类似 JML 的规格语言进行功能描述,如果是,如何保证编写的正确性?如果不是,如何保证规格的严谨性?
团队项目中,我们使用了 API 文档进行前后端交互,后端内部使用数据库设计文档进行数据库约束,没有涉及到具体某一个方法的类似 JML 的规格化表述。我认为这种方案就是比较可行的,该分离的地方分离,接合分离处的地方写明设计文档即可。
问题六:集成测试应不应该在模块构建时进行
这里纯粹对集成测试和模块构建的理解有一些偏差,有点抠字眼了,本质还是手段与目的的问题。
问题七:事后诸葛亮会议为何不能融入每日例会
邹欣老师的解答
- 每日例会时间要短
- 很多任务在进行中,不是一个好的回顾总结的时间点。 (例如,你写的一个功能号称会有很多用户喜欢, 在没有用户反馈前,你是不知道的,也无法总结)
- 总结要拨出专门时间好好讨论
和宝玉老师的解答
当然可以融入,但是不能替代。
- 要有仪式感
- 站会要短而精,加上事后诸葛,那么站会的意义就变了
已经解答了我的疑惑,在敏捷开发这一盘快棋中,诸葛亮会议之于每日例会即是复盘之于思考,每一步落子的思考是带有局限性的。在 Alpha 和 Beta 两次冲刺结束后,我们对于自己的产品分别进行了两次事后会议,能够在更加高的角度俯瞰整一个冲刺中无论是管理还是分工,或是对于产品的思考分析,以及方方面面的得失,我认为这是比纯粹的赶 DDL 冲一个项目收获更大的环节。
知识点
先按博客要求写一下“知识点”。
需求:见上“问题四”:NABCD 该如何分析;对于小众需求,受众需要提前找。
设计:需求设计不分家,确定需求后即可进行初步的架构设计和 UI 逻辑设计了。设计方面主要学到了使用 processon 也能进行原型图绘制,以及对于文档应该如何撰写的基本了解(如 API 文档的撰写、ER 图和数据库设计文档该如何撰写等)。同时,对于架构设计尤其是数据库部分,要充分考虑到解耦合、添加合适的多属性键等影响较大的、有助于后续迭代开发的部分,避免设计低鲁棒性的、难以维护的数据库。
实现:实现部分,作为后端,主要是对于前端传来的 API 进行与数据库的对接。因此实现部分较为简单,所学知识大概是 CI/CD 的搭建、代码规范、代码风格、命名规范的统一。
测试:见上“问题一”:单元测试是手段,目的是软工;通过压力测试可以不断优化算法和配置,如 Alpha 测试报告中所提到的。
发布:发布不仅仅是给一个链接扔到朋友圈就行,做的是产品,方便的是用户。要做宣传册、方便用户观看且短小精悍的视频、针对用户需求精心设计的文案等等,不一而足。要尽可能让用户简单地进行反馈,用户的反馈真的很重要。因此,也需要尽早进行发布,不能发布得太晚。
维护:直接置顶反馈群,同时每日一刷 core_remark 用户反馈并进行讨论。bug 方面讨论的较少,可能也与测试较为完备有关,主要还是讨论适配问题。对这种 bug 也需要进行一定量的记录。
心得体会
运用之妙,存乎一心。
其实学这门课之前我对软工所有的了解就是:要学的东西很多,但我啥技术都不会。不过被昂神忽悠过来罗杰老师班之后的一个学期,收获是颇丰的。
非常喜欢学期初的个人阅读作业,把整个人从寒假的摸鱼状态直接拉回紧张的学习生活中,仔细对自己进行分析、阅读邹老师的著作、分析软件的差异性。还记得整整一个周除了吃饭睡觉打疫苗之外无时无刻不在捧读《构建之法》的日子,两整天找洛谷和力扣 bug 的场景仍历历在目。
读完《构建》,一栋完整的大楼在脑中逐渐浮现。从需求分析,到架构设计,再到代码实现测试;从个人能力,到结对编程,再到团队敏捷开发;从单元测试,到场景测试,再到系统集成测试......有感而发,一鼓作气提出了九个问题,现在看来多数都是对一些细节钻入了牛角尖;但也有一些至今仍未搞懂的问题,或许需要在将来的生产生活中进一步的领悟了。
案例分析作业是一个真正煞费苦心写的博客,不过可能由于交的过早没有覆盖到一些东西(笑)。这是我使用两三年洛谷第一次认真的去扒它的 bug,只记得以前一直用的挺顺畅,用户体验不错,难找 bug;没想却成为了点炒饭的顾客。在分析产品规划的时候,我逐渐形成了一种分析用户特点的思维模式,也即做用户所需:做大部分用户所需,做特定功能用户所需。自此以后,对于软工的需求分析有了进一步的认知。
结对作业做的不像软工,而更像一个变异体的 OO,本地测试强度梦回第三单元,但是强测强度真是一言难尽。主要还是过了一把驾驶员的瘾,操纵全局、从需求分析开始,设计类的架构、设计实现方法、设计测试用例,倒也有点小软工的意思。从结对作业中与助教高强度开 issue 对线的经历里,我更加深刻地体会到一个合适的需求分析的重要性,以及一个鲁棒性强的架构与实现在变动的需求下是多么的重要;同时对 gitlab 协作使用有了更多的经验。
题目确实难出,既要出的能够迭代,又要描述严谨、不漏边界情况,还不可以太简单,因此对于题目就不进行吐槽了;但是个人其实对结对这种编程方式没有什么特别好的印象,没有体会到结对能够如何帮助我们多少(也如上方问题二中的想法相同),而且真正也没有见到有公司使用这种方法进行工作,因此对结对作业部分仍然存疑。可以考虑删掉结对作业直接组队,或者将结对换为个人的热身小作业;或者必须保留的话,可以将结对作业作为热身项目,不要出的这么绕,体验都会提升一个层次。
团队项目中,我负责后端的开发以及轮值 PM,最开始对 Django 技术栈一窍不通,在老田一个之前做过的项目 demo 下逐渐全摸明白了,老田 NB!刚开始分配任务栈的时候,需要四名前端,但大家基本都没干过前端,四位勇士当仁不让,站出来挑战前端,从零开始干劲满满地学习技术栈,啃技术难点硬骨头、搜索挑选五花八门的组件库,在如此短的时间内将 UI 做的这么精致美观,将词图功能展现的淋漓尽致。我们能够作为一个团队共同努力奋斗,是一件多么幸福的事情。
在 Alpha 阶段后,课程组对我们提出了宣传力度不够的评论,并给我们一份内容翔实的深度分析博客,我们非常重视,马上将宣传提上了 Beta 阶段重大任务的日程,并且详细地品读了深度分析博客,深度读完后惊喜地发现,其中大部分内容和 Beta 阶段的任务相同,从对于用户的新手引导、单词的添加逻辑,到单词复习的功能交互感、加入词图可能的重叠,以及域名的申请,这都是 Beta 阶段当时定下的重点考虑对象,在最后的 Beta 阶段均已被实现。唯一的遗憾就是平板的适配弱了一些,这是技术问题,没有被解决掉。
换人阶段感谢老田提出的“双向选择”转会方式,我们能够在一个更加真实的转会背景下进行合理的人员再分配。
在如此短暂的开发时间下,我们将最主要的功能进行了实现,其他一些花里胡哨的功能,比如测试中的选择题,都被踢下了日程,换上了宣传视频的制作、H5 宣传册的制作、以及 B 站 up 的交流工作等等,真正做到了有舍有得、以我们现有能力在如此短时间内能做到的最佳状态。在此我们要感谢课程组一个学期以来对于我们组无论是需求还是宣传方面做的事情,无论是 push 也好,热烈的讨论也罢,都是一笔软工给我们留下的财富。虽然 PM 需要在统筹的同时完成不少于普通组员的任务,但我们仍然坐定冷板凳,认真地考虑和讨论课程组所提意见的合理性并付诸行动,真正做到了核心功能扎实、杀手功能突出、广纳博取融会贯通的软工。如果再给我们多一些时间对软件进行完善,我想还能够进一步完善的就是宣传的广度和力度,打通通向受众的通道;以及对于平板的支持度、对于各种分辨率屏幕的适应程度。
在包括众多因素的现实背景下,我们仍然能够拿到现场评审的第一名、总体评分的第二名,且与第一名的队伍分可能只差在一两个评分上,这个成绩还是相当满意了。当然,在这里也要祝下一届有一群更加负责任的助教团队,如果作为助教还是搞不明白自己应该把什么放在重点、把什么“助”教给学生,把自己的先验概率藏起来的话,那可能还是比较适合搞技术,和助教可能有一定的区别,希望软工课程组能够认识到这一点。
“唯陛下观览古今,反复参考,无以先入之语为主。”
总之,课程内容很好,很推荐,通过从阅读到分析再到实践的一个完整过程让我们熟悉了软工的基本流程。如果有人问我,给我一次机会,是否还会选择罗杰老师的软工,我会毫不犹豫地说一句“是”。伯乐不常有,但万一有呢?