项目 | 内容 |
---|---|
这个作业属于哪个课程 | 2021春季计算机学院软件工程(罗杰 任健) |
这个作业的要求在哪里 | 提问回顾与个人总结 |
与本作业对应的博客 | 2021年软工-个人阅读作业2 |
我在这个课程的目标是 | 提升软件开发能力与团队意识 |
这个作业在哪个具体方面帮助我实现目标 | 总结本学期软件工程心得体会 |
一、问题回顾
学期初的提问链接:2021年软工-个人阅读作业2
1. 单元测试必须要程序作者来写吗?
学期初我认为,程序作者本身可能更容易陷入自己的思路,导致忽略一些边界情况。应该是最熟悉需求的人来写单元测试。但是这一想法在软工实践中体现出了其问题:
在团队作业中,针对代码的单元测试,我们尝试了这样的三种方式:由作者本人写、由PM(团队中最熟悉需求的人)写、由完全无关的其他人写。针对这三种情况,我们对应的效率(代码行数×覆盖率÷编写时间)排序为,(E_{作者}>E_{PM}>E_{无关人员})。按照我原来的想法,应该是(E_{PM}>E_{作者})才对,但是事实与之矛盾,说明我的假设出现了问题。
针对这个结果,我重新修改了假设:对于单元测试的代码,由谁来撰写存在两方面的考虑,一是效率问题,即多久可以完成对代码的单元测试覆盖,随着代码量的增大,对于非作者本人而言的单元测试编写者,效率会成指数级下降,因为需要更多时间去理清代码之间的逻辑;二是覆盖情况问题,即单元测试编写完成后,还有哪些特殊的边界情况未覆盖到,可能PM对用户应用场景更熟悉进而可以更多地覆盖这样的特殊情况,但是软件工程团队作为一个整体,开发人员也应该对需求有一定的了解。因此,基于这两方面的权衡,程序作者在单元测试的编写方面比PM更好。
2. 完成任务的预估时间如何预估?
学期初我认为,预估时间是基于开发人员的经验得到,会因为意料之外的情况而与真实时间极大背离。
事实上可能也确实如此,在Alpha开发阶段,我们对任务的预估时间与真实开发时间存在不小的出入,进而导致开发过程出现了前松后紧的情况,这个预估时间也没起到太大的统筹作用。
而可以起到指导作用的预估时间应该怎么得到,我通过阅读这个博客似乎找到了一些线索,它给出了这样一些步骤:
- 制定技术计划
- 为每个步骤添加时间估算
- 增加大量的额外时间
- 在发布之后对估算进行回顾
- 一切都是跟沟通有关
回顾Alpha阶段的开发过程,我们做的不好的地方是3和5:对开发流程过于乐观和出现问题时不及时沟通成了阻塞开发顺利进行的重要问题。
而在Beta阶段,我们做了一些改善,一是细化了issue的粒度,使得2的估算更加准确,同时留出缓冲区以满足3;二是指定PM和频繁的线下沟通使得开发过程不会被某个人的某个任务而阻塞。而最后的燃尽图也印证这种方式的可行性。
因此我认为这是一个可以参照的预估方式。
3 满足NABCD模型,是否就意味着是一个好软件?
学期初,我从一个不同于NABCD的角度考量了迅雷是否是一个好软件。进而得出了满足NABCD模型不是一个好软件的充分条件的结论。
学期结束,这个结论看起来仍不过时:制造和使用工具是人类和其它动物的本质区别。NABCD模型也许可以让制造软件的人有充分的动机去制造软件,但对于使用软件者似乎还缺乏一个对应的模型去评价软件。
4 非典型用户是否不是软件的服务对象?
学期初我提出了一个矛盾:非典型用户使用软件的概率很小,所以不为他们设计功能;但概论给出的例子又说百万分之一概率会使用的功能也要做好。进而提出了这个疑问。
经历了需求调研之后,我觉得这个问题是可以回答的:软件所覆盖的使用人群是有限的,通过调研我们可以对使用人群做出一些合理的假设,进而减小软件的开发工作量。而后者所对应的百万分之一概率使用的功能其实是指飞机的安全功能,是典型用户也会遇见并且如果缺失会产生严重后果的功能。
如果将功能和安全解耦来看,这个问题就更加清晰,功能存在其适用人群,而安全需要对所有人群进行全覆盖,因此最开始提出的矛盾并不存在,非典型用户就功能方面而言确实不是软件的服务对象。
5 成功团队与创新
那么我们应该如何既从成功团队中汲取经验,又能不被颠覆性创新而淘汰?
对于学期初提出的这个问题,回答起来十分简单,实事求是即可,对于自己的开发项目,适合使用的经验当然可以大加推广,而被颠覆性创新所淘汰,也只是某个方面的淘汰,这个淘汰可能指产品方面,技术方面,框架方面;但如果我们其他方面也已经吸取好经验并达到state-of-the-art,实事求是在对应的方面进行补短也并非是一个不可能的情况,但如果墨守成规,则确实有可能会被扫进历史的垃圾堆。
二、新的问题
在团队项目中,由于内部对单元测试做了较强的要求,导致代码撰写时出现了“过度工程”的情况,想问一下是否有可以遵循的步骤来避免设计或编码时的“过度工程”?
三、实践学习
1. 需求
- NABCD赋予我们结构化分析需求的能力
- 假定我们从零开始进行需求分析,可能会是无头苍蝇式的碰运气;但是NABCD提供了一个较为可行的方式进行逐步分析,并且对需求分析做了进一步的延申,对整个产品的逻辑做了一个完整的梳理,给予了一个相对明确的指导。
2. 设计
- 有记录的设计 >> 没记录的设计
- 在「观隅」的开发过程中,我们遇见了一些前后端的意见分歧。通过第三人的梳理,我们发现意见分歧的来源是因为该接口的设计未成文规定,虽然前后端任意一方妥协一下就可以继续开发,但是未成文的接口设计给予了双方充分的解释权,进而引发了不小的争执。最后,我们决定由PM在Swagger文档中明确给出该部分的设计。
3. 实现
- 好的实现是经过复审的
- 有位文豪说得好:“看一个作家的水平,不是看他发表了多少文字,而要看他的废纸篓里扔掉了多少。” 就像文学作品一样,代码是不可能一蹴而就的。如果我们希望有一个好的实现,最好自行审查后他人复审,可以最大程度地减少其可能存在的问题。
4. 测试
- 单元测试不是测试的全部
- 单元测试可以帮我们尽早发现问题,但不能帮我们发现所有的问题,许多问题还是依赖于进一步的压力测试、内部测试来发现
5. 发布
- 好的第一印象可以帮助俘获用户
- 基本可用版尽早发布
6. 维护
- 为反馈者提供无压力途径:加群固然可以持续交流,但存在一个反馈门槛,不能收取所有用户反馈,因此我们还有一个网页端反馈入口
- 对反馈及时响应
四、个人总结
1. 个人项目
在个人作业中,我通过阅读《构建之法》和相关博文,对软件工程和敏捷开发形成了自己的认识。之后在这个基础上分析了一个现有的软件案例,讲真是一个很新奇的体验。在软件使用上,我往往会反复横跳,因为某个软件的某个优点而短暂尝试,又因为其某个缺点而弃之不用,从使用者的角度我得到的是碎片化的体验。但身份转变为调研者,则开始对软件进行全方位的评测,从而能形成一个比较全面的视野。这也对之后团队作业的需求分析提供了一些经验。
2. 结对编程
在结对编程中,让我首次体会到了要为自己的代码高度负责的责任感。一是最开始设计时要充分考虑到结对编程的交替性,进而要在架构设计上多下功夫;二是由于角色身份的切换,我在指出对方错误时也在思考自己编程时该如何避免出现这样的错误。然后在本次结对过程中,我和结对伙伴做到了很好的沟通,对于设计或者出现的问题,通常都是两个人一起讨论解决的办法,然后选择一个较为保险的,两个人总能比一个人考虑更加全面。这样的过程,很大程度提高了我们的代码质量。
3. 团队项目
团队项目是本课程的重心。我作为后端开发的一员参与了团队项目 观隅——数据集管理与可视化平台 的开发过程,并最终得到了一个令自己相对满意的结果。作为后端开发人员,我实现了数据集的可视化接口和数据统计接口,并且为之构造了基本的单元测试样例。而且因为承担了Alpha和Beta阶段的除例会外的多数博客的撰写,我深刻体会到记录和总结的重要性,并且锻炼了自己的写作能力。
五、个人感想
软件工程课程为我们提供了一个充分实践敏捷开发的平台,并且为之构建了一个全面的评价体系,使得我们可以从中受到了极大的锻炼。不仅过程颇具锻炼意义,而且也收获了一个比较满意的结果。在此感谢结对过程中的结对伙伴田静文同学,经常交流沟通的牟钰同学,谜语人队的诸位成员,和课程组的助教老师们。