项目 | 内容 |
---|---|
作业所属课程 | 2021春季计算机学院软件工程(罗杰 任健) |
教学班级 | 周五上午 |
课程的目标 | 掌握构建之法,提升软工开发能力与团队协作能力 |
这个作业在哪个具体方面帮助我实现目标 | 温故而知新,在总结与回顾中进行思考与体悟 |
在开课初期通过阅读《构建之法》,我在阅读提问博客中留些了诸多问题,有些问题凭借自己的"脑补",在之前的博客书写时便给出了看似合理的答复,但经过一学期结对项目和两阶段团队项目的洗礼,结合自身的经历与体会,针对诸多问题我都有了更深、更贴合实际的理解,便在下文一并列出。
软件的很多错误都来源于程序员对模块功能的误解、疏忽或不了解模块的变化。如何能让自己负责的板块定义尽量明确,模块内部的改变不会影响其他模块,而且模块的质量能够得到稳定的、量化的保证?单元测试就是一个很有效的解决方案。—— 2.1单元测试
可以说还没进行软工实践时,我对单元测试并不感冒,认为其与编写自动评测机进行测试没有可比性。然而通过Beta阶段团队项目的测试工作,我体会到,单元测试与其说是简单的进行程序正确与否的判断,不如看作给予程序开发者再一次思考模块可行性的机会。例如我在Beta阶段对ChampionShop.cs
模块进行检查时发现,GetRandomChampionInfo()
的随机过程似乎实现有误,通过对该函数进行单元测试发现,由于在Alpha阶段我们默认了分配卡牌的数量,而由于Beta阶段我们新增了大量卡牌,原本的实现方式会导致refresh时选取卡牌操作会每次从默认牌组头部进行遍历,若卡牌已经由后端提供则跳过,对剩下部分进行随机,最终导致默认牌组靠前的卡牌更容易选出的伪随机效果,不符合设计初衷。
可以想见,即使不考虑真实工程中实现的可能性,这类细节性的错误很难通过较为宏观的自动评测机进行检验,而“强制”的单元测试则“迫使”代码的书写者在完成相应模块后重新对整个模块进行可行性的分析,根据贝叶斯定理,这里更要求书写者站在外部视角(用户的角度)来对该模块进行测试,以保障不陷入内部视角的思维局限。同时针对各个模块单独进行单元测试,也能使各模块相互独立,“保证即使模块内部的改变也不会影响其他模块,而且模块的质量能够得到稳定的、量化的保证”,这也是实际软工中行而有效的良方。
函数最好有单一的出口,为了达到这一目的,可以使用goto。只要有助于程序逻辑的清晰体现,什么方法都可以使用,包括goto。
该问题提的着实没有水平orz,我只能说在结对编程和团队项目中,我和我的队友都没有使用过类Goto()
语句,一方面由于结对编程两人需要频繁切换“驾驶员”的角色,另一方面团队项目Alpha、Beta阶段存在人员变动与职责变动,因此与其贪图一时的简便为队友后期徒增烦恼,不如踏踏实实写好备注,完善代码规范性来得实在。
为什么这一节要讲这么多两人合作的反馈问题?因为,如果软件工程师连一对一的合作都做不好,不能有效地去影响同伴,让合作双方都能从合作中收益,提高水平,那大家就别扯什么团队合作这些事。 —— 4.6 两人合作
经过一学期的体会,我的答案是肯定的。结对项目带给我的体会我已经在结对总结中提及,总的来讲其带给我最大的收获即为跳出小我,从团队的利益出发去思考、处理问题,这样的收获也使我能更快的适应团队项目开发中和各组员间的合作。在Alpha、Beta阶段发现程序漏洞后,大家都抢着抓紧修复,即使测试中遇到其他部门实现错误导致的Bug时,也会先力所能及地进行测试分析,这样的良性环境也保证我们小组每个成员都能够有效地处理意料之外的工作请求。
这种模式当然有它的问题:领导对许多技术细节是外行;领导未必懂得软件项目的管理,领导的权威影响了自由的交流和构造。—— 5.3.5 老板驱动的流程
该问题在我们的团队项目中可以换个说法,即“PM需要具备掌握/熟练运用各部门对应技术栈的能力吗?”,我认为答案并非肯定的,只能说全能的PM能做到锦上添花,但无法雪中送炭。尽管PM优秀的代码功底能起到见缝插针的作用,但由于一个人经历有限,必然有失有得。尽管我并非团队PM,但作为PM-lcy的室友,也能感受到他在除代码外的其他工作中投入了诸多精力,例如整合博客、分配任务、综合管理仓库、与助教老师进行对接等,人力有限,这样看美滋滋组的多人PM或许真有其道理所在。
另外,很多时候用户并不知道自己确切的需求,或者不愿意表达完整的需求,软件团队需要设身处地,替用户着想,引导出需求。软件团队可以分析技术的发展趋势以及产业的变化、社会发展的大趋势,推测用户会产生哪些新的需求。 —— 8.1.1 获取和引导需求(Elicitation)
在问题提问博客中我给出了一个可能的解决方案,即采用原型法,先根据基本用户需求开发初始原型,在根据用户的反馈进行原型的修改、扩充、完善,我们的Beta阶段也同样根据用户、助教、老师在Alpha阶段的反馈,新增了卡牌种类与教程两个模块。当然在实际开发中,必须面临决定“推迟”和“必须实现”的功能的情况,关于这点的处理方式在Beta阶段事后分析博客中已详细提及。
如何衡量两个并非完美软件?例如一个功能完善但存在安全漏洞,一个功能残缺但无安全性问题。或者换种说法,对于一个功能,临近发布DDL,发现存在安全漏洞(较难触发/对用户财产不会造成重大隐患),该如何衡量是否应当去除该功能?
我们Beta阶段的团队项目也遇到了以上问题,由于django和unity的不兼容,负责后端的同学较难实现密码在后端的加密,对用户的信息安全会造成较大影响。但由于我们的产品并不存在用户记录/消费一说,倘若我们在发布前直接删去前后端的登录交互,或者采用每次上线注册用户名直接登录,定期清理数据库的方式,是否算是在有限时间内能做出的最好决策?
需求阶段
显然最为重要的即为NABCD模型,然而可惜的是,我们在Alpha阶段对A、B、C、D都进行了较为完整的分析与调查,而恰恰忽视了最为重要的N(Need):我们将目标用户定位于传统的卡牌、自走棋玩家,以及想要利用零碎时间的轻度玩家,目标打造一款简洁、节奏快、操作简便的游戏,但过于”简洁“却导致我们忽视了没有接触过自走棋的用户上手难度的问题,对于该类用户,更需要在一进入就对其进行教程引导,避免出现拔剑四顾心茫然的情况,这亦是我们Alpha需求分析没有完善的地方,没能充分考虑所有目标用户的需求。
设计阶段
感悟最深的便是在结对编程中,我和我的队友需要对指导书中的一字一句有相同的理解,并且在保证正确性的前提下规范二人的代码风格、接口规范等,这些都需要在设计阶段一一明确。
实现阶段
必须与队友时刻保持沟通,即使遇到困难/对对方有意见、抱怨,都需要立刻且直白的指出,因为结对/团队的存在意义即为通过多人合作高效的完成项目,在进行开发时要更像汇编语言一样机械、高效,避免恋爱ing剪不断理还乱的PUA/自主PUA现象发生。
测试阶段
单元测试不可或缺,同时对于安卓app,测试软件在非正常情况下的容错性与可恢复性也极为重要,例如游戏运行至一半直接强行退出等。同时还要考虑密码、用户信息传输的安全性,以及apk本身的安全性(是否需要加固)等。
发布阶段
首先是针对安卓平台,尤其是游戏产品的发布,一定要做好规划,提前申请软著。其次,对于所有发布到公开仓库的代码,都要慎重考虑其规范性(绝不会再把.vscode文件直接一股脑扔仓库了orz)
维护阶段
对于每次版本的迭代更新都要有完整的说明,并且再满足CI/CD单元测试的同时,也需要进行与之前版本同样强度的传统测试,以避免拆东墙补西墙的情况发生。
一学期的软工课程就这样走向了尾声,可以说全程的体验与自己的高三心路历程不能说相同,只能说完全一样:
至于各个阶段学到的东西,体会到的东西,在结对总结博客以及本文中已经详细提及便不再赘述,在这里,我更想表达一下自己的谢意:
最后想说的是,一路走来,我也听到了一些关于我们软工班级的冷嘲热讽,但其实我只想说,许多东西只有经历了,才能真正体会到/才有资格领会到,其价值所在。在这里我也期待着罗老师的软工课能越办越好。