截止到目前,我们的软件开发Alpha轮已经结束。在软件工程课所参与的结对编程、团队项目,是我第一次参与多人的软件开发项目,有许多体会和感悟。下面结合老师所布置的阅读作业来说说我的心得。
No Silver Bullet: Essence and Accidents of Software Engineering
没有银弹
很久以前我在朋友圈看过一则谣言,说是有一个硅谷的奇才设计出一种方法,可以把iphone上的任意两个应用合为一个,功能也合二为一。只要把图标随便拖一拖就产生新APP了,甚至图标都是新的。当然了,专业人士看这种谣言的第一反应都是:好扯…… 天真无知的我还专门查了一下,发现是风靡朋友圈的新谣言。为什么感觉很扯呢?亲身参与了软件开发,就能发现软件开发竟是这样繁琐的一件事,是耗费多少人多少工时多少协作才能产生的,绝不可能像工厂里的汽车一样,有个流水线就能批量生产了。这谣言鬼扯的地方就在于“有人开发了一种全自动的方法,可以自己产生实现不同功能的软件!”而《没有银弹》讨论的论题正是:不可能存在这样的方法,可以全自动或是大幅减小软件开发的难度。
作者将开发软件的困难分为次要困难以及根本困难。次要困难指的是我们可以克服的,不是与生俱来的困难。这部分的繁琐程度可以被简化,比如使用高级编程语言,统一大家的编程环境。然而根本困难是不能够有效克服的。这其中最大的困难就是复杂度的问题。软件是一个大型工程,并且要满足各种各样的需求,它是繁琐并且注重细节的。不像其他基础学科所追求的简洁普适、高度概括,软件工程所追求的就是实用,具体,满足不同需求。同时,因为计算机本身就状态复杂,具有不可见性,在其上运行的软件还需满足需求,配合不同状态,因此就更加复杂。“软件实体的拓展不仅仅是相同元素重复添加,而必须是不同元素实体的添加。”可见,新软件新功能的产生,也绝不是已有功能的简单叠加,已有代码的复制黏贴。
本文的作者是位大牛,站在很高的角度来说软件开发这个概念。作为一个学习者、参与者,在我的亲身体验中,我也很有这样的感受:软件开发不是一个容易的事,写好的框架、现成的工具,也并没有为我们节省量级上的时间。我们的团队在开发中并不是一帆风顺的,我们不断遇到各种问题。作为初学者,功能的实现也许是很核心的问题,然而功能间的耦合,程序的正确性,以及bug的查杀却是最耗费时间的。在一开始设计好的结构,在具体实现中还会遇到问题,并且因为运行的不可见性,查找问题在哪非常痛苦。
反对意见也有提出,有人认为作者太过于强调银弹,从而会使大家忽略那些确实会为软件开发带来好处却是次于银弹或是有可能成为银弹的方法。寻找这些方法,保持对银弹的热情是很有必要的,脚踏实地的同时也需要偶尔“仰望星空”。
Big ball of mud
大泥球
我非常喜欢大泥球这个名字,形象贴切,如同我在写这些程序时的心情。
大泥球指的是一种程序的框架设计:没有设计。为了实现功能而拼凑,用各种稀奇古怪或者非常笨拙的方法来完成程序。虽然显得没有逻辑,不够正统,却是一个经久不衰的奇迹。不知道在自有程序面世以来,多少软件、程序都是大泥球产物。在写大泥球方面,我认为我很有经验了Orz。虽然我倾向于把所有逻辑,构建框架想清楚了再写,然而当时间不够,任务紧急,或者写的时候不想走心,你不得不承认,大泥球写起来挺给力哈。然而接触大泥球也是大二下学期,程序得有一定代码量才涉及到考虑架构的问题。面向对象课程比较讲究代码的重用。我有一次在写一个作业的时候,一开始都是想得好好的,到最后发现时间不够了,有的地方实现还有问题。不行,也没有时间考虑重新组织结构了,那就一个方法里不停套循环吧……虽然最后功能也完成了,但当听说下一个作业是在此基础上继续添加功能,我的心情就像吃了个大屎球。这样写出的代码不具有什么可拓展性,都是一次性为了赶DDL所弄出来的权宜之计。最后我又重写了。这样的开发体验非常糟糕。
在此次团队项目中,虽然我不是负责后端代码的,然而我也从我们的PM那里听闻:有部分的后端代码已经套了好几层了。大泥球所带来的最直接的后果就是:bug多,复杂不好修复,程序可拓展性差。然而我认为出现这样的问题绝对是可以理解的。我们不仅缺乏知识,更缺乏经验。成熟的团队也有可能做出泥球来。然而同时我们要看到,人家有做得比我们好的团队,人家也是初次团队开发大项目,架构就能做得更合理。我们还需要在这方面继续努力,在开发阶段不能光求快,求能使,同时也要注意代码的质量。不能一个上传图片的代码哪里需要哪里贴。Beta阶段也许可以考虑如何能在完善整体的架构。
The Cathedral and the Bazaar
大教堂与市集
大教堂与市集的方式开发自由软件,这个描述上的对比很有意思。以市集方式来比喻新出现的这种开发软件的新形式非常贴切。在我看来,市集模型非常不可思议,而且Linux居然成功了,就更不可思议了。很难想象世界各地的程序员没见过面(没开过会!)就一起开发出了一个可用的操作系统。相比较而言,我们的项目很小,可能不涉及到他是大教堂还是市集的问题。第一,如果我们的项目是教堂,他肯定不是大教堂。第二,我们的市集太小以至于不会有人来光顾市集。如果非要分类,我想可能更偏向于教堂。我们的PM负责整个项目,并且把关代码的质量。然而如果以后有机会,我想我会非常乐意体会参与一下市集,很多人共同开发一个开源项目,无数双眼睛审视代码和其中的bug,参与到这种活动中来有种为全人类做贡献的感觉。
市集虽好,却也不乏反对的声音。有人认为市集缺少一种“集中的智慧”。有人看到,这种开源项目的热情带来的是质量上的参差不齐以及缺少整体性的规划。“所谓质量,只有在某人对它负责时才有意义,而这个“某人”只能是一个人,不能是几个人——二重奏除外。”既然是开放的市集,你就无法阻止有人可能来卖次品,这不是他们本意,但这真是不同人不同水平的问题。大教堂与市集这本书的作者好像是非常认同集市的,并且认为未来会是集市模式的天下。我认为他们的未来会各有各的市场和各自的天下。市集模式所带来的效应以及这种新模式所具有的鼓动性使人很难放弃他,同时,传统的大教堂依然是有诉求的人们每周日会固定礼拜的地方。教堂模式的高质量试用于那些对稳定性有要求的商业软件。这种需求不会削弱的。
瀑布模型
瀑布模型核心思想是按工序将问题化简,将功能的实现与设计分开,便于分工协作,即采用结构化的分析与设计方法将逻辑实现与物理实现分开。将软件生命周期划分为制定计划、需求分析、软件设计、程序编写、软件测试和运行维护等六个基本活动,并且规定了它们自上而下、相互衔接的固定次序,如同瀑布流水,逐级下落。
瀑布模型图例
瀑布模型的优点
(1)为项目提供了按阶段划分的检查点。
(2)当前一阶段完成后,您只需要去关注后续阶段。
(3)可在迭代模型中应用瀑布模型。增量迭代应用于瀑布模型。迭代1解决最大的问题。每次迭代产生一个可运行的版本,同时增加更多的功能。每次迭代必须经过质量和集成测试。
(4)它提供了一个模板,这个模板使得分析、设计、编码、测试和支持的方法可以在该模板下有一个共同的指导。
我们的开发过程基本上就是采用了瀑布模型并且按每个阶段来实施的。然而在软件设计与程序编写上,因为我们也不知道我们的团队可以达到什么程度,因此我们的应用在实际编写时是不断增加需求和功能的。这点与瀑布模型有些不同,然而瀑布模型对需求更改是不利的。
敏捷开发
“敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。”
我们的项目还是采用了一些敏捷开发思想的。比如我们把项目分成了许多小功能,并且随着写随着添加功能。在这个APP中一共有几个页面,每个页面完成什么功能,都会提前设计好。每个页面都是从前端写xml到后端完善功能,保证每次的页面里所有功能都实现了,就继续往下走。软件一直都处于可使用的状态,只是功能不完善。
软件工程的方法到底有多少用处?
毫无疑问,应该回答:有用。然而有多少用处?对于刚入门的人来说,有一个方法总比没有好,没有方法像没头苍蝇,无从下手。然而具体的比对比如:瀑布式比敏捷式好多少?这种问题脱离具体环境谈是没什么意义的。方法应该是灵活的,因为创造方法的环境和使用方法的环境不可能完全一样。又回到了第一个问题:软件项目是复杂的,没有银弹,没有万用药。软件工程的方法有用,缩短了开发周期,是将次要问题的难度降低了。而实在的,抛开形而上的问题,剩下的干货却还是依靠于开发工作者的能力。软件工程的方法想讨论的是一个适用于大量项目的方法,这注定了他只能规定一下抽象的形式的开发方法。没有一种工程方法能具体的告诉你:开发软件用C++! 没有。然而就目前的方法,好的我们是要学习和努力适用的。这些方法能让你的团队在开发无论什么软件都能有章可循。在能节省时间的地方为团队节省时间。