一、软件工程M1/M2总结
写下这篇总结的时候,我们的软件项目尚未完工。虽然尝试申请了延期答辩,但最终未能成功。这意味着,我们的项目能否正常发布已经处于了一个微妙的状态。可能可以,也可能不可以。只能尽力而为了。
整个一学期的开发下来,我在软件工程方面体会最深的是成本问题以及技术债。以前写的项目往往没有特别严格的deadline,很多是个人的随兴而写的东西,写不动了就不写了。又或者是作业,最多也就那么一千行,怎么都是可以写完的。而软件工程这门课的团队项目,7个人,一个完整的网站,特别是对于我们这个由4个组合作的大家伙,和以往写的东西完全不是一个概念。因此,就需要团队管理,需要设计,需要每一个人的努力。
先说说成本问题吧。我们的项目从一接手就做出了一个非常“大胆”的决定,我们决心完整地重写这个项目。原因我们自认为很充分:学长代码里坑多,分析代码需要很多时间,技术栈太老等等。现在看来,这个决定有些初生牛犊不怕虎的感觉。当时没怎么纠结就定下来了,我们并没有觉得重写的成本有多高,而且对于自身团队的力量极度自信。如果现在要我重新来做这个决定,我肯定不会再像当初那样轻率,虽然,我依旧可能倾向于用全新的技术栈重构整个项目。迁移方案,如何与其他组兼容协调,开发能力,团队组织能力等等,各方面因素都应当考虑进去。而当时,仅仅考虑了很少的几个点,就决定了重写整个项目。直到后来才慢慢地理解到,有些东西的成本和代价是相当高的。
另外,除了开发成本之外,我还亲身体会到了软件的修改成本以及技术债。我们的第二个阶段几乎重构了所有的代码,原有的HTML和部分Python代码大多都迁移成了JS/JSX代码,换句话说,我们的M2阶段几乎把所有功能又都重写了一遍。之所以会产生这样一个结果,是为了解决第一个阶段所遗留下来的一个问题:四个组之间的衔接。在最初设计时,我们没能及早地意识到组间连接的复杂性。在M1阶段,当我们真正遇到衔接问题时,并且被这一问题卡住了以后,才发现这个问题的严重性。虽然靠着团队的努力,顽强地完成了第一阶段的开发,但也为第二阶段留下了很大的问题:我们必须在第二阶段完成组间衔接。作为架构师,在重新做设计地时候才发现,想要修正最初在设计阶段犯下的错误,成本相当地高。为了和APP组共用后端,我们需要将整个基于Django模版的网站迁移为基于ReactJS的单页应用,同时,将之前的搜索和数据部分大部分改为和Solr衔接。这样才能和其它组完全衔接上。这一方案对于四个组来说是相对改动较小的方案,前两个组只需将结果插入到Solr中即可,但前端,也就是APP和网页前端都需要做大幅的变动,以适应一个统一的后端。而其中,又以网页端的改动幅度最大。
其实,也并非没有简单地衔接方案:比如直接开发段小程序,把第二组的数据库的模型转换下插入到我们的数据库中。这样,开发成本能够小很多。但手头满满变成个大泥球的代码,特别是混乱地HTML和JS,都在告诉我,如果就这样写下去了,那么,以后会越来越没法维护的。也许是处于所谓的情怀或者一些说不清楚地情感,最终,我们还是决定采用一个大胆而完美地解决方案。也许代价很高,但是架构的可扩展性以及可维护性都很好,技术栈也很新很漂亮。这样,当下一届接手的时候,就不必再为如何完美地接上,如何扩展现有功能而苦恼了。而且,我们希望,数年之内,这一架构可以很好地适应新的需求以及技术热点:分布式、云、前端模式的变化等等。
最后,我想总结的是团队。M2阶段对于团队是一个巨大的考验。M2阶段由于时间严重不足,对于团队的压力非常大。有些团队甚至就集体放弃了。或者只剩下一两个人还在顽强地支撑着团队。我们的团队能够顺利地将页面重构成单页应用,与我们这个团队的特点也很有关系。我们团队的所有人都非常靠谱,这种靠谱不光是态度上的,同时也是能力上的。团队成员在能力上很强,能够应对新技术的挑战。另外,每个团队成员都很负责人,交予的任务都能尽全力去完成。所以,团队能够接受一些新的技术。这次软工的经历使我深深意识到,有怎样的团队,就做怎样的事情。如果团队本身的能力有限,那么在最初设计方案的时候就应当考虑到团队能力的问题。
二、阅读作业
提问博客链接:http://www.cnblogs.com/fzyz999/p/4831068.html
请说明哪些问题现在自己已经清楚了,请阐明一下,是如何通过看书,实践,或者讨论弄清楚的。
1. 软件工程是否是更为正确、可靠的软件的正确方向?软件工程的目标是使得通过工程化的方法,可以在合理的时间内,以足够高的质量完成相应的目标。但 最近函数式语言的重新流行也使人不得不思考这样一个问题:构建正确的软件能否存在其他的方式?目前的一些纯函数式语言甚至可以采用一些工具进行机器辅助证 明。我们如果能用形式化的方法描述该软件的行为和特性,之后便可以让机器辅助证明软件是正确的。例如seL4这个微内核就是采用这种方式证明其正确性的。 相较于单纯的测试而言,这样的方式得到的程序更为可靠。那么这是否是未来发展的一种主流方向呢?软件开发是否会逐渐由手工艺转向一种更为工业化的模式?我 们不仅可以创建“足够好”的软件,更能创建完全正确的程序?
未弄清。感觉这个问题很大。经过软件工程的学习,感觉会的东西更多了,理解的知识也更多了,但软件未来的发展方向如何,还是没法给出自己的观点。也许随着学习的进一步深入,理解的东西更多一些以后,就能够看清这个问题的答案了。
2. 在个人软件开发流程中,代码复审的意义究竟有多大?代码本身就是我们自己写出来的,很多在我们设计时就存在的逻辑错误,通过复审并不见得可以发现。毕竟,我们一度认为那些逻辑是正确的。个人的复审仅仅能够处理手误或者是一时的疏忽,但对于一些根本性的设计问题,也许无从下手。那么如果我们直接进 入单元测试等阶段,直接通过调试错误来定位代码中的逻辑问题,是否比复审更具有性价比呢?
这个问题助教在评论中给了一个答案,我觉得这个答案很合理。过一段时间重新审视一下自己的代码是很重要的。经过软件工程以后也有这个体会,项目最初的时候很多东西不太会用,后面慢慢用得熟了,理解得也多了,再看之前的代码,确实会感觉自己之前的代码有些不好。因此,个人软件开发流程中,代码复审也是有意义的。
3. 针对最近频频爆发的信息安全问题,我们能否从软件工程的角度提出一些应对措施?比如在设计、复审等阶段是否存在一些方法可以大幅提高软件的安全性?
如果安全是一种必须的需求,那么我们在最初设计的时候,就应当将安全作为一种需求。在设计和分析阶段需要进行相应的设计。另外,老师在评论区的回答也很值得借鉴。特别是最近XCode Ghost爆发以后,我们确实应当尽量从官方网站下载相应的工具软件。
4. 在《构建之法》中,我们关注的主要是一个一般的开发团队所面临的一些问题。那么对于像开源社区这种与传统的商业软件团队有明显区别的团队,在某些方面是否会有不同、乃至完全相反的情况发生?开源项目中的质量控制、bug修复、用户体验等等各方面是否会有截然不同的一些样貌或方法?
这个问题依旧没有弄明白。个人虽然很热爱开源,但未能参与过大型的开源软件社区中的开发。对于开源社区的模式缺乏了解,所以这个问题依旧没有得出答案。
5. 用户需求往往是在不断变化的。我们应当如何把握软件在哪些方面因留有扩展的余地?或者说,怎样的设计是合理的?怎样就会引发过度设计?如何把握好扩展性的度?
对于有需求变化的,我们也许应当采用快速原型的方法。先快速地将软件做出来,然后让用户自己发现问题和需求,之后,根据用户的建议,来决定哪些部分可扩展,那些地方不需要扩展。
请问你们在项目的 需求/设计/实现/测试/发布/维护
阶段(一共6 个阶段)中都学到了什么 “知识点”, 每个阶段只要说明一个知识点就可以。
需求阶段:需求分析需要完整地分析出来哪些功能是重点的,哪些功能是可以砍掉的,用户真正的需求是什么。
设计阶段:设计阶段尤为重要!设计阶段尤为重要!设计阶段尤为重要!重要的要说三遍。特别是接口设计,架构设计等等,一旦出错后面将会面临极大的改动。
实现阶段:实现阶段重点在于控制进度。如果进度控制不好,可能最后项目就会崩溃或者跳票。
测试阶段:测试阶段重点在于自动化。自动测试等等很重要。
发布阶段:发布阶段发布的产品必须经过严格的测试,否则给用户的体验会非常不好。
维护阶段:维护阶段其实极度依赖测试,必须通过严格测试保证维护后的代码不退化。