一 . 关于银弹 (Silver Bullet)
银弹,被引申为解决问题的有效办法。IBM大型机之父福瑞德·布鲁克斯在1986年的论文《没有银弹》中表达了他的观点:软件工程中不存在银弹——没有任何一项技术或方法可使软件工程的生产力在十年内提高十倍。文中着重探讨了软件工作的两个分类:本质性与附属性。
布鲁克斯认为,附加性的困难会随着工具的改善而逐渐淡化,反而是本质性的困难最难以解决,因为大部分的活动是发生在人们的脑海里,缺乏有效的辅助工具。以往,软件生产力的重要进展绝大部分是来自于人为障碍的排除,像是严苛的硬件限制、难用的编程语言、上机时间(machine time)的不足等等,这些都是造成附属性工作益发困难的原因。这也是他提出该论点的主要依据。
在我看来,他的观点是有他所处时代带有的局限性的。论文发表时间为1986年,正如上面提到,那时候人们正为编程语言、硬件配置这些外部环境而绞尽脑汁,附属性工作自然会成为软件工作中的关键元素。本质性反而容易被忽略。可是随着时间推移,附属性工作的难度与地位愈发降低,人们的目光也逐渐转移到了布鲁克斯所提的本质性工作上。正如1990年,Brad Cox发表的《银弹存在(There Is a Silver Bullet)》,Cox指出采取可再利用(reusable)、可替换组件的方式来对付属于概念本质性部分的问题。以及越来越多的软件开发模式及方法论的出现,都是对本质性工作困难进行的优化。其次,他仅仅将软件的本质性归于解决概念完整性和处理沟通,而忽视了软件开发是一个复杂的过程,设计,规格化,测试都是重要组成部分,也会对软件工程生产力产生巨大影响。
就以这次团队项目的第一轮迭代为例,我觉得十分符合布鲁克斯设定的情景。我们在这四周里有很大精力都放在了附属工作上:统一开发环境与开发语言,解决服务器和域名的问题,学习开发网站需要的前后端知识。而第一轮迭代我们本身的设定便是完成网站开发的入门工作,并大概搭起网站框架以及实现简略功能。所以,附属性工作所占比例便会很大,这时提高这方面的工作效率与质量就会使这一时期的软件工作生产力大幅度提升。
二 . 大泥球 (big ball of mud)
所谓大泥球,是指杂乱无章、错综复杂、邋遢不堪、随意拼贴的大堆代码。我们现在惯用的敏捷性开发的很多方面会直接导致泥球,包括:缺少前期设计、应对需求变化过晚、应对架构变化过晚、碎片式增长。尤其是在需求导向愈发重要的今天,很多软件在发布的同时就已经过时了,大泥球也会随之产生。同时随着修改BUG,新BUG可能也会随之产生。
例如,这次的团队项目(网站)我们分为前后端开发,每组有三个人,每天通过例会分配任务,再最终汇总。不同成员的代码之间必然存在风格差异,一开始设计分工时考虑也难免不周全,成员之间的沟通也可能不足。这就必然会导致功能覆盖、代码冗余的问题,从而出现杂乱无章、错综复杂的代码,也就是大泥球。这可能也是刚刚开始从事团队软件开发难以避免的歧路。但我们也增加了对应的代码复查以及测试环节,同时也会及时开会总结,调整需求,继而修改设计,整合、修改并重构代码,这样在我看来可以尽量减少大泥球的产生。
而在之前的个人项目中,一是有一些功能函数是复用的网络开源代码,其次是没有代码复查以及对应的检查测试,会有大量的大泥球。
在我看来,对于一个项目而言,减少大泥球的办法有如下几点:
三 . 你的团队是用什么方式建造软件?
作者把开源软件的开发模式分为两种,一种是大教堂模式,源码公开,但是开发过程有一个团体控制;一种是市集模式,同源源码公开,且源码放在互联网上供人阅览,并可以贡献代码,进行开发。并且提倡市集模式,认为在足够的人的检视之下,BUG将无处藏身。
我们的开发模式属于前者——大教堂模式。我们会实时更新我们的代码进度,并会公开最终代码。但整个开发过程完全由我们的团队控制,最终的网站也会由我们来发布和维护。
四 . Lost in CatB
作者集中讲述了由开源软件而引发的代码过度依赖问题。一段话就可展示出作者的态度 “这是由Raymond在其书中称颂的集市模式导致的悲哀的现实:一坨脓包似的权宜代码,被一群盲目的根本不知IT架构为何物的所谓IT“专业人士”永无休止地复制着,粘贴着。这事儿放在今天你也许很难相信,但就是在这令人无比尴尬的混沌之下,沉睡着美轮美奂的Unix大教堂的遗迹,而Unix恰恰是以设计简约、功能实用、执行优雅而著称于世的。(世间荣耀就此消失……)”。 也是我上面提到的开源代码复用带来的后果。
这个问题广泛存在。各式各样的自定义库、包十分泛滥,而且互相依赖嵌套,造成用户安装使用软件时遇到巨大的困难,甚至无法使用。而在我们的团队中,也存在着对应现象。
在前端开发中,设计UI时用到了当下很时兴的semanticUI。里面涉及到了弹窗的设计,而这时需要引用一些网络上的开源jQuery包来支持相关html代码。但我们根本不了解它的具体实现,只是作为用来实现功能的工具使用。后端开发也存在着从开源代码中只顾现功能而不解所以的复用部分代码的现象。这的确会对第二轮迭代造成潜在的影响,且不利于软件的稳定与完整。而在自己的个人作业与结对项目中这种现象会更多一些......直接造成了对自己程序的掌控不足。
还是套用坐着的一句话:所谓质量,只有在某人对它负责时才有意义,而这个“某人”只能是一个人,不能是几个人——二重奏除外。
五 . Worse is Better
作者抛开传统的软件理论:正确性、完整性、兼容性均不可侵犯,简洁性只能服务于他们。提出了新的论点:worse is better——简洁性成为首要原则,正确性、完整性、兼容性均可为其做出让步。
文中也提到 Unix 和 C语言就是这种理论支持下的产物,也间接证明了这种理论的可行性。
个人认为,这也反映出当下的一些趋势,如今,十全十美已经不现实,就连用户也逐渐接受一点。对于软件而言,用户主要在意的就是自己集中使用的那一部分功能;而开发者主要专注于最多被使用的情况。工程的简洁性的重要性也就随之显著,能影响开发的周期以及最终的结果。用户逐渐接受了不完整与不完全正确,于是worse is better理论变得更加有说服力。
在我们的项目中,我们也在不知觉中应用了这些理论。因为第一轮迭代的设定以及时间的紧张,做成一个完整的社团平台并不现实。于是我们舍弃诸如社团前台注册,用户加入社团内部等功能,将着眼点放在最关键的社团活动上——学生参加社团绝大多数为了参加活动,围绕活动搭起初步框架。即为了简洁性,牺牲了部分完整性,但确实使我们完成了Alpha版本的设定任务。
但这两种理论究竟谁更好,个人认为要取决于项目的类型与定位。如果一个项目拥有足够的资源,并且着眼于长期的稳定与进步,完整性与正确性依然要是重中之重,也完全有能力去把项目本身做得更好。
六 . 瀑布模型
瀑布模型严格把软件项目的开发分隔成各个开发阶段:需求分析,要件定义,基本设计,详细设计,编码,单体测试,结合测试,系统测试等。像流水线操作一样,把软件开发过程分成各种工序,对每种工序进行了更细致的分配。 而在温斯顿·罗伊斯的那篇文章中,他并不推崇严格意义上的瀑布模型,相反他指出了缺陷,并提出了几种改进,例如回溯、增加文档等。
特点:
1.它的核心思想是将各项功能的实现与设计分开,规定了各阶段的一个自上而下的顺序,相邻的两个阶段有紧密的联系,就好比我们平时写的操作步骤,从第一个步骤开始,每个步骤都依赖于上一个步骤的结果,作为本阶段的一个输入,有很强烈的先后顺序。
2.瀑布模型对软件的每项功能在需求分析、设计时就给出了实现的具体方案,所以用瀑布模型,整个软件的设计框架很清晰,每一步也很明确,软件工作者也很清楚自己的分工。
3.任何阶段如果发生错误,立即回到前面发生错误得阶段,进行修正工作.
4.每一阶段完成后,皆会有严谨的文件产生.
5.使用者即用户只有在调查,需求分析及测试三个阶段参与.
七 . 敏捷开发
敏捷开发是一种面临迅速变化的需求快速开发的能力。敏捷不仅仅是简单的快,而是短周期的不断改进、提高和调整;敏捷不仅仅是一个版本只做几个功能,而是突出重点、果断放弃当前的非重点;敏捷不仅仅是随时增加需求,而是每个迭代周期对需求的重新审核和排序。
(一) 敏捷开发是一种面临迅速变化的需求快速开发的能力,它有四个核心思想,而在我们的团队项目均有应用:
1.是强调面对面的沟通,也就是说沟通很重要,人和人的相互交流胜于任何流程和工具。所以每周的大会以及每日的例会均是我们开发工程中的常态,面对面的交流会省掉很多麻烦。
2.是要把精力集中在可执行的程序上,可以运行的产品胜于编制综合性文档,也就是强调了原型、模型、Demo等的重要性。我们整个过程中,始终以产品进度为主,各项开发文档为次要工作。
3.是团队合作和团队激励,合作胜于谈判,敏捷开发能将需求、开发、测试等全部团队成员融合成一个整体,大家都是一条线上的蚂蚱。PM经常会鼓励我们,我们团队中各个成员也会互帮互助,所以这次的开发大家都尽其所能,进度也比较理想。
4.是超强的适应能力,适应变化胜于按部就班,敏捷开发的特点就是快速。对于互联网行业来说,这点非常重要。在开发中,经常会出现预期之外的状况,这是大家会召开临时会议,商讨应变,必要的话便会更改原计划来适应新状况。
(二)应用这些思想的过程中,对应地,我们也采取了许多敏捷开发的经典做法:
1.极限编程:PM作为用户的模拟者会随时与成员保持沟通交互,从而随时修改代码。同时 前端与后端也各自有两位成员进行结对编程——前者针对页面实现,后者针对数据库model的建立。
2.精益开发:PM以及小组内部在分配任务时,除了一开始的规划外,不会做太长久的任务,同时赋予各自充分的自主权。同时,第一轮迭代整体就是一个成员不断学习的过程。
3.Scrum:每天进行汇报总结,开展例会,并发表报告。每个团队成员需要汇报各自的进展情况,同时提出目前遇到的各种障碍。而在 Sprint 计划会上,将会对所有已经分配Sprint 周期中的产品需求积压进行估计,并对每个条目进行设计和任务分配。
八 . 软件工程的方法论到底有多少用处?
编程的方法论是指软件开发的一整套方法、过程、规则、实践和技术。我们通常提到的方法论都侧重于项目、过程和人员的管理。
而在这两篇文章中,都探讨了软件开发方法论对软件开发产生的影响,也各有侧重。但各自提到了方法论在预测需求以及度量项目方面的不可行性。需求无法通过方法论被准确地预测;而典型的软件项目往往也是没有规律及可预测环境的。项目成功的唯一正确度量就是:最终的结果通过整个生命周期里的实施达到了预期目标吗? 很难知道什么关键活动导致了项目成功和失败,很少有人能够通过旧有或现有的项目获得答案。几乎不可能判定哪些决策导致了成功或失败。这也有了第二篇文章作者的怀疑,方法论真的有用吗?
通过第二篇文章后面的评论,我们可以看到有的人赞成 “lines of code”已经根本无法起到度量IT技能的作用了,进一步支持方法论怀疑论;但同时也有人提出现金的方法论中的关于代码复审、单元测试、冲刺等的不可忽视的巨大作用。
所以,由于以计算机为基础的系统在数量、复杂程度、应用方面的增长,对无处不在的计算机软件提出了更高的要求:更广,以解决层出不穷的应用问题;更精,以安全可靠地完成各项任务;更简便,以适应千家万户的使用普及。要达到这一目标,仅依靠的现有的思想方法是不够的。
方法论可以为我们提供大量的关于代码审核、开发模式上的经验与便捷,这是它最大的用处;但它不能是一成不变的,应该是随着需求不断进步发展到,这才会真正的发挥出作用。同时,软件开发人员的存在才是最关键的,需求预测,IT技能这些方法论的盲区还是要依靠经验丰富的专业人士来解决。软件开发人员的自主能力与方法论结合,也许才是解决问题之道。