Eclipse's Culture of Shipping
Copyright © 1996-2005 Artima Software, Inc. All rights reserved
http://www.artima.com/lejava/articles/eclipse_culture.html
Eclipse的发布传统
与Erich Gamma的一次谈话,第五部分
Bill Venners
Jun 28, 2005
翻译:lxwde
摘要
在这次采访中,Erich Gamma(里程碑式的书籍《设计模式》的作者之一)向Bill Venners谈论了Eclipse团队所采用的开发流程,这个团队的“发布传统(culture of shipping),”以及透明度(transparency)在围绕一个产品构建一个社区的时候的重要性。
Erich Gamma是在1995年作为畅销书籍《设计模式:可复用面向对象软件的基础》 (Addison-Wesley, 1995) [1] 的合著者而跃上软件业界舞台的。这项具有里程碑意义的工作,经常被援引为四人帮(GoF)的书,该书针对通常的设计问题分类整理出了23种特定的解决方案。1998年,他和Kent Beck组成团队开发JUnit[2],这成为Java社区事实上的单元测试工具。Gamma现在是IBM的一名杰出工程师,他在位于瑞士苏黎世的IBM Object Technology International(OTI)实验室工作。他担任Eclipse社区的领导工作,负责Eclipse平台[3]上与Java开发相关的事务。
2004年10月27号,Bill Venners 在加拿大温哥华举行的OOPSLA会议上遇到了Erich Gamma。在这次采访中(这次采访的内容将分多次在Artima Developer的Leading-Edge Java频道刊登出来),Gamma讲述了软件设计中深层次的东西。
· 在第一部分:如何使用设计模式中, Gamma给出了他对于如何正确思考和使用设计模式的看法,并且描述了模式库(比如GoF)和Alexandrian的模式语言之间的差异。
· 在第二部分:Erich Gamma讲述灵活性和重用中, Gamma谈论了重用的重要性,推测(speculating)的风险,以及 框架症(frameworkitis)所带来的问题。
· 在第三部分:来自《设计模式》的设计原则中,Gamma谈论了在GoF书中被着重强调的两个设计原则:针对接口(而不是实现)编程,优先选择对象组合而不是类继承。
· 在第四部分:《模式与实践》中,Gamma谈论了设计模式是如何成为成对的问题解决方案(problem solution pair),设计模式如何帮助你理解意图(intent)和折衷(tradeoffs),以及如何通过实践成为一个好的设计师。
· 在这一次访谈中,Gamma描述了Eclipse团队所采用的开发流程,这个团队的“发布传统,”以及透明度(transparency)在围绕一个产品构建一个社区的时候的重要性。
发布的传统(A culture of shipping)
Bill Venners: 您参与Eclipse项目已经有多长时间了? 您觉的在这个过程当中,关于开发流程,您和Eclipse团队学到的的最重要的经验教训是什么?
Erich Gamma: 从一开始我就参与了Eclipse。确实很难给出一个确切的开始日期,因为有几个项目很自然地演化成了Eclipse的一部分。例如,那时候我已经在忙于Visual Age Micro Edition的集成开发环境了。有些组件一开始是在这个项目里的,持续不断地改进以后成了Eclipse的一部分。SWT也是在这个项目期间诞生的。我想大概已经有六年了。
当Eclipse项目开始的时候,OTI有一个传统(culture)要求把注意力集中在按时发布(shipping on time)上,它总是可以让大家位于开发流程的中心。从那时起我就是与John Wiegand一起工作的人中的一员,我们不断调节我们的开发方法。在过去的六年当中,我们持续不断地调整。我们试了各种各样的方法。不好用的那些我们就不再采用了,好用的方法我们继续保持。而且,我们的团队干的还不错。
我们学到的一点是,梳理出(teasing out)持续的、可交付使用的东西是非常重要的。一开始我们没意识到这一点。带来的结果就是在发布周期将近结束的时候,为了完工顶着压力加班加点。现在我们的发布间隔比较短。每六个礼拜是一个里程碑(milestone)。我们是逐渐发展成这样的,现在我们朝着随时为发布做好准备而努力这种模式前进——我们希望随时都可以进入beta测试阶段。
因为我们是开源的(项目),所以我们同样知道社区反馈的重要性。与社区的交互是至关重要的,透明也同样重要,这样整个社区才能参与其中。我们达到了一个很好的透明度,但是我们仍然在不断地努力试图做的更好,以及让社区更多地参与进来。这是显而易见的,不是么?社区的参与度越高,最终的结果就越好。
Bill Venners: 看起来您对于什么是软件发布的好的传统是有自己的看法的?
Erich Gamma: 是的。就软件来说,有酷点子固然很好,但是发布它们才是关键所在。对于我们来说,只有发布了它们才有意义。这实际上是我们一贯的倾向。既然说了要把焦点放在发布上,我们可不想采用一直要等上两年才发布一次的模式。你需要有周期较短的可交付使用的东西。你还得做好计划和决定,并且按照这种习惯来实施。你很清楚风险在哪里——因为你知道哪些是自己力所能及的,所以你仍然可以按时保质地发布。
持续不断地交付使用(Continuous deliverables)
Bill Venners: 在Eclipse项目中您是如何持续不断地发布可交付使用的东西的?
Erich Gamma: 我们把发布周期划分成粒度(granularity)为六周的里程碑(milestones),每个里程碑都以一个改进过的、可用的、成功编译的Eclipse作为结束。大体上说,这六个礼拜就像是一个小的开发周期,在此期间我们做计划,然后进行开发和测试。通过这种分段的大的计划,我们针对每个发布实施好几个小的开发周期。我们会拿出一天让所有的人喘口气(???get out of the water),也就是做测试。针对每个里程碑做测试避免了在发布周期将要结束的时候我们会累积一大堆的测试工作。接下来我们把新的和值得注意的东西写成文档,然后我们把这些宣布给社区,这样他们就可以评说我们的进展并且尽早地给出反馈。然后我们计划下一个里程碑,我们会把总体的计划和针对单个组件的计划都考虑在内。
所以说我们总是希望处于beta测试阶段。特别地,我们不希望躲在黑暗里,让大家一连数月不知道我们在干什么。我们的目标是让我们的社区跟踪我们的进展并且提供持续不断的反馈。
Bill Venners: 为什么说让社区跟踪你们的进展是很有价值的? 透明的开发是否更适合于开源项目,或者您是否认为非开源的项目也能从中受益?
Erich Gamma: 我想这和开源与否并没有关系。软件创建一个社区,如果你想要使一个社区发展壮大,透明的开发是非常重要的。特别是开源,尽管(这么称呼),但它并不是仅仅依照某些license开放源代码;实际上它是要建立一个社区。你通过给他们展示你想要做的事情来建立一个社区,也就意味着你要让大家能够看到你的计划。我们所有关于里程碑的计划和项目计划都可以在网上看到。所有的bug也都是可见的。整个社区可以很真实地看到我们在干什么。当然,作为回报,我们希望的是整个社区能够参与进来。这种参与可以有许多种形式——比如通过bug报告提供反馈,帮忙回答新闻组(newsgroup)里的问题,提供补丁程序,实现其它的插件,或者写一些文章。这些就是组成一个紧凑的反馈循环的一些元素,这种反馈循环对于最终产生令人满意的可发布产品来说是至关重要的。Eclipse拥有一个如此活跃的社区实在是酷毙了,这也是我们的一个主要资产。拥有这样一个社区,无论是对于开源还是非开源的环境来说都是一个资产。
Bill Venners: 您说了,你们先做计划,然后执行,再然后测试。在以六周为单位的小的开发周期开始的时候,你们计划多长时间?
Erich Gamma: 我们通常试着在一周后公布我们关于里程碑的计划。每个开发周期的最后一周是“冷却时间(chill down)”。典型的情况下,我们在周二做一个备选的编译(candidate build),周三做测试,周四修整一些重要的bug,周五的时候我们宣布这个里程碑的编译(milestone build)。为了宣布milestone build,负责每个组件(component)的小组都需要承诺,“是的,我的组件准备好了。”如果仍然有关于编译的问题,那就需要额外地编译组件。
这有点像驾驶一辆公共汽车并且弄清出你应该停靠多少个站台。如果停靠地站台过多,那么起动和停靠就会把你的速度慢下来。这就是我们选择六个礼拜的理由。我们需要一个礼拜来做好计划,而且还需要大半周地时间来停下来。
Bill Venners: 也就是说你们有四个礼拜的执行时间?
Erich Gamma: 是的,这么安排给了我们至少四个礼拜的执行时间,这让我们有足够的时间做一些重大的事情。你必须能够在一个开发周期内解决一些比较重大的问题。一开始我们采用四个礼拜为一个周期,但是发现在四个礼拜的周期内起动并且停止实在是太吃力了。
Bill Venners: 在这些发布周期之间您是否安排了休息减压的时间呢?
Erich Gamma: 每次发布一个大的版本(major release)之后,我们有一个月左右的休息时间。通常我们在六月份或七月份大家休假之前提交发布版本。然后我们会安排一些计划好的休息减压时间,回头看看并且考虑一下哪些是起作用的哪些是不起作用的,以及哪些是可以改进的。这也是研究新东西的时候。然后我们转入思考下一个发布版本。
Bill Venners: 在每次小的发布周期开始的时候是否有一个比较短的休息减压时间呢?
Erich Gamma: 当真正有压力的时候,你才需要减压,但是里程碑发布这个点子就是为了避免持续不断地受到压力。确切地说,我们希望不间断地开发并且有一个正常的节奏。我们起动,然后停下来,最后我们发布一个实际的——而不是关于里程碑的——版本,这时候我们就有压力了。到了最后的时刻了,而且很紧张。为了处理最后几分钟的完善工作或者是性能问题,我们必须做测试和非常小心地修整。我们知道自己只能在有限的时间内做这些事情。整个步骤行将结束的时候是非常累人的,完事以后你需要给自己减压,因为越到最后每个人必须做大量的有压力的工作。
Bill Venners: 整个步骤行将结束的时候是指什么?
Erich Gamma: 指最后那六个礼拜。我们经历一个又一个的里程碑,然后基本上最后一个里程碑就是整个步骤将要结束的时候。通常它也是六个礼拜。这时候我们需要汇总。我们希望稳定一下然后继续小心前行。这六个礼拜的计划更为详尽,而且整个步骤结束的计划会公布在网上。最后的结束计划定义了重复不断地测试、修整的节律。整个团队,在社区的协助下完成这些工作。所有的开发人员和整个社区进行为期两天的测试,然后我们进行四到五天的修整。然后再次进行两三天的测试。如果这些修改都可以通过,就很难再加入其它的变动。换句话说,越接近结束的时候,越难加入其它的变动。比如,如果要修改一个bug,就必须发邮件到开发者的邮件列表(mailing list),而且所作的修改都要经过同事复查(peer-reviewed)。
行将结束的时候还可能给我门带来压力的是,有时候有一些波动(ripples)没办法不渗透到上层去。我们当然希望做计划好的事情,但是到整个步骤行将结束的时候很难做到把所有事情都计划好。
Bill Venners: 什么样的波动呢?
Erich Gamma: 比如,我们发现某个较低抽象层添加了一种新的机制,而这种机制还没有在所有比较靠上的抽象层得以发挥作用(leveraged)。这种波动是很难被计划到的。某个靠上的抽象层可能已经转向于一个新的函数,而较低的抽象层以为这一切都已经好了。
Bill Venners: 听起来像是一个关于沟通的问题。写底层的人们应该和写上层的人们更好地沟通一下。
Erich Gamma: 完全正确,我提及这个问题是为了说明,即使已经按时发布了好几年,我们仍然没有做到完美无缺。我们发现最好的解决方法是,让底层通过提供补丁的方式帮助把需求的变更向前传递,进而为上层提供帮助。我们试图养成的一个习惯是,在一个新的功能(feature)渗透到所有抽象层之前,都不能算实现了这个功能。
Eclipse开发中的敏捷实践(Agile practices)
Bill Venners: Eclipse团队遵循哪些敏捷实践呢?
Erich Gamma: 你不仅会在我们的工作中看到我们的敏捷实践,而且你还可以从我们写代码构建的工具中发现它们。我们支持重构和单元测试,并且通过一个本地历史信息和紧密集成的版本控制让你不用担心开发中的(版本)问题,我们支持直接在Eclipse中使用Ant——或者类似的东西——进行自动编译。
至于我们在开发Eclipse的时候所遵循的敏捷实践,我们总是尽早测试,并且经常性地进行自动测试。针对每次编译的结果我们都要运行超过2万个测试。我们有自动的每晚构建(nightly builds)。会有编译报告告诉我们失败信息。最近在3.1版本里,我们加入了性能测试。所以我们不仅仅测试正确性,而且我们还测试性能。这在3.1的开发周期中帮了我们的大忙,实际上你会注意到3.1版本的性能得到了大幅提升。
我们实践了递增式设计(incremental design)。我们一上来就直接把API弄出来。接下来我们一点一点地对它们进行改进。我们做重构,但是重构的时候我们牢记保持已发布API的稳定性。我们不能打断客户端。每天我们也吃自己的狗食。每个组件都发布(exports)它自己的最新插件并且让这些插件基于自己运行。这样做很棒,因为你是第一个发现自己错误的人。当然,当你是在构建一个集成开发环境(IDE)或者工具的时候,你就有更充裕的机会发现自己的错误。有时候我们每天不止部署(deploy)一次。所以如果我们在最近两小时引入了Bug,通常我们可以在每日构建(daily build)开始以前就发现它门。
Bill Venners: 你真的把那些组件部署到开发者的工作站上,而且他们使用当前发布的版本来做手头的事情么?
Erich Gamma: 是的,确实如此。开发人员安装他们的插件的最新编译版本并且一道运行它们。
用户参与是一个敏捷实践。就开源来说,它意味着社区参与。而且我们有一个非常活跃的大社区。社区的人们并不害羞。他们提出雄心勃勃的要求,但是最终结果是和这样一个社区一起工作是收获颇丰并且很有意思的。
另外一个敏捷实践是持续集成(continous integration)。我们每晚、每周、每个里程碑都要做构建(builds)。我们还有一个逐步升级构建(build promotion)的概念。每晚构建编译最新的代码。我们把它当作找出组件之间继承问题的预警系统来使用。下一个级别是集成构建(integration build):每周一次,我们想要的是对于其他Eclipse开发者(committers)来说好用的东西。再下一个级别是里程碑构建(milestone build),每六周一次。现在我们想要的不是仅仅对我们这些开发者有用的东西,而且还要对整个社区也得很有用。所以我们实践了不断升级的持续集成。
我们也实践了短的开发周期。我们的开发周期并不像XP所建议的那样短。如同我前面解释的公共汽车停靠的那个比方,我们觉得没法比六个礼拜的周期再短了。
我们还通过time boxing来做递增式的计划(incremental planning)。既然我们采用六个礼拜作为一个周期,这就是我们的time box。最上层的计划也是一个动态的计划,它以递增的方式被更新。也就是说,我们不是一上来就给出最终的计划。我们有一个初步的计划列出里程碑、主题、以及主要工作,但是我们会随着时间推移对这个计划进行改动。这也是我们学到的一个经验教训。最初我们采用的是一成不变的计划,这就意味着只有在开始的时候这个计划才是准确的,而随后就不是那么回事了。我们决定一遍执行一遍制定计划,现在最后版本的计划直到发布的那一天才出来。我们所有的计划的制定都是透明的。对于每一个计划条目我们都说明它是承诺的(committed)还是提议的(proposed),并且定期更新它的状态。这样社区就知道哪些是我们承诺要做的,哪些是我们的提议。通常我们希望达到预期的目标,如果不能,我们会希望取消哪些提议性的条目,但是我们不会轻易去掉承诺的条目。回头看看3.1版本,我很高兴,这种情况几乎没有发生。
下周
7月11号,星期一,请您回来看与Erich Gamma这次谈话的下一部分。如果你想收到Artima.com上新文章每周简报的电子邮件,请订阅 Artima Newsletter。
反馈
对本文中讨论的设计模式话题有自己的观点么?那么请到文章论坛里讨论这个话题, Eclipse's Culture of Shipping.
资源
[1] Erich Gamma是《设计模式:可复用面向对象软件的基础》的合著者之一,可以在Amazon.com上找到这本书 :
http://www.amazon.com/exec/obidos/ASIN/0201633612/
[2] Erich Gamma 是JUnit的作者之一,JUnit是事实上的Java单元测试标准工具:
http://www.junit.org/index.htm
[3] Erich Gamma 领导Eclipse平台上与Java开发相关的事务:
关于作者
Bill Venners 是Artima软件公司的主席兼Artima Developer的主编。他是《Inside the Java Virtual Machine》一书的作者,该书从面向程序员的角度讲述了Java平台的架构和内幕。他在JavaWorld杂志上广受欢迎的专栏覆盖了Java内幕,面向对象设计,以及Jini。从Jini启动以来,Bill就活跃在这个社区。他领导Jini社区的ServiceUI项目,这个ServiceUI API成为连接用户接口和Jini服务之间既成事实的标准方法。Bill还被选为Jini社区最初的技术监管委员会(TOC)的一员,他担任这个职务期间帮助定义了社区的管理流程。