提问回顾与个人总结
提问回顾与个人总结
Q | A |
---|---|
这个作业属于哪个课程 | 2020春季计算机学院软件工程(罗杰 任健) |
这个作业的要求在哪里 | 提问回顾与个人总结 |
我在这个课程的目标是 | 系统地学习软件工程开发知识,掌握相关流程和技术,提升工程化开发的能力 |
这个作业在哪个具体方面帮助我实现目标 | 对一学期软件工程的学习进行反思总结 |
链接到以前提问题的博客
对自己提出的问题进行解答
Q1:关于“银弹”
目前我们还是没有看到“银弹“的希望吗?高级编程语言、分时操作系统和统一开发环境在一定程度上解决了附属性困难;面向对象编程、人工智能、专家系统、“自动编程”、图形化编程、程序验证、更好的环境和工具等是解决本质性困难的希望吗?计算机的底层硬件发展速度极快,但是底层原理从发明到现在都没变,是不是在计算机底层领域也没有”银弹“呢?就我自己的感受而言,编程的过程似乎是人”将就“机器的过程,机器不具有容错能力,一遇到bug只能人去解决,是否是说只有计算机体系发生质的改变,软件工程的本质性困难才能得到解决呢?
布鲁克斯认为,软件开发的困难主要分为两类:
- 本质性困难:软件本身在概念(conceptual)建构上存先天的困难;亦即如何从抽象性问题,发展出具体概念上的解决方案。
- 附属性困难 :将概念上的构思施行于电脑上,所遭遇到的困难。
就这学期的软件工程开发实践而言,由于团队项目有老师的指导,每周有会议老师会提出建议来进行项目的推进和完善,团队项目中也是和队友一起解决问题,我们也并不是完全从0到1的开发,所以对软件工程中的本质性困难和附属性困难没有特别深刻的体验,同时我自己对计算机底层领域的学习和理解也不够深入,这个问题我目前还是存疑。
Q2:关于结对编程
在结对编程过程中会不会出现水平较高的程序员长时间掌握着主导权,而水平不那么高的程序员为了最终的产品效果更好或是作业取得更高的评价也只能在大部分时间里做一些边缘任务的情况呢?应当怎样合理的分配任务才能让保质保量地完成工作,同时两个人都有所收获呢?研发和测试工程师之间或同PM之间的结对,也可以带来不错的效果?
在课程前期的结对编程实践中,我的队友是之前认识的朋友,彼此之间比较熟悉,能力水平也没有很大的差异,交流起来没有什么障碍,所以说没有出现某一位同学长期掌握着主导权而另一位同学只是做边缘任务的情况。我认为在结对编程中,首先是对彼此的信任,在出现问题的时候互相交流,两个人一起VS问题,而不是推卸责任;其次是端正自己的态度,不能说有摸鱼划水的想法,尽职尽责的完成自己的工作,那么在结对编程中是一定会有所得的。也会收获到1+1>2的高效率开发和高质量成果。
在课程的结对项目中,我和队友之间的工作分配比较明确,驾驶员(Driver)和领航员(Navigator)的身份也不是固定的,比如在错误处理阶段和UI设计开发阶段,我俩的身份就是互换的,在减小任务压力上有很大的帮助,不至于让某一个人一直处于高速运转状态。可能由于此次结对项目的功能实现设计比较明确,所以在分工的时候没有什么困难。若是以后涉及到结对编程分配任务,我觉得首先需要考虑项目的功能设计和划分,分解粒度随具体项目而定,然后按照每个人擅长的方向对任务进行分配,以此来确定不同阶段的驾驶员(Driver)和领航员(Navigator)角色。
在团队开发中,我们并没有采用开发和测试或同PM之间进行结对编程,大家在团队中都有自己的角色和任务,也是自己对自己的代码进行测试,这样做的优点是可以很好的提高个人开发的效率。在课堂上看到其他小组的展示中有提到一个前端一个后端的匹配模式进行结对编程,也取得了不错的效果。
Q3:关于敏捷开发和极限编程
我比较困惑的是设计在软件工程中应当处于什么样的位置,如果说是用户驱动,但是用户对自己的需求也没有很准确的表述,是否意味着团队就不需要做尽善尽美的设计,而是迅速开发,跟用户交流后再修改重构,这样是否会增加潜藏的修改、测试成本?好的做法推广到极致一定是更好吗?
经过老师的评论,对设计进行了更细致的描述,在这里主要指的是功能设计。在课程学习中,不管是作业还是项目老师都会给明确的需求,比如某个程序应当实现什么样的功能,某个作业应当达到什么样的基本目标,而通常我们在正式写代码之前会分析功能需求,进一步确定具体实现的架构。但是在开发中,我们接收到的可能是不明确或是不完整的需求和功能要求,一开始我的想法是在团队动手之前,需要先进行尽可能完善的设计再着手开发;但是经过团队项目,我现在的看法是一开始可以不做详细的设计,而是在后期做频繁的增量开发、重构和发布,这也和书上提到的观点一致:将有效的方法发挥到极致。
在团队开发的alpha阶段,我们一开始简单确定了需要实现的功能,得到初版本后和老师交流又进行了功能的增量开发和测试,最终发布了alpha阶段的成果。在项目开发的过程中,需求一定是不断变化的,和用户的交流成本也是无法避免的,我觉得在这个过程中比较好的解决方法是先开发出一个最小可用的版本,然后再考虑需要修改或者增加的功能实现,用户也只有在看到具体的产品过后才会更明确的知道当前成果和目标产品的差距在哪,开发团队也就更能抓住重点进行项目的完善。重构和迭代大概也是软件工程的必经之路。
Q4:关于QA(Quality Assurance)
在第三方认证出现之前,团队里应该有独立的QA角色,按照典型的软件工程团队里PM,开发,测试三种角色,似乎很少有提到QA的,或者说QA的工作几乎是分摊到每个角色头上的。在我们之后软件工程开发和组队时,团队里需要有专门的QA角色吗?QA应当在整个工程的哪个阶段介入和产生影响呢?
在我们的团队项目开发中,团队里没有专门的QA角色。软件质量保障工作(Quality Assurance)是软件团队为了让软件达到事先定义的质量标准而进行的所有活动,包括测试工作。从测试的层面上来说,团队里的每位成员都对自己负责的功能模块进行了测试,参与到了QA的工作中;从整体上来说, PM除了把控项目的进度、协调前后端以外,也对整个项目的质量进行了把关,及时对不合理的地方进行修正和完善,完成了QA的大部分工作。可能是因为我们的团队项目只是比较小量级的开发,因此感觉独立的QA角色没有什么必要;但是若是在成熟的软件工程项目中,独立的质量保障角色应该也是不可避免的,在第三方认证之前,团队里需要有一个人对QA这件事负责。
我想QA最好是在项目一开始就介入,首先专门的QA对软件项目的设计和实现要点有细致的了解之后,才能进行有效的测试和评估;其次在开发的过程中可能会有很多意料之外的难题和风险,若是QA的工作(尤其是测试)进行得晚了可能会造成比较大的损失,也可能会增加后期修改、重构的成本。
Q5:关于DCR(Design Change Request)
在实际的开发过程中,我们该如何判断应不应该重构或重写呢?什么样的重构才是好的呢?该由谁来做这个决策呢,是开发工程师,PM,整个团队,或是用户?
在团队项目中,我们的项目也经历了重构和重写的阶段。重构主要是针对于前端的界面优化,重写主要是针对后端的原有功能完善和功能增量开发。关于判断应不应该重构或重写,书中关于DCR的方法我觉得比较有借鉴意义:首先是弄清楚问题在哪里,问题的影响,如果不修改会有什么后果,然后是对修改方案进行评估,讨论各种方案的优缺点和成本,最后进行决策。我想在这个过程中比较重要的是团队不能冲动行事,不能说一拍脑袋就加一个什么功能,而是要进行细节的讨论和分析;在alpha阶段的一些开发想法可能放在beta阶段实现会更好,如书中所说:“项目的当前阶段是一个阻尼振荡的过程,要收敛和稳定”。
关于什么样的重构才是好的,首先是改善既有代码的设计,在符合需求的前提下有项目的优化和发展;其次要能抗得住测试,而不能说越改bug越多;还需要考虑重构和重写的时间成本,若是因为重写或重构而严重影响到整个项目的进展甚至发布,可能就会得不偿失了。在我们的项目开发中,第一次重写可以说是由用户提出的,一开始没有实现相应的功能所以极限进行了功能增量开发(这也是由于我们前期对需求的分析不够到位所以导致了后期的重写);之后的对项目的优化,也就是重构是由团队做出的决策,大家都发现了项目存在的问题所以经过开会讨论决定重构。关于谁做出决策这个问题我觉得答案是不固定的,毕竟软件开发也不是死板的流程,期间有很多情况需要灵活处理,重要的是需要仔细评估有没有必要进行重构或者重写。
Q6:关于创新
在计算机行业发展迅速的今天,对新企业来说,是沿着既有技术本身发展,毕竟已经有了确定可行的市场,还是谋图技术革新、冒着比较大的风险追求”颠覆性创新“呢?”颠覆性创新“在大企业中又是否存在局限性呢?
我觉得对于新兴企业来说,沿着既有技术本身发展是比较保险的做法,但是会很难出彩;追求“颠覆性创新”的挑战性更大,对小企业来说也没有那么多的试错机会,可能需要有破釜沉舟的勇气,但是高风险也意味着高收益,颠覆性创新也有着突出的财富杠杆效应。再结合现在创新也是国家战略布局的重点,我想或许谋图创新会是比较好的选择。对于大企业来说,有了技术和资本的积淀,以及源源不断的人才流入,可能会更容易实现“颠覆性创新”。
在实践中学习知识点
1.需求
在需求分析阶段,主要学习到了NABCD模型的方法。首先需要了解用户的需求(Need),抓住用户的痛点,同时也要分析市场上是否有相应的需求;其次是确定做法(Approach),明确已有的技术支撑以及客观的优势条件;第三点是分析好处(Benefit),所做的产品会给用户带来什么样的体验以及为什么会吸引到用户;然后是竞争(Competitors)分析,知己知彼,百战不殆,看似是分析竞争者,其实也是在看清我方的优势和劣势;最后是推广(Delivery),让更多的用户知道我们的产品。
2.设计
设计阶段主要是学习到了WBS的工作分解方法。在确定好需求后,团队确定了功能规格说明书,技术规格说明书以及任务分解,从比较宽泛的应用场景到实现技术再到分配给每位成员的细节的工作都是逐步实现了整个项目的细化和工作分配。WBS可以清晰地表示项目各工作之间相互联系的结构,也可以组织定义整个项目的范围,在团队项目中有效地帮助我们理清思路,确定方案,条理清晰且高效地完成开发。
3.实现
在实现阶段主要是学习到了更具体的技术。比如在alpha阶段我是前端的成员,在开发中接触到的是react框架,并且是在开源代码的基础上进行功能增加,边学习边进行编程的过程让我更快的上手了代码;beta阶段转入后端,学习到了如何在python中调用其他的API以实现自己的需求;团队开发代码管理是在github平台,我学习到了之前不曾接触到的github操作,也在代码规范方面有了更强的意识;在这个过程中我也更深刻的体会到了软件工程中文档的重要性,文档是开发人员交流沟通的重要渠道,好的文档在开发中可以起到事半功倍的作用。
4.测试
测试阶段主要的收获是学习到了单元测试这样一种对最小可测单元进行检查和验证的测试方式。之前测试自己写的代码都是直接构造样例,很莽也很暴力,并且可能无法考虑到各种特殊情况;单元测试的测试粒度很细,小到一个类、一个函数,它可以确保一个程序模块的行为符合我们设计的测试用例。在将来修改的时候,也可以极大程度地保证该模块行为仍然是正确的。同时回归测试和压力测试在软件测试中也是必不可少的一部分。
5.发布
发布阶段主要是感受到了推广的重要性。我们的团队在推广上有一定的局限性,由于项目的典型用户面向的不是学生群体,最后推广的时候也只是采用了“打广告”以及拉熟人的方式来增加用户量,并不是基于产品本身的吸引力,还是有一点点遗憾的。
6.维护
维护阶段主要是需要根据用户反馈对项目进行错误修改、优化等项目完善。维护大概可以分为两个方面,一个是软件代码,一个是环境部署。在我们的团队项目中一开始有用户反馈速度太慢,体验不佳,主要原因是服务器在国外,在维护阶段我们将代码重新部署到了国内的服务器,很好的解决了这个问题。而修改代码主要是针对在测试阶段没有发现的bug纠错,一般在这个阶段发现的错误不会影响系统的正常运行,其维护工作可随时进行,这也让我感受到了前期测试工作的重要性。
理解和心得
个人项目
个人项目需要完成的是求几何图形交点,功能实现的难度并不是特别大,主要精力也是花在了测试和优化上。感觉个人项目主要是对PSP流程的学习和熟悉,在这个过程中也学习到了一些基本的概念和技术,比如单元测试、回归测试以及效能分析工具等,为之后的结对编程和团队项目打下基础。个人项目中最深刻的感受是一定得先进行具体设计再进行编码,这也是之前面向对象课程所强调的,比如直线和圆怎样抽象成类、采用什么容器对点进行管理等都是需要先进行细致的设计,这样也可以在之后的自测中大大节省debug的时间。
结对编程
结对编程在个人项目的基础上增加了射线、线段以及GUI,我和队友分工也比较明确,并且由于是认识的同学,所以在结对编程中除了线上的一些不方便之外没有很大的阻碍。在结对编程中我主要是体会到了模块接口设计的重要性,比如core模块是为UI和命令行程序提供计算和错误处理功能的,接口定义一定得清晰明确;同时也了解到了 Information Hiding,Interface Design,Loose Coupling 等的接口设计原则。
我觉得在结对编程中,最重要的是保持交流的高效性。虽然需要调整自己的节奏来和队友磨合,但是如果在结对中交流沟通得比较充分的话,两个人的工作效率肯定是会比一个人的高,和队友一起交换思路商量着并行进行工作,会收获到更好的设计质量和代码质量,也会有更多的责任感,在开发中少走很多弯路;在这个过程中心态也很重要,结对工作能带来更多的信心,尤其是在遇到bug的时候,会让自己的压力和焦虑感减轻不少(再次感谢队友平和、不急躁的心态让我学到很多)。
虽然是第一次接触结对编程,但是体验还是很棒的,以后如果有类似的开发情况,我也会很愿意选择这种方式。
团队项目
这是我第一次比较规范的进行团队项目合作,每位队友都很积极,互相帮助,解决了很多意料之外的问题。在alpha阶段我在前端组,首先和队友一起梳理了原项目的代码逻辑,再进行开发,从一开始只会简单的css和html到了解react框架,在开源代码的基础上进行也让我体会到了代码规范和注释的重要性;beta阶段转入了后端组,对python的代码编写和单元测试有了更深刻的体验,也感受到了认知服务的优越性。前端到后端,虽然接触到的技术不同,但是软件工程开发的规范却是不变的,比如开发文档的必要性,要想让团队里其他成员很快的了解到自己所做的模块,不可能直接去阅读代码,规范的文档就起到了非常重要的作用。
我觉得在团队项目中,无论是队友之间还是和用户之间,高效的沟通都很重要。跟队友及时的交流可以很快的解决技术难点,准确的定位开发目的,提高软件质量;跟用户细致的沟通可以明确需求,减少后续修改重构的成本。一开始其实觉得每日例会非常繁琐,后来才渐渐感受到每日例会的必要性。每天的会议不仅可以督促团队里的成员完成自己的工作,保证项目的进度,同时也提供了团队交流的平台,可以及时反馈问题解决问题,进而保障软件的质量。
团队项目是课程前期理论学习的实践,在这个过程中我系统地学习到了相关流程和技术,收获颇丰,也感到很幸运和大家一起见证了一个项目的成长😀
小结
这学期所有的课程都是在线上进行,软件工程课也即将结束,翻看自己一学期以来写的博客也可以清楚的感知到自己的成长和收获。之前相关专业课的学习似乎是以一个比较窄的视角编写代码,在软件工程中,学习到了很多代码之外的理论知识,比如软件开发流程、TSP、敏捷开发等,也在个人项目、结对项目、团队项目中进行了实践,都是十分宝贵的体验。 最后,希望软件工程课程越来越好(撒花~)