一、研发工具与研发模式
据说,人之区别于禽兽,最大的特征在于利用,甚至发明工具。在没有任何其他工具时,我们只能借助于自己的肢体,一旦有了工具之后,我们的能力将会大大的增加。
但是,从另一个角度来看,工具也同时在限制我们的能力,甚至限制了我们的行为模式与思维模式。有一句俗话说得好:「手里拿着锤子,看见什么都像钉子。」
而在研发工具的领域,我们观察到另外一些有趣的现象:因为软件研发工具的开发者,同时也是工具的使用者。因此,他们不仅仅会受制于工具,也往往会由此被激发,开发出对自己而言更加趁手的工具。开发者与使用者身份合二为一的现象,使得研发工具的发展,简直可以用「日新月异」、「层出不穷」甚至「争奇斗艳」来形容。
随着软件复杂性的不断增加,以及软件开发的参与者不断增多,团队协作的辅助软件,也开始不断增加,随后我们发现:工具不仅仅限制了个人的行为模式,更进一步限制了团队的协作模式。
软件研发企业的管理者,往往会有某种错觉,他们会认为:管理就是定下制度、流程与规范,然后「下面的人」就会照此执行。因为有人「听话」,有人「不听话」,所以才需要奖励与惩罚的制度,来帮助管理者推行他的「规则」。所以,他们一般都很喜欢看《执行力》这样的书。
在开源社区,事情变得有些不一样。虽说开源社区也有「领导者」,甚至往往会有「精神领袖」,但他们并没有暴力手段,也没有经济手段,甚至行政手段。因此,要协调一帮自由散漫的黑客,共同开发高质量的开源软件,必须有更加高明的手段。
由于一切都是Open的,所以:不仅代码人人可见,开源社区的协作模式,也暴露在众目睽睽之下。从某种意义上来说:这促进了开源社区的协作工具的开发、进而使得开源的研发协作模式,以远远超过企业内部的演化速度飞速演化。
二、第一代开源协作模式
第一代开源协作模式,在早期几乎没有符合自身特殊需要的工具,有什么用什么,因此最为常用的email,被发展为Maillist,成为整个开发团队的协作核心工具,大多数操作系统内置的diff/patch工具,使得代码的交流以email patch为主。这些老牌的开源项目,从使用RCS、CVS,到了后来也开始逐步引入svn/git,bugzilla这样的工具,但是围绕mailing list开展协作的特征,则持久不变。
作为协作核心的Maillist
一个开源社区,往往就是一个邮件列表,随着软件的日益复杂,社区的不断扩大,邮件列表也会不断分化,通常会划分为:核心组、开发组、用户组。开发组与用户组的邮件列表,随着软件的架构分化为多个模块,还会进一步分解。
在邮件列表里,所有的用户都是平等的,在无法用工具保障流程的情况下,社区逐渐发展出了一套严格的邮件礼仪和格式规范。不规范的邮件,不会被理睬;不礼貌的家伙,甚至会被赶走。
邮件越来越多,即使分成多个邮件列表,依然太多。Archive这样的邮件归档、查阅的工具,就必须得有了。一封邮件,大家都来回复,严格re:的标题,组成了一个可供追溯的线索。
在邮件列表里,通常出现个人的名称,加上Reported-By、Tested-By、Acked-By的标记,即是一种代表个人名义的认可,也是流程规范的一部分,更是计算各人贡献的依据。
Bugzilla应运而生
在邮件中,有一类话题是最活跃的,那就是bug。但是,通过翻找邮件查阅bug的最新的解决状况,是非常困难的。一个bug,从提出,到最终解决,并被确认在哪一个版本中发布fix,是一种稳定的状态转化模式。一个专有的处理工具,势必应运而生。Bugzilla、trac等一批工具,就由此被创造出来了。
代码提交流程的规范化
开源社区,表面上非常的崇尚民主自由,但实际上却盛行精英主义、甚至是个人独裁的。我们往往会给某个开源项目的创始人,冠以「仁慈的独裁者」的头衔。虽然,是否仁慈,大家不得而知,但独裁确实是显然的了。
最大的独裁,是代码的管理权。因为作为创始人与核心开发者,他们往往以一己之力,贡献了绝大多数的代码,确定了项目最初的架构与发展方向。他们不会容忍任何人随意地向代码库提交代码。
在邮件列表中,一个新来的家伙,从没人认识,到能够独立的向代码库提交代码,非得经历艰辛的历程不可。这样的历程,简单的说,就是一次一次的Code Review。被审核通过、合入代码库的patch越多,一个人对于社区的贡献就越大,可信度也越高,身份地位也逐步提高,然后,他也就可以去Review其他人的代码了。
总结:在简陋的工具条件下,发展出高效、严格的社区协作模式
三、第二代开源协作模式
第二代开源协作模式,有两大特征:Web化、集成化。随着Web技术的不断成熟,开源社区也开始创造一个又一个的Web开源项目,其中Web化的项目管理工具,如雨后春笋般冒了出来。在wikipedia上,issue-tracking systems列出了55个,project management software列出了152个,其中开源的也有30+,open-source software hosting列出了22个,堪称蔚为壮观。
这类平台又可以分为两大类:基于开源的项目管理工具或issue tracking工具,自建平台,以JIRA、DotProject、Redmine为代表;基于免费开源托管平台,以SourceForge、Google、LaunchPad为代表;
第二代的开源项目管理工具,可以说,主要是在向企业内的开发管理学习。文档、流程、角色、权限、统计报表等等功能,都开始出现了。有些开源项目,也在用这些东西。
以SourceForge与Google Code为代表的开源托管平台免除了开源项目搭建自己的官方网站,管理工具,代码仓库之类的繁琐事务,大大促进了开源项目的发展。不过,由于平台的功能总是受限的,因此自建门户,自组工具的开源项目依然层出不穷。
issue & milestone
在第二代开源协作模式日渐成熟的过程中,另一股潮流也正方兴未艾:「敏捷软件开发」。其中,最为深入人心的概念之一,就是每个迭代,完成一批User Story。
在开源社区,这个概念被进一步演绎:无论是bug和feature,都被统称为issue。这些issue,被分到不同的milestone(版本),即使最后有可能延期,milestone也会定义一个预期完成时间。
这是好事?还是坏事?其实很难评价,因为从开源的原始教义而言:所有的贡献,都是自愿、随机、不可预期的。为自然生长的软件,规定里程碑,本来就显得荒谬。但是,从另一方面而言,我们可以引用另一个中国人过马路的例子:「不管红绿灯,凑够一堆人就过马路」,开源软件,往往也是「不管里程碑,稳定一堆特性和bugfix,就发布一个版本」。
如果在开源软件很少,更别提形成开源生态圈的情况下,这种随意的做法还是可行的。但是在大量软件,相互依赖的情况下,一个开源项目要赢得其他协作项目的信赖与协作,必须给出稳定的规划,以便相互配合。
这种规范,也是被逼出来的。
服务平台化
虽然黑客们喜欢写程序,但是要写的程序实在太多了,能够不重复造轮子,有现成的好工具可以直接拿来用,也是件好事。如果可以打开一个网站,注册一个用户,创建一个新的项目,剩下的事情自有平台帮忙打理,那么大家都可以愉快、专心的写自己的代码了。
平台在逐步进化,因而能够帮助开源项目,打理越来越多的事务。通常主流的开源项目托管平台,都能够完成:
- 在线代码浏览,并能够支持不同的配置库
- 需求管理、Bug管理,通常合并为Issue tracking
- 版本与里程碑管理
- 文档编写与管理,以Wiki的形式为主
更进一步的,还有能够完成:简单的自定义工作流、文件夹与静态资源管理、输出各种统计报表、甚至提供论坛、搜索、邮件列表以及各种排行榜等等。
在此之前,一个开源项目,是一个社区。到了大平台的时代,整个平台,构成了一个更大的社区。
总结:以Web形式提供的集成化开源项目托管平台,标志着开源项目的协作模式,进入成熟期
四、第三代开源协作模式
到了MySpace、Facebook与Twitter这样的SNS网站的兴起,开源项目的协作模式,受到SNS的启发,也随之进入了第三代,以Social Coding为核心的开发协作模式,这样的模式在以Github为代表的网站上,体现的最为充分,众多的模仿者也层出不穷。过去的开源项目与托管平台,都是以项目为中心来打造,而Github则是围绕着参与开源的人来打造。首先满足的不是项目的需求,而是个人的需求,由于对人的黏性大大增加,也使得Github成为近年来最具吸引力的开发社区。
围绕着Github,一大批周边扩展服务被建立起来,构成了一个更加有活力的生态圈。而程序员们,不仅在Github上参与开源项目,更在Github上结交朋友,分享经验,增进能力。甚至这样的协作模式,还拓展到了编程领域之外,成为开放式协作的流行模式。
激励机制
第三代开源协作模式,以Github为代表,以Social Coding为精髓,这一代模式想要解决的问题,是激励机制的问题。
第一代开源协作,虽然创造了一批大大有名的项目,但事实上却是一个非常小圈子的事业。即使是最为成功的Linux内核开发,也不过1000~2000人。一旦人多事杂,就会出现管理混乱的现象。
第二代开源协作,虽然借鉴了很多企业界的规范管理经验,但是在事实上,却是不适应开源软件的风格的,举一个例子:在Redmine中存在的角色、权限、工作流之类的东西,实际开源项目使用的,却非常少。
第三代开源协作,借鉴了社交网络中的各种数值化模型,关注者数量,Star数量,Fork数量,Issue数量,Pull Request数量,都在显要位置标示出来,对于开发者形成正向激励,还有很多的统计图表,形象的展示了项目的活跃程度。
开源社区,原本就有非常深厚的,统计补丁数计算贡献度的传统,这一点在Github被发扬光大,可以说是优秀的继承与创新。
基于fork/pull request的协作机制
在github,一键就能够fork自己的分支,然后可以跟原有的分支毫无关联,也可以非常方便的提交pull request,这就带来了更加频繁的分裂,使得分裂常态化了。
原来的开源社区,开发者修改了代码,希望能够贡献给社区,需要穿越种种障碍,如果社区不接受,最后开发者只能逼不得已,自己开一个新的分支,变成一个新的项目。
在分裂是异常的状态下,分裂是罪恶的,是不应该的,是会带来阵痛的。当分裂变得常态化,pull request也变得常态化,分分合合,以每天N次的速度发生,恰恰因为如此,他不再是一种罪恶,而是一种健康的、向上的、以更快速度进步的模式。大家不再是在一个版本下,各自贡献,而是在各自的版本下,独立发展,想分就分,想合就合。
Pull request,从一个代码合并的方式,变成了开发者之间主要的交流方式,他们发现,最好的交流,正是通过源代码来交流,一切的讲道理,都不如用源代码来讲道理。这恰恰是程序员们最习惯,也最喜欢的一种交流方式。
围绕Github出现的扩展服务
较之上一代的平台,Github提供了优秀的开放扩展机制:OAuth、API、SDK、WebHooks、ServiceHooks等等,使得围绕Github,扩展各种满足项目特定需要的服务,变得非常容易。
这就是从上一代平台的开源大社区,进化为「围绕Github的开源生态圈」。
到目前为止,Github一共支持超过170个不同的扩展服务,其中较为热门的服务有:
- 与其他项目管理工具集成(Bugzilla,Asana, Basecamp,Redmine,JIRA,ZohoProject)
- 与持续集成服务集成(Travis,Bamboo,CircleCI)
- 与消息通知服务集成(Amazon SNS,Email,IRC,Jabber)
- 与DevOps服务集成(AWS OpsWorks, DeployHQ)
Github 开放平台与API,基于Github OAuth API,其他网站可以支持开发者用自己Github账号登录,并使用一些有趣的服务。
- Cloud IDE,用Github账号登录,直接在浏览器里打开一个IDE,编辑自己在Github上的开源代码
- Resume Service,根据开发者在Github上的各种社交行为与开源项目贡献度,自动生成格式化的简历
这些扩展服务,极大的丰富了开源生态圈的内涵。
总结:社区天生就应该是社交化的,Social Coding与开源社区,简直就是天作之和。
五、开源协作模式的新探索
Git:作为标配
目前看来,git作为分布式配置库的王者地位,已经不可动摇了。能够初步总结的原因,至少有三个:
- git与github互相促进,作为全球最大也最流行的开源社区,他的标配是git。这也导致越来越多的开源项目,选择git作为标配
- 众人拾材火焰高,越是参与开发的人不断涌入,越是帮助git发展得更快。这是一个赢家通吃的世界
- 开源生态圈的出现,使得围绕git、github发展出一大批相关的开源项目、开源工具以及次级社区。这一现象,在docker横空出世之后,再一次得到展现。
Code Review:必不可少
开源社区,一直有非常悠久的CodeReview的历史,哪怕在最早的mail & patch的时代,Review也是开源协作的头等大事。仅仅梳理Review的历程,也可以看到其中工具与流程的发展。
最初是邮件review,然后是在集成平台上内置review功能,或者提供更强大的review插件。到github创新的提出pull request,则是一种更加方便有效的review模式。
与此同时,独立于集成平台的专门的code review工具,也开始发展起来:Review Board、Google Gerrit、Facebook Phabricator是其中重要的几个代表。
Workflow:百花齐放
在git逐步流行之后,大家发现基于git可以选择的「玩法」实在是太多了。从最初写下一行代码,到最终出现在项目发布的版本之中,期间可以有无数的「路径」。
在git-scm.com官方教程《ProGit》里,提及了三种:集中式工作流、集成管理员工作流以及司令官与副官工作流。
在蒋鑫的《Git权威指南》里,又提及基于TopGit、基于submodule、基于subtree、基于repo、基于gerrit、以及git与svn配合使用的不同工作模型。
再后来:GitFlow、Github的Pull Request、以及基于Github的Github Flow等等工作模式,堪称百花齐放。
为什么会出来这么多workflow?因为团队与项目的差别,实在太大了。现在到我们简直无法想象:那些在各种情况下都坚持使用SVN都开发者,是怎么熬过来的?
当然,从另一方面来说:选择太多,也会带来另一种烦恼...
CI、CD、DevOps
从Everything as Code到Everything Automation,是另一个越来越明显的趋势。前两天,我从机场出来,正好看到两个并列的广告牌,一个广告的大意是:「UPS助您打通全球供应链」、另一个则是「中国银行助您打通全球供应链」。这真的很有意思,看来在各行各业,大家都开始在关注整个生命周期的各个环节之间的打通。
只是,在软件领域,我们会感觉到这是一种回归。毕竟,最初的软件开发,都是很简单的。在一台计算机上,自己写程序,自己编译,自己调试、运行,最后发布。既不用依赖他人,更不用等待什么流程。
随着项目越来越复杂,参与的人越来越多,我们的软件,不能仅仅运行在自己的机器上,或者需要部署到服务器上,或者需要发布到某种平台上。在协作者众多的情况下,如何分工合作?
在开发者水平参差不齐的情况下,如何保证质量?在分工、协作、流程与质量保证的要求之下,如何提高效率?
这些都是DevOps致力于解决的问题,也是DevOps不断得以发展的原动力。
总结:开源社区,始终在进步,Github代表的也只是「一代」而已,新的一代协作模式,还会被创造出来的。
六、暗线:工具、习俗背后的逻辑
过去是如何?未来又会怎样?想要回答这类问题,其实需要更加深入的思考:「开源社区的协作模式,为何会变?变化背后的逻辑是什么?」
开源社区研发工具的两大目标:降低门槛,提高效率
开源社区,与普通的软件开发最大的不同,就是参与者多多益善。在《大教堂与集市》中,Eric Steven Raymond总结到:「如果开发者协调者有至少一个像Internet这样好的沟通媒介,并且知道如何不靠强制来领导,那么多人合作必然强于单兵作战」,这简直就是绝妙的预言。虽然当年的ESR也许并未预测到,基于Internet会出现那么多辅助开源的相关工具(他们当时还只有邮件列表)。
所以,开源社区一直在致力于两个看上去相反的目标:「吸引尽可能多的人,以尽可能简单、便捷的方式,参与到开源中来」、「在人多得超乎想象的情况下,依然能够保持,甚至不断提高效率」。
如何计算参与者的贡献?
开源社区,不会给参与者发工资,因此激励是一个大问题。公平、公开、公正大计算所有参与者的贡献,以所有人都能够接受都形式,计算并公布各种排行榜,可以说是开源社区特有都「刚性需求」,因此SNS与开源社区的结合,成为必然。以后,面向开源协作的大数据分析,也一定会出现。
如何激励、吸引、回报参与者?
计算参与者的贡献,仅仅是公平激励的基础。让激励变得有趣,变得有价值,变得有意义,则是吸引与回报参与者的不二法门。因此:游戏化的思路,会被越来越多的引入到开源社区中来。
如何保障项目质量?
开源项目保障项目质量都最大利器,是引入数量众多都热心测试者。但是,仅仅有人愿意测试,主动、积极都帮助测试,已经越来越不够了。随着项目越来越复杂,开源项目必须逐步走出仅仅依赖肉眼、依赖人多+运气的质量保障模式。
自动化测试、以及更加规范的Review流程,则是必然出现,而且将越来越重要的环节之一。
如何协调一致的工作?
自由与规范,计划与变化,兴趣与责任。经常会在社区里,成为争论的热点话题。虽然在《大教堂与集市》中,ESR极力鼓吹「礼物文化远远胜过交换经济」,但是:「在一个庞大的社区,各种各样的事务都需要有人去完成,而且还不能漫无章法。」
因此:「某种调节手段、协调者与协调机制、甚至是看不见的手」之类的东西,会慢慢的回到社区。
如何在社区里平等、高效的协商?
目前来说,依然只能是线上讨论+线下开会。虽然,很多开源社区,开始学习《罗伯特议事规则》这样的开会圣经。但是,开会依然是最令程序员感到苦恼的事情。在这方面,将来会不会出现更好的辅助工具,这方面很值得期待。
结束语
唯有变化,是不变的。开源协作模式,同样如此。惟愿我们,能够成为推起其前进的力量之一。