2020BUAA软工提问回顾和个人总结作业
17373010 杜博玮
项目 | 内容 |
---|---|
这个作业属于哪个课程 | 2020春季计算机学院软件工程(罗杰 任健) |
这个作业的要求在哪里 | 提问回顾和个人总结作业 |
我在这个课程的目标是 | 学习软件工程,培养工程开发能力、团队协作能力,开阔视野 |
这个作业在哪个具体方面帮助我实现目标 | 反思整个课程的学习过程,通过自我总结提升软工总体水平 |
提问博客链接 | 2020BUAA软工个人博客作业 |
对自己曾经提出的问题进行解答
-
在4.3.2中,作者表达了只要有助于程序逻辑的清晰体现,什么方法都可以使用的观点。
我个人对这一观点表示反对。因为一个程序员很难保证自己的思维永远清晰完整,而开放类似于goto之类的方法,完全是给整个程序的正确性埋下巨大的隐患。毕竟大型软件逻辑结构比较复杂,使用goto之类被公认会降低程序安全性并且破坏程序的结构化程度的方法来使程序逻辑清晰完全是得不偿失。我们完全可以通过增加注释,整理代码等多种方式来做到这一点,为什么要使用goto之类的方法呢?
现在我并不认同作者提出的观点。在原文中作者表示函数最好有单一出口,为了达到这个目的,即使使用goto也是没有问题的。因为这样有助于程序逻辑的清晰体现。然而在实际应用编写中,错误处理占据了代码的很大篇幅。这次的团队项目中由于我所编写的代码涉及到网页访问,程序异常处理多如牛毛,不同的异常也需要不同的处理,如果强行使用goto做到单一出口,风险与收益完全不成比例。
在我看来,通过保证程序只有一个出口这类要求来达到程序逻辑清晰完全没有通过增加注释,整理代码等方式便捷、安全。当然,在一些代码规范如pylint中有return语句的数量限制,但是这种限制很宽松,基本上不会对正常程序报错,通过这种规范反而能够通过较小的代码修改很好地规范代码格式。
总而言之,我认为使用任意方法来达到程序逻辑清晰是不可取的,我们需要在正确性、工作量以及逻辑清晰之间进行取舍以达到一个平衡值。
-
在11.5.5中,作者对小强地狱进行了阐述,在阐述中我们不难发现开发新功能与修复小强之间的矛盾。
在客户与绩效的压力下,开发新功能有着很高的优先级,但是拖着大量小强既导致测试人员无法有效地继续测试,也可能将小小强拖成大小强,在后续的过程中造成巨大的困难。作者介绍了小强地狱的方式来解决这一矛盾,但是我感觉这种按照阈值修复小强的方法做得不够彻底,大量的bug依然会被遗留下来。
在我看来,借鉴ZBB是一个很不错的选择,在一周的开始,开发人员开发新功能,测试人员进行测试,在这一星期的结束,开发人员针对测试人员提出的bug进行修复,下一周继续进行上述工作。
如果一切顺利,开发人员一周内需要解决的bug也就是他们在上周的开发中所产生的bug,这样是不是就可以比较好地解决开发新功能与修复小强之间的矛盾。
在这次团队作业中,我们团队在开发阶段出现了不少的bug。这些bug对项目的继续开发造成了比较严重的影响。比如前端的bug就会影响后端的相应部分的开发、对接、测试。但是着重于bug的修复又会产生进度问题。比如在Beta阶段我们组内一个前端同学就因为一些bug导致一个比较简单的任务做了大概一个星期,这极大程度地拖慢了前端乃至后端的工作进度。
因此我们可以看到在实际项目中,bug和开发之间确实是像书上说的存在矛盾。但是通过实践来看,解决这种矛盾不能拘泥于纸面上的分析,而是要带入项目本身。无论是小强地狱的方式还是我此前提出的方法都是有它的优缺点的。比如小强地狱就易于使用,但是可能会做得不够彻底。而我所提出的方法过于理想化,不易实现。实际应用中还是要结合项目自身处理开发与bug处理之间的矛盾。
-
在15.1.3中,作者介绍了从代码完成到代码发布时可以采取的不同操作,其中有重写和重构两种解决Bug的思路。
这两种方式各有不同,但都是解决Bug的相当好的途径,同时也会增加大量的劳动量。我的疑问是这两种方法的差异以及各自的应用领域。
在书中,作者介绍了重写与重构的含义。重写是指重新实现原有功能,重构是指在尽量保持原有界面的基础上优化部分代码。
我在网络上发现很多程序员对重写持有很不友善的态度。他们认为重写是一个相当大工作量的工作,成本很高,很多逻辑可能会被忽略,需要花费更多的人力来测试和debug,并且需要重新了解项目的需求,完全重新设计与实现,任务繁重且困难。为了维持正在运行的系统,我们可能还需要一边重写新系统,一边重构旧系统。而且一个需要重写来处理的项目很有可能留下的文档与代码一样混乱不堪,因此在对业务逻辑没有理足够清楚的情况下,大多数人都不推荐重写系统,只有在很清楚地知道代码做什么,但是很难理解那些代码的时候才会重写。
而大家对重构就比较友善了,重构是一种局部式,增量式的活动,我们通过向旧系统中增补补丁来对代码进行逐步的优化,从而逐渐减少代码的混乱程度,增加代码可读性。一般情况下,当代码难于理解,并且团队不能确定它做什么的时候进行代码的重构。(参考:重构?还是重写?)
在Beta阶段我对自己的代码大规模进行了重构和重写的工作。根据我自身的经验来看,重写主要是用相同或不同的方法重新写一遍,重新实现原有功能。而重构则是不改变代码本身基本架构和大多数代码,只优化少部分的代码。
在Beta阶段,由于用户数的增长,此前Alpha阶段所设计的方法消耗太大,导致服务器负载大,提供服务卡顿。因此项目只能通过另一种方法来获取数据。这导致我需要完全重写我的数据获取程序。整个重写过程很痛苦,完全的推倒重来导致工作量很大。然而重写后的程序运行速度提升了3-5倍,内存占用减少了几十倍,效果相当可喜。
同时,在Beta阶段,团队决定使用pylint进行代码规范。装上pylint后测试出现了400多个错误。其中还有很多代码结构上的问题。为了一个好的代码风格,我对整个代码进行了重构,改写了部分循环分支繁杂、大量返回语句堆叠在一起的代码。整个重构过程比较快速,大概只花费了4-5个小时,重构后的效果也非常不错。
-
在12.1.2中,作者对“吃狗食”进行进行了阐述
“吃狗食”保证了开发人员能了解软件功能的实际表现,可以发现很多关于用户体验方面的问题。但是程序员作为软件开发专业人士,对软件构造的看法与用户有很大的区别。那么我不禁想到,不如专门让那些没有程序员思维的体验员进行体验,通过体验员与程序员之间的交流、辩论来改善软件在用户体验方面的问题。
在团队作业中我们主要通过“吃狗食”这种方法来进行测试以及用户体验方面的改进。整体而言这种方式确实让我们找到了大部分的问题,进行了很多用户体验上的改进。但是我们作为程序的开发者,由于对程序的运行机制有比较深的了解,有很多用户体验上的问题没有发现。而且我们团队的前端开发者在“吃狗食”的过程中发现的问题就更少了。因此在我看来,“吃狗食”确实很有意义,但是不能盲目相信它的作用,没有程序员思维的体验员的意见应当更为重要。“吃狗食”更大的意义还是在于迫使程序员好好写代码,
不要写屎给自己吃。
还不明白的问题
-
在2.1.2好的单元检测的标准中给出了单元测试好坏的判断标准,我的问题是关于单元测试的针对方向。
作者在单元测试好坏的判断标准中写道,单元测试应该在最基本的功能/参数上验证程序的正确性且单元测试要快。但是在前面对单元测试的引入中作者通过小故事表达技术模块各项要求最好都可以表示为一个单元测试样例的思想。那么单元测试到底应当针对什么呢?
首先我认为根据单元测试的名字我们可以看出它应当测试基础功能,其他重要功能应当在功能测试、集成测试等领域展开,但是我们有时会利用单元测试来检验一个类或函数的正确性,通过查找资料,我发现单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。(参考:单元测试)那么我们是不是应当针对程序中所编写的一个个单元进行验证,而不是针对技术的一个个最基本功能来验证呢,换句话说,单元测试是基于设计层面,还是基于程序方面?在我看来,我们应当专注于程序方面,但我并不能完全说服自己。
在这次软工的项目中,我的单元测试还是更倾向于验证一个设计层面的功能是否正确,这样的测试易于编写,结果也更容易理解。但是我也认为对每一个程序的单元进行测试更为严苛、标准,出现了问题也更容易排查。我对这个问题总体的印象还是比较模棱两可的,没有对某一方的偏爱。
学习的新知识
-
需求
需求不能只靠团队设想,但是也不能全凭用户决定。而是应当由团队设计主体架构及方向,用户和团队一同提出详细需求,最终交由团队取舍。
-
设计
设计时绝对不能过于笼统,这会导致具体实现不好下手,但也不能过于详细,具体实现时出现一些问题会使原计划大幅度变动,影响太深。
-
实现
具体实现时不能一昧猛干,而是要先解决知识盲区,再解决数据接口格式等问题后再下手。
-
测试
测试用例必须要全面,从各个有可能出现问题的角度出发设计样例。
-
发布
发布不能随便一个广告了事,而是要有针对性地设计宣传语,内有要有足够的吸引力,从多个渠道投放广告。
-
维护
错误反馈必须要有及时的通道,比如程序可以设计成抛出未知异常时向微信发出问题的详细信息,从而做到及时获取有用的错误信息。
心得和理解
-
个人项目
其实感觉与以前的大作业没有太大的区别,甚至可以说把这道题和去年OO的多项式的题放在一起,我不能看出这次的个人项目到底“软工”在了哪里。
但是这个项目还是让我获得了一定的收获。首先这道题目看似是很简单的模拟题(不追求O(n^2)以下的时间复杂度的话),实际应用时你还是会被浮点数的精确性、部分耗时较大的语句卡住。我之后在浮点数判断时采用与1e-8相比的方法提高精确度,将set改为unsorted_set大大提高运行速度。同时这次的项目还着重引入了单元测试,这是以前几乎没有接触过的。
以上这三个方面都给我一些启示,精确性与复杂度都是可以在很小的地方抠出来的。而有效的测试则是代码质量提升的好方法。
-
结对项目
整个结对项目可以看作是个人项目与团队项目之间的过渡。整个项目做下来确实感受到了两个人一起做项目的好处,奇葩bug少多了,思考的时间也变少了。但是我们所付出的是效率降低的代价。总体来说有利有弊吧,其实我个人是更偏好于一个人写代码的,多一个人监督总会让我有些慌乱,不知所措。但是整个结对项目下来通过与同伴的沟通,我也学到了不少的东西,也学会了从旁观者的角度去看待问题和编程。
-
团队项目
整个团队项目做下来让我感觉选罗杰老师的课选对了,或者说我进了一个好团队。PM认真负责,对开发的各个方面都有一定的了解,各团队成员之间友好协作,一起做一个我们很想去做的项目。这可能就是软件工程的魅力所在吧。
感觉整个项目的关键还是在于设计阶段。在需求基本确定的情况下确定需求的实现手段并分配任务。能否选用恰当的实现手段很大程度上决定了整个开发阶段会不会疯狂爆肝一个难以实现的东西,或者说实现了大半了发现不好用,全部推倒重来。而任务分配和时间规划则很大程度上决定了整个实现阶段的效率和实现效果。
回顾团队项目阶段,一个月的时间我们这个刚刚搭建起来的团队做出了一个界面还算美观,功能实用、基本上没有bug的程序。我内心感到相当的快乐和充实。