The skies await.
这个作业属于哪个课程 | 2021春软件工程实践|W班(福州大学) |
---|---|
这个作业要求在哪里 | 软件工程实践总结&个人技术博客 |
这个作业的目标 | 对自己在一学期以来的软件工程实践课程中学到的东西进行总结 |
其他参考文献 | 无 |
第一部分:课程回顾与总结
给自己的总结博客起一个有意义的标题
The skies await.天空待我翱翔。星际争霸2神族单位Phoenix(凤凰)的台词。
因为很合适就拿来用了,天空待我等翱翔,而我们要做的首先是丰满羽翼,然后才能展翅翱翔。
这是我们在软件工程实践中努力去做的,也是三年以来、未来一年、甚至于到更久更久的未来都是我们要做的。
The skies await.天空永远在那里静静的等待,飞出怎样的风采取决于我们自己。
给出以前提问题的博客链接
请尝试对自己曾经提出的问题进行解答,并阐明,是如何通过看书,实践,或者讨论弄清楚的
1.《构建之法》中提到一个很有趣的例子:一个程序员入职后认为之前程序员写的代码看不懂、无法维护,于是决定重写。后来被老员工告知这份代码就是去年新入职的程序员受不了之前的代码而重新编写的。这也涉及了我一直以来的疑问,事实上,在三年的学习生活中,我也遇到这样一个现象,由于代码的排版和编写习惯、变量和函数的取名习惯等等诸多原因,比起自己写的代码,要看懂他人写的代码要花费更多的时间和精力,即使对方的代码符合规范也是如此,在学习中我们最多使用数百行的代码,要看懂他人的这些代码已经非常费力,而在实际项目中,代码的行数想必以万为基准,实际工作中程序员接替前人的代码进行维护和添加或者修改功能的时候到底是如何顺利理解和继承前人代码的呢,只靠单薄的注释能够完成以万为单位的代码交接吗?
在团队作业的实际工作中,我们进行分工之后,往往并不需要看懂甚至不需要知道对方的代码是什么样子的,仅仅通过协商好接口,通过了解对方提供的函数名、需要的参数以及返回值就可以进行工作的衔接。在将项目制作完成后,通过接口文档和代码中简洁的注释,某个功能的代码在哪个位置、需要什么参数,输出什么数据,大家都了然于胸,但是对于具体的实现代码是如何做的,只有负责该模块的成员才完全清楚。通过接口协商,我们可以完全不需要看懂甚至不怎么需要看对方的代码就能互相衔接并实现完整的功能,一定程度上规避了看别人的代码要花费大量时间这一事情。然而,对于需要进行工作交接的人来说,就无可避免的需要完全理解对方的代码并具备在此基础上进行修改和增加相应功能的能力。虽然我没有换组,但是通过本组的交换情况和与交换成员交流,理解到交接工作要从项目本身,接口,功能、代码编写逻辑和情况等各种方面都要完成交接。虽然要花费很多精力,但是最终是可以顺利完成的。
2.《构建之法》中提到,“很少有人能够在学校中掌握这么多知识后才毕业找工作,随后把技术应用在实践中。”事实上,即使是已经大三的现在,我认为我们学习的内容距离真正在市场上使用的软件项目差距是天差地别的级别,还有一年我们就将毕业,但是以目前的状态,我认为只依靠目前课程教授的内容,即使进入工作岗位我应该也无法发挥非常大的价值。从中衍生出的我的问题是:“毕业后,如果我们试图竞争某个工作岗位时,到底应该具备何种程度的能力?”以及,“即使成功拿到某个工作岗位,在入职后面临所学知识和实际项目的复杂程度天差地别的状况,我们会被分配怎样程度的任务,需要做哪些学习,需要花费多长的时间才能完成从持有学校教授的基础知识到可以进行在市场上流通的实际项目的维护和开发这样一个跳跃呢?”
在团队项目中可以看到,有人选择了做游戏,这需要unity和相关技术;有人选择做微信小程序,这需要小程序相关的制作技术……这些都是在实际生活中被广泛应用的实用型技术。这些在学校课程中完全没有教过的东西,我们往往能通过教学视频或者百度搜的帖子等,在一天两天内理解并上手这些制作技术,着手进行开发,并且在后续的开发过程中逐步解决遇到的困难,最终完成项目开发。这恰恰正是我们具有能够把理论有效地转化为实践的体现。我们之所以能这么容易习得实践性的开发技术,很大一部分原因是因为课堂中教授的基础内容使得我们具有牢固的基础,支持我们进行这样的学习。所以这个问题其实已经解决了——大学课堂中学习到的似乎离市场中实际使用的技术天差地别,然而这些知识构成的基础,会使得我们在自学和掌握实践技术的时候如鱼得水。
3.《构建之法》中提到的“结对编程”的概念让我很感兴趣,如书中所说:“学校一直教导我们编程是一个人的事情”,正是如此,即使是团队项目一般我们也会分成数个模块,在协调好模块之间的接口的基础上,再将每个模块都各自交付给某一个人完成,最后组合成完整的程序,而书中则提到了结对编程的诸多好处。由此我提出的问题是:“结对编程只是一个听上去美好的概念还是一个具备实用性而业界普遍使用的人员分配方式?”。书中以跳交谊舞为例详细的阐述了结对编程中搭档的各个磨合阶段,说明搭档需要时间进行磨合。因此,在上个问题中:“如果答案是后者,这样绑定某两个程序员会不会使得人员管理出现问题?如果某一个长时间进行结对编程的组合,出现其中一个程序员被解职等情况,另一个程序员再重新与其他人进行结对编程搭档会不会适应困难?”
通过搜集资料发现,结对编程在国内并不流行,两人合作解决一个问题,大多数情况下出现在“老带新”这样的师徒情况下,利于新手一方迅速熟悉业务流程,与严格意义上的结对编程定义并不一致。查询的资料中,对于出现这样结果的原因大致分为两点:第一点是人力成本问题,公司的最终目的是追求经济利益,结对编程将两个员工编成一组来解决一个问题,理想情况下或许能够提升代码质量,然而终极问题是结对编程同一时间终究只有一个人敲代码,其经济效益能否超过两人分开负责两项工作所能造成的经济效益存疑,公司领导层往往不愿意将两个人当一个能力更高的人使用,他们倾向于一个人当两个人用。第二个问题在于结对编程的匹配问题,结对编程对于两人的适性要求很高,这往往很难达成。
4.《构建之法》3.3节中提到一个招聘C#程序员的例子,提出 “他把时间都花在‘解决(低层次)问题’上了”,这样的程序员当然不能说是精通C#。我个人学习并偏爱java,能使用java写的程序都使用java,因此构建基本的类、java的循环、条件等语句当然也能不用大脑就自然写出来,可这就算 “精通”了吗?当然也不算吧。书中提出的:“‘提高技能’就是通过长时间的练习来使得不需要动脑就能解决低层次问题”,我认为并不全面,我能够不用动脑就能书写出基础语句和循环条件等语句,我就已经精通这项语言了吗?当然不是,可继续长时间练习更上一级的内容,我就能变得精通吗?也不尽然。“长期练习到不需动脑”说到底只是在固化大脑和身体本能,让我们想到“循环”的时候不需要思考就能敲出重复过很多很多遍的循环语句,可是当我固化了更上一级的内容,将某一个问题的算法作为身体本能记录下来,当遇到这一类问题的时候没有思考脑中就会自然蹦出这一算法并书写,这真的是一件好事吗?编程就是在用代码解决实际问题,书中所说的“提高技能”的极致也不过只是不断重复和累加前人的做法来堆砌出程序,丧失了自己的思考和创新来做程序算得上是一种提升吗?这是我与作者这句话理念相悖的地方。
这个问题现在看来感觉就是想太多了,仔细分析之后发现这样的想法已经快到达想要创造效率更高更有效的算法这一地步了。在实际开发过程中能够应用上学习到的算法来提升效率就已经很了不得了,在互联网环境下,面向百度编程,参考其他人的代码并没什么错误,这能大幅提高开发效率,只要针对自己的项目进行优化和修改就可以了。即使是游戏的核心功能,例如卡牌所应拥有的属性,拼接如何实现,如何根据拼接的结果计分等功能,只要提出了可行的方案以后,具体实现参考网上的代码也没什么不好的,最后能按方案实现,能跑起来不出错,效率不拉跨,他就是好代码。
5.《构建之法》在4.3.4中对于“如何处理C++中的类”,这一问题,提出“仅在必要时,才使用类”。在我过去几年的学习生活和了解中,面向对象的思想是相当好用而且受到市场承认的。我认为类的概念作为面向对象编程的核心概念,正是C++语言比起C语言来得更加优越的核心之一,类所体现的面向对象思想和各种相关内容毫无疑问是有用而且有必要的。而《构建之法》却提出“仅在必要时”使用类,却体现出了并不是很想使用的意愿,这到底是为什么?
这个问题我至今也没解决,unity的游戏制作,在编写游戏脚本的时候也一直使用类,我觉得这很好用,不懂为什么构建之法这一小节中的语气似乎并不推荐。
6.《构建之法》的第4章中详细阐述了结对编程的概念和它的诸多好处,然而具有诸多好处的结对编程“只是一个美好的概念还是业界普遍使用的一种开发方式呢?”这一点我在上次的提问中也有涉及,但是没有得到回答。我在上网查询了许多资料后,发现“结对编程”在国内似乎并不是一种公司乐意使用的方法。书中如此详尽地介绍了如此之多结对编程的好处,可它似乎并没有被市场接纳,到底在哪个环节出现了问题呢?
这个问题的提出是由于当时的并没有得到解决所以二次提出了,现在我悟了,详见第三问的解答。
7.《构建之法》16.1中提及,“改良式”和“颠覆式”的创新,改良式的创新往往会受到欢迎。虽然颠覆式的创新往往更能更大幅度的改良技术和推进历史进程,但却因为会引起不安而受到抵制,就像文中提及的“电话”颠覆“电报”一样。可对于软件开发而言,能否被用户广泛接受可以说是产品的生命线,因此,作为软件开发从业者的角度来看,是不是比起“颠覆式”的创新,更多地尝试“改良式”的创新会更合适呢?
现在我认为是这样的,在一学期的软件工程的学习中,我认识到改良式的创新是更能够被人接受并且欢迎的。最经典的案例就是“山烛”小组,他们在一开始的原型展示阶段,由于展示的网站外观和B站有一定程度上的相似而受人质疑,但是他们当时反驳说:“这也证明这样的原型是能够被人接受且受欢迎的。”他们以B站这一成功案例作为基础,进行了符合自己项目的修改,完成了让人感觉非常舒服的界面和交互设计,事实上,他们的最终成品也受到好评。软件制作是需要大量时间、资金和人力成本的,比起“颠覆式”的创新,在已经被证明受欢迎的模式上进行改良会更受青睐,也往往会达到更好的效果。
8.《构建之法》第6章提及敏捷流程的概念,敏捷流程作为一个与通常的编程流程几乎完全不通的流程,书中花了大量的篇幅来介绍它的好处,可是我依旧无法理解,这种“没有计划、没有文档、马上写代码、随时发牢骚”的流程不正是我们在学习软件工程这一门课之前,写作业的时候用的流程吗,事实证明我们写的非常痛苦,成品也并不十分优秀。这样的流程不正是我们学习软件工程后要来避免的东西吗?这样的流程真的具有实用价值吗?
事实上我们也并没有采用敏捷模式来进行团队项目开发,而是用瀑布模式进行。我通过查阅资料后的理解就是,敏捷模式属于返璞归真了,“没有计划、没有文档、马上写代码、随时发牢骚”在我们学生用来写作业的时候写的很痛苦,但是对于一个所有成员都具备极高素质以及道德和职业操守的团队来说,它能够将团队的价值发挥出来。
做中学
请问你在项目的需求/设计/实现/测试/发布阶段(一共5个阶段)中,每个阶段收获最大的知识或能力是什么?
需求阶段:
认识到需求阶段真的很重要,要认识到用户需要什么,我们能提供什么,比起现在市场上已经有这方面的产品,我们比起他们更关注哪一部分的需求,我们要针对这一需求提供什么样的功能,能让用户用的舒服从而选择我们。需求分析是支持整个项目的基础,没有正确而精准的需求分析而做出来的项目也只是无人问津的废品,还要消耗人力物力和时间。
设计阶段:
设计阶段主要是界面原型和功能的设计,在界面原型的设计上使用了Axure RP来进行原型设计,托课程中几次原型设计相关的作业的福,现在已经能较为熟练地使用这一软件进行原型制作了。在我们所制作的游戏项目中,最难也最核心的部分在于功能的实现,作为一款在现实中已经有的桌游,我们要做的实际上是将这款游戏通过编写代码在电脑上呈现出来,让处于不同位置的人能够不必见面就能一起游玩这款桌游。在人脑中非常容易理解和使用的卡片拼接、计分方式、放置旗子等游戏动作在代码层面实际上非常难以实现,我们必须在设计阶段就把卡牌应该具有什么样的属性和方法,如何让游戏能够判定是否能够进行拼接,拼接之后怎么样将连起来的部分判定计分,旗子的放置如何处理等各种方面进行考虑。在设计阶段花费大量时间讨论和思考如何进行游戏功能的设计和实现,让我们在后续开发阶段能够不迷惘地每天推进项目进程。我认识到好的设计能够使得开发事半功倍。
实现阶段:
实现阶段主要就是游戏界面的具体制作和美化,游戏脚本的编写和优化。这一步骤我们的项目主要是通过unity完成的,我通过这一次的项目初步掌握了unity的使用方法,能够亲身参与一款游戏(虽然实际上比较粗糙)的制作让我感到十分满足,从unity的使用方法,例如如何将游戏脚本与控件绑定,如何编写游戏脚本实现功能,如何通过unity制作和美化游戏界面,如何进行前后端接口的衔接,团队沟通的重要性等等,这一个阶段让我学习到了数不清的东西,具体都在之前的开发记录中了。
测试阶段:
测试阶段我活用了软件质量与测试中学到的部分知识,让我对书本上的知识有了更加深刻的了解。例如单元测试,这门课程中wordcount的作业是我第一次学习并使用单元测试,以前针对程序作业等做的测试就嗯一遍遍打开关闭程序,纯靠手敲数据来测试,现在看来实在很呆。还有黑盒测试和白盒测试,我之前还有些疑惑为什么要分成这两种,后来导出可运行的游戏包之后发现,原本在编辑器内正常使用的提示框全部无法显示,查询后才知道原本的提示框代码只在unity编辑器内生效,在实际游戏中生效的提示框代码是另外一种。在白盒测试中没有出现问题的部分,在黑盒测试中出现了问题,这个分法实际体验后发现十分合理。现在还学会了使用自动化测试工具。
发布阶段:
发布阶段,对于我们制作的游戏来说其实就是导出可执行的游戏包然后把安装包挂在官网上,因为是端游,也不能挂在应用商店之类的地方,要挂在Steam之类的地方上吧,小团队制作比较粗糙,对比steam上各种3A大作也感觉不好意思。说实话没什么可说的东西。
结合自己在个人项目/结对编程/团队项目的经历,谈谈自己的理解或心得。
1.需求和设计阶段非常重要,能否找到并抓住市场真正需要的东西几乎在一定程度上决定了你这个项目是否能够成功。良好而完备的设计能够让开发事半功倍,如果没有做好设计——试想一下如果我们没有经过最初的功能实现方案的敲定就开始开发,几乎可以预见在游戏流程的例如放牌和计分等核心功能处卡死然后推倒重来的未来了。
2.接口文档真的很好用。在这门课以前,即使是有团队项目开发的作业,由于难度不高而且规模较小,从来没有使用过接口文档,在这门课以后才开始使用。这玩意儿真的很好用,通过大家协商接口并登记在接口文档后,成员可以在其他人的具体代码对自己透明的情况下依旧毫无阻碍顺利地进行功能编写,并且与其他人编写的功能无缝衔接,只需要看接口文档的那一点信息,就可以顺利地做出整个项目。
3.团队沟通很重要,无论是开发前的讨论,或是接口的协商,或是每天的任务完成进度报告会议,都对任务的推进产生了肉眼可见的良好影响。
4.测试很关键。对于编写者本人可能不好发现甚至无法察觉的bug(比如那个离谱的只能在unity编辑器内才生效的提示框亦或者屏幕大小不同会由于没有自动适配而造成界面控件位置错乱),不经过测试是无法发现的。良好而全面的测试可以极大的提升产品发布时的质量和用户体验。
第二部分:个人技术总结
在Unity脚本中如何向后端服务器传递、接收与解析Json对象
概述:在前端与后端进行数据交换的时候,往往都采用将数据封装成Json对象进行传输。该方法是在unity脚本中向后端服务器传递、接收与解析Json对象的方法。