----沉痛悼念巴黎恐怖袭击中的死难者,并对一切形式的恐怖袭击发出最恶毒的诅咒与最强烈的谴责!
1.No Silver Bullet: Essence and Accidents of Software Engineering
by Frederick P. Brooks, Jr.
初次了解到银弹这一概念,是在名侦探柯南中,在一个假面推理派对上,柯南由看到了一个头戴狼人头套的人使用银质餐具而对他产生了怀疑,从而成功侦破了一起蓄谋已久的杀人案,从那时起我了解到了狼人与银弹的渊源。这次的这篇文章,一上来作者就提出了一个夺人眼球的观点——软件工程就像狼人一样。他之所以会有这样的看法是因为,在一个项目中,落下的进度,膨胀的预算,以及有缺陷的产品,都会给我们带来很大的困扰,让我们恐惧,这也就是为什么我们急切地盼望着一颗能够将“狼人”一击致命的银弹的产生。
然而作者认为,从软件工程的性质本身看来,银弹是不会存在的。接下来作者就从多个角度探讨了为什么不可能会有银弹的存在。
他从软件工程的本质出发,阐释了自己的观点,在这一部分,我颇有感触。
在过去的一段时间里,大家都忙于团队项目,我们团队做的是一个app,在缺少安卓开发的基础的不利条件下,起初我们进度较慢。好在后期,有赖于大家的通力合作,在焚膏继晷、没日没夜的工作后,我们终于做出了一个能够令我们勉强满意的作品,并且在各大应用市场上发布。
说实在的,这是一段有些痛苦的经历,每每回想起那几天,五个人在宿舍里安营扎寨,从一睁眼就开始和各种未完成的任务,未调试解决的bug作斗争,到了饭点就叫一个外卖,吃完饭之后继续斗争,直至深夜三四点。
这样的作息持续了差不多四五天,我们都感觉心力交瘁,痛苦不堪。
在看到作者的这段内容后我只觉得,软件工程的本质决定了完成一个项目确实很难。
作者介绍了软件工程的几个基本难点:
首先,软件是十分复杂的。这一点我深以为是。我们的APP说来功能并不复杂,现阶段做的一些程序逻辑也并不困难,没有涉及到一些高深的算法。但是就算这样,依照版本管理工具的统计,我们的项目规模已经到了八千行这么多。如果把写代码看成是写文章,行无疑是这篇文章的篇幅的基本单位,也就相当于字,相信对这世上的绝大部分人来说,写一篇八千多字、言之有物的文章绝非易事,更何况一行代码中的意蕴绝非是一个汉字能比。在这样的规模下,我们的项目的复杂度就可见一斑,在构思,描述,书写和测试各个环节上,需要投入的精力都会很大。并且,因为各个功能模块、前端与后台由不同的人负责书写,书写的过程中各人的想法会有所差别,书写出的代码再整合的过程中将会带来新的问题。在沟通探讨的过程中,我们也会花去大量的时间,这也体现着一个项目的复杂。
第二点,软件的整合也十分困难。就拿我们从一些开源项目中找到的一些框架来说吧,许多的框架对于安卓的版本有所要求,有的SDK不太适合Eclipse使用,所以首先我们将开发环境由Eclipse换成了Android Studio,不得不说,使用Android Studio使得将我们的项目与开源项目的部分功能进行整合的过程大大简化,然而也带来新的问题:
Android Studio实在是 太!卡!了!
Android Studio实在是 太!卡!了!
Android Studio实在是 太!卡!了!
五台电脑,平均的编译时间大约在两分钟左右,我们每次在点击运行后都要等两分钟,在每次修改代码通过运行判断正误的时候也要等两分钟,而且,既然是平均,那么自然有的要多于两分钟,开发的效率在等待它编译的过程中大大降低。
毫无疑问,为了整合我们的项目与现有的SDK,我们对编程环境做出了改变,这改变牺牲的就是我们的开发效率,实在是不得以而为之。所以在将各个软件模块进行整合的过程中我们也会遇到很大的困难。
第三点就是软件的可变性:软件实体不断受到变革的压力,他提到的一点非常值得品味:软件可以很容易地改变 - 它是纯粹的思想的东西,无限延展性。人们尝试在新的情况下在或超出原始域的边缘。该压力的扩展功能都主要来自与那些不仅仅喜欢基本功能的用户,并为他创造新的用途。
在我们的开发过程中,因为我在前期的开发任务中参与度相对较高,对于软件的整体功能有一定自己的认识,我印象很深的是,在11月4号那天,我们的项目的后台功能只剩下最后的几项没有实现,我仿佛看到了黎明的曙光一样,想要经过一通宵的奋战,为后台工作画上一个圆满的句号,再加上那天的三点半有欧洲冠军联赛皇家马德里主场迎战巴黎圣日耳曼的比赛,作为一个13年的皇马球迷,自然是不容错过的比赛。所以,那一天我向PM主动请缨,准备奋战到比赛开始。结果是喜人的,在解决了几个Bug并且实现了两个功能后,我安心的打开了直播的链接。
那一刻我一度以为,软工的团队项目到此便完全结束了,然而我想的太简单了!
初期的UI界面太过粗糙,我们不得不重构界面,利用一些开源项目中的一些较为美观的组件进行设计,由于时间紧任务重,负责后台的队员们也要转入界面的设计工作中来。这就有了之前提到的转变开发环境带来的痛苦感受。
除此之外,为了更好的用户体验,我们还引入了缓存机制,为一些需要加载图片的界面中的图片增加了直接从缓存中载入的功能,然而这也带来了很大的问题,由于我们的服务器的关系,在初次下载的时候有时会发生图片下载不全的问题,本地的缓存相应的也就成为了残缺的图片,之后这幅图片将会被加载而不会从服务器端重新加载。
经过了不知道多少小时的查漏补缺,我们确认了这一问题的来源是服务器对于是否下载成功的OnSuccess函数的判断有问题。木已成舟,更换服务器已经来不及了,这一问题就只能留到β版本再解决了。
最后一点:软件是无形的,在项目工作中,我们的很多工作可能只能通过界面得到执行的结果,然而有些问题的产生过程却无法由界面显示了解到。在调试过程中,多线程的程序让我们十分头疼,每每这种时候就后悔上学期面向对象程序设计课上没有将多线程的内容好好学好。
不过作者在陈述了软件工程寻找银弹遇到的种种困难之后,也对未来抱有一定的希望,列举了一系列他认为潜在的银弹,模块化编程、面向对象编程、人工智能、专家系统、自动编程、可视化设计等等,可以说,这些可能的银弹对软件工程的复杂性有一定的缓解作用,但是距离真正的解决软件工程中遇到的所有问题,还相去甚远。
可以说,通过阅作者的论述,并且结合自己的项目体会,我也觉得,想要找到一个银弹,简直是太难了,或许我们能为一个软件成功与否加入许多判断的依据,然而,如何去审核一个项目是否达到了定义的要求呢,这一过程的完成还是要依靠团队中的工作成员或者外界人员进行决断,这样的决断就难以避免存在着人为的影响,可能存在错误,这就是所谓的银弹不可能被找到的一个不可判定的逻辑结点。
2.There Is a Silver Bullet
By Brad J. Cox, December 06, 2004
然而这篇文章中,作者却认为:
To turn Brooks' own metaphor in a new direction, there is a silver bullet. It is a tremendously powerful weapon, propelled by vast economic forces that mere technical obstacles can resist only briefly. But as Brooks would agree, it is not a technology, a whiz-bang invention that will slay the software werewolf without effort on our part or vast side effects on our value systems and the balance of power between software producers and consumers.
The silver bullet is a cultural change rather than a technological change. It is a paradigm shift--a software industrial revolution based on reusable and interchangeable parts that will alter the software universe as surely as the industrial revolution changed manufacturing.
也就是说,作者认为,银弹是文化变革,而不是一个技术变化.
他认为软件工程问题的终极的解决方案是基于复用和互换的软件工业革命,其实这一点在我们的项目中也有体现,在初期的后台功能更时限结束后我们将工作重心转移到了美化界面上来,缺乏经验的我们,最直接的想法就是通过使用一些开源项目中的框架和组件,可以说,我们这部分的工作是在前人的基础上完成的,但是在开源化的今天,我并不觉得这样的行为有何不妥,开源技术的飞速发展使得作者在文中提到的许多大胆假设与美好愿望有了实现的可能,他在文中提到的许多软件复用面临的问题,诸如:记录他们的接口,使消费者能够理解他们,移植到新的硬件平台上,增强以端口没有违反一些已经存在的接口,并把它们推向市场,新的文化的价值体系,这样的殖民工坊中,鼓励改良重构的第一原则,以避免依赖于别人的工作。在开源化的今天,都得到了较为妥善的解决,我们或许正掌握着一枚银弹,但是如何使用,可能还需要我们不断地提升自我,在拿到一个开源项目的同时,从人家的代码中提炼出值得我们学习的内容,并且将这样的提升服务于之后的工作中。
当然,作者还提出了另外一个他认为能够成为银弹的思想:面向对象编程思想。上一篇文章《没有银弹》是Fred Brooks在1987年所发表,或许面向对象编程思想在那个时段还没有得到广泛地普及,至少在Fred的看法里:
Nevertheless, such advances can do no more than to remove all the accidental difficulties from the expression of the design. The complexity of the design itself is essential, and such attacks make no change whatever in that. An order-of-magnitude gain can be made by object-oriented programming only if the unnecessary type-specification underbrush still in our programming language is itself nine-tenths of the work involved in designing a program product. I doubt it.
可以说,两位作者的分歧归根结底还是他们对于怎样才算是消灭了“狼人”的评价标准不同,Fred认为所谓的没有银弹则是指没有任何一项技术或方法可以能让软件工程的生产力在十年内提高十倍。关于这一点在我看来,首先如何衡量软件工程的生产力就存在疑难,即算是说找到了一个科学系统的衡量软件工程的生产力的标准,想要在十年内提高十倍这本身就与之所以把软件工程比作狼人的出发点相违背(落下的进度,膨胀的预算,以及有缺陷的产品),既然狼人之说已不复存在,又何来银弹之谈呢。
而在Brad J. Cox看来,能够大幅度改善开发效率,并且能够整体提升软件工程开发的成果,都能够称为“银弹”,不可否认的是面向对象等让编程清晰,可复用的方法确实能将问题拆分,从而令问题结构清晰化,让人避免进行重复冗余的工作。虽然问题的差异性以及某些特异问题的困难性依旧存在,但是开发的效率已经得到了极大提升,一个大问题被规约成几个子问题,问题的难度已经大大减小。
,
总结:关于银弹问题,可能仁者见仁智者见智,我们也无需太过在意,结合这几周来团队编程的经验,我只想说思考和行动都有其价值所在,光做不想不如不做!
3.大泥球
在读这篇文章的时候我脑海中浮现出了很多之前自己写过的程序。(主要是去年OO课写的)在那个阶段,自己在每次作业中的想法很简单,赶紧写完交上去,不crash就行,功能能实现一部分就行,对于代码的风格是否简洁,结构是否清晰,逻辑是否完备。在一段时间内养成了许多不好的编程习惯,诸如:写到某一段落时发现对于某种错误的输出不知道如何处理,就选择输出一个错误信息之后exit(0),即便是说用了异常,也只是将各个异常零散地定义在了这个类的内部。偶然一次看到了一位同学的代码,他居然还会定义一个叫做myException的类,里面写好了各种各样的Exception。
现在看来,自己当时写的代码就是一个不折不扣的“大泥球”!所谓的大泥球,所指的就是那种杂乱无章、错综复杂、邋遢不堪、随意拼贴的面条式代码。
据我个人经验看来,这种情况往往大多产生于调试阶段,相信我们中的很多人都会为了快速解决Bug而忽略了程序的完整性,比方说,我要在一个保存函数里通过findViewByID获取到几个用户输入,通过调试突然发现某一个控件对应的输入块有一定的问题,可能要在程序外部才能这样获取到,然后就很自然而然地给原来没有参数的函数加入了一个参数,问题是得到了解决,但是这个函数就变得不伦不类了。对于这个问题,在我看来,在进行编程之前,要对程序的各个模块之间的借口定义明确,并且在每个功能模块内部,要有一个合理并且清晰的规划,在相关设计方案都明确之后才开始实际的编码工作。
因为自己之前的编程习惯不是太好,所以在这次团队编程的过程中,自己有意识地要求自己,通过诸如多写注释,变量命名遵守规范等方面,确保自己的代码不会成为一个大泥球。
此外,有赖于PM的未雨绸缪,在一切编程开始之前,我们的第一次Scrum meeting上,我们就通过协商,对于代码规范进行了明确地说明,条分缕析地提出了要求,并且保存为了书面文件,供大家学习参考。
总之,通过我们的努力,我们的团队项目基本能够做到模块接口一致,保持封装,保持代码整洁,大泥球并没有出现。
4.大教堂和市集
这个链接是维基百科中对于一本书的简要介绍,这本书叫《大教堂与市集》(The Cathedral and the Bazaar)是埃里克斯蒂芬雷蒙德(Eric Steven Raymond)所撰写的软件工程方法论。
本书讨论两种不同的自由软件开发模式:
大教堂模式(The Cathedral model):源代码在软件发行后公开,但在软件的每个版本开发过程中是由一个专属的团队所控管的。
市集模式(The Bazaar model):源代码在开发过程中即在互联网上公开,供人检视及开发。
对于我们的团队项目来说,我们目前还没有考虑过源代码的公开问题,所以也就无从谈起是大教堂模式还是市集模式,说来惭愧,学了两年计算机,我一直都不知道开源社区是干嘛的。在这次的团队项目开发中由于我们参考了一些开源项目,自己也头一次知道了开源社区的工作模式,我们用到的几个项目,从他的文件上传记录上可以看出,这个项目的开发者先后上传过许多版本,修复了许多bug,但是用的是哪种模式就无从得知了,在我看来,这两种模式各有优劣,市集模式的开发过程实时公开,能够很快获取到别人的意见,更方便解决某些开发过程中的问题。然而,很容易受到他人意见的影响,因而也就有了大教堂模式,在自己独立完成某一版本的全部功能之后才进行源码公开,工作过程相对更加独立自主。
5.有人负责,才有质量
记得刚上大学的时候,我们的计算机导论课上,熊璋老师就给我们讲过这个问题,后来高晓鹏院长也跟我们反复强调:当下,几乎所有的专业都会学C语言,都会学数据结构,各种突击速成的培训机构层出不穷。我们作为计算机专业人才的专业性体现在哪里:会写代码?显然,别的专业的同学也会写代码,并且人家还具备有你所不知道的专业知识,当面临到实际的问题的时候,人家能做的比你能做的更多。
在这篇文章的作者身上,我看到了一个真正的程序员的身影,他所热衷地,不仅仅是通过几行代码解决某个问题,而是去探讨某些程序(甚至是某些工具软件的功能局限)的本质,在他眼中,许多人不求甚解,这是由Raymond在其书中称颂的集市模式导致的悲哀的现实:一坨脓包似的权宜代码,被一群盲目的根本不知IT架构为何物的所谓IT“专业人士”永无休止地复制着,粘贴着。
回想自己在这次团队项目中负责加入的一个侧边栏,当时想要更改弹出侧边栏和主界面的比例,读了很久的代码还是没有读懂,然而灵机一动,找出了某个具体的数字,在进行修改过后果真发现了画面的比例发生了变化,于是果断停止去探究实现这一功能的原理,而是不断地修改尝试,直到找出一个自己觉得较为合适的参数。与我形成鲜明对比的就是我们的PM林珣玙,他所研究的很多高深的问题,比如说百度地图的API,以及下拉刷新的问题(虽然最后没研究出来),网上都有现成的使用示例,然而他并不满足于此,他都会深入阅读源码,耗费大量时间也在所不惜。
记不清是哪位老师曾经跟我们讲过,现在某些学生的毕设,就是从开源社区上面找几个项目,拼成一个,然后草草交上。在以后的编程生涯中,我们会无数次的面临这种选择,或许我们可以很快地完成一项任务,但是这项任务对于以后的指导价值,完全得不到体现,要成为一个真正的程序员,知其然,还需知其所以然!
6.worse is better
这篇文章中,作者首先介绍了MIT和stanford对于软件设计的要求:
简洁性——实际的接口与实现都必须简单,当然,接口的简单比实现的简单更为重要
正确性——设计必须在所有可考的方面都正确,不正确完全不被允许。
一致性——设计不能不一致,一致性要比简洁性和完整性更为重要,和正确性一样重要。
完整性——设计必须涵盖实际中所有可能面临的重要清净,所有合理的情形都要能够应对。
之后,他介绍了自己对于这一问题的见解:
简洁性:设计中最优先考虑的就是简洁性,实现比接口更要求简洁!
正确性:可考方面都必须正确,然而简洁要比正确更重要。
一致性:只要不过分地不一致就好,可以牺牲以保证简洁性。
完整性:可以为了其他三点的满足而被牺牲。
说实话,起初我并不太赞同他的看法, 受制于OO的遗毒,我一直都觉得正确性才是首先要考虑的,用户输入了他的输入,我们必须保证得出的是正确的输出,否则,可能会产生不好的影响。
然而,在当今这个时代,我们在实际使用一个软件的过程中,最直接感受到的是软件的设计风格,界面的美观程度,以及功能的完整性,而程序的正确性,并不会很快地影响一个用户的想法,让他决定是否要安装这个软件。所以在这样一个信息碎片化的快节奏的时代,我们对程序的完整性与一致性的要求或许并不那么重要,在核心功能的正确无误的基础上,某些非常罕有的特殊情况并不需要花费大量的精力去处理,如何改善大多数用户的体验感受才是我们应该关注的内容!
7.瀑布模型
本文主要介绍了瀑布模型:
瀑布模型将软件生命周期分成了六个阶段:制定计划,需求分析,软件设计,程序编写,软件测试和运行维护。它规定了软件开发的顺序自上而下、相互衔接的固定次序,如果有信息未被覆盖或者发现了问题则返回上一阶段查找问题并进行适当的修改。
优点是:为项目提供了按阶段划分的检查点,当前一阶段完成后,您只需要去关注后续阶段;在增量开发的过程中,一般需要做单元测试,单元测试又需要做回归测试,而瀑布模型的循环反馈的工作就等于是做了测试的工作,更加保证程序的正确性。用工作的顺序将问题简化了,将功能实现与设计分开,方便分工协作。
目前我们的项目并没有一个整体的功能规划,希望后一阶段,我觉得我们真的考虑用这种瀑布模型进行开发,为每个阶段设立明确地日期界限,不要想现在这样想起要实现一个功能就去实现一个功能,想到要做一个特效就花费好久去做,缺乏一个整体的规划。
8.Agile Method
这篇文章中讲到了一系列敏捷开发的方法,在我们的开过程总主要用到的有极限编程与Scrum meeting两项。首先,极限编程中有四个核心价值:沟通(Communication)、简单(Simplicity)、反馈(Feedback)、勇气(Courage)、此外还扩展了第五个价值观:谦逊(Modesty)。 XP用“沟通、简单、反馈、勇气和谦逊”来减轻开发压力和包袱;无论是术语命名、专著叙述内容和方式、过程要求,都可以从中感受到轻松愉快和主动奋发的态度和气氛。这是一种帮助理解和更容易激发人的潜力的手段。XP用自己的实践,在一定范围内成功地打破了软件工程“必须重量”才能成功的传统观念。
XP精神可以启发我们如何学习和对待快速变化、多样的开发技术。成功学习XP的关键,是用“沟通、简单、反馈、勇气和谦逊”的态度来对待XP;轻松愉快地来感受XP的实践思想;自己认真实践后,通过对真实反馈的分析,来决定XP对自己的价值;有勇气接受它,或改进它。
在我们的团队合作中,我们五个人在三天的时间内,集中地在宿舍内进行集体编程,遇到了问题(像是不太明白别人写的代码中的某些细节)都能够第一时间地从对方那里了解到情况,在共同合作编写同一个功能模块的时候如果遇到了某些分歧或者不统一,都能够征得团队其他成员的意见以供参考。
我很喜欢这样的开发模式,开发的效率较高,并且很欢乐,但是这样的开发模式有时候也会让人觉得比较压抑(那段时间我玩笑地把我们宿舍成为722黑网吧),在后一阶段的开发过程中,我们一定要取其精华去其糟粕,尽量保持这种协作模式,但是要注意避免不好的作息规律,也不影响他人。
另外一个就是Daily Scrum了,我感觉这一个内容的意义在于,明确每天的任务,并且显示你的完成情况,能够让你对你自己的任务有一个明确的认识,很多时候,我们发现任务不能按时完成不是因为自己能力不够,而是因为缺少规划,缺少对自己的要求。Daily Scrum能够将所有人对工作的完成情况摆在台面上,这就逼迫着我们出于面子也好,团队的责任感也好,必须努力完成自己的任务。
除此之外,项目经理通过为每个人布置任务,也能够更好地了解项目的进展情况,对下一步的工作日程更加合理地进行安排。
9.软件工程需要方法论吗
需要!真的需要!要想避免通宵达旦,要想不过得浑浑噩噩,一定要有方法论!
发自内心的!
β阶段一定要好好计划一下!
最后加一句,我们的团队会是最棒的!加油!Chronos