契约

在自由软件项目中的契约需要小心处理。理想状况下,你希望一个承包者的工作被社区接受并打包进入公共发布版本。在理论上,谁是承包者并不重要,只要他的作品足够好并满足项目的指导方针。理论和实践一般也是一致的:一个通过贡献好的补丁展示自己的完全陌生人通常能将代码置入软件当中。问题是,一个完全的陌生人很难为非琐碎的改进或新的特性贡献好的补丁;一个人必须首先和项目的其他人进行讨论。讨论的时间不能精确预测。如果承包者根据小时付费,你最终可能会付出超过预期的费用;如果他是通过总费用支付,那么他最终会做出超过承受能力的工作。

这里有两种方式。较好的一个方法是根据以前的经验,对讨论过程的长度做出一个有根据的推测,并要考虑到出错的延误,并根据这些信息完成契约。这也有利于尽可能的将问题分离为许多小的独立的区块,增加每个区块的可预测能力。另一个方法是为每一个发布的补丁单独契约,然后将补丁的被接受当作公共项目一个独立的事件。这样编写契约就可以很容易,但是只要你依赖这个软件,或至少在这个补丁或对应功能进入主线的这些时间里,你必须承担维护单个补丁的责任。当然,即使是你中意的方法,契约本身不能要求代码必须可以接受补丁,因为那会包含出售一些不能销售的东西。 (如果项目的余下成员不希望对这个特性提供支持?)然而,契约可以要求真诚地投入以获得社区接受的机会,也就是在社区认可的情况下被提交到版本库。例如,如果项目编写了代码变更的标准,契约可以参考这个标准并指明作品必须达标。在实践中,这通常会超出每个人期望的方式。

最好的策略是雇佣项目的一个开发者—最好是提交者—作为承包者。这可以看作是购买影响力的一种形式。但是并不是表面上那样的不道德。一个开发者对于项目的影响力主要取决于他的代码质量和与其他开发者的交互。他作为承包者完成特定工作的举动并不会提升他的状态,当然也不会降低,尽管这样会让人们对他更加仔细的审视。大多数开发者不会因为返回不当或广泛反对的新特性而让自己的长期位置经受风险。实际上,当你雇佣一个这样承包者时,一定程度上你会得到,或者说一定会得到一些关于哪些变更会被社区接受的忠告。项目的优先级也会得到些许转变。因为优先级只与哪个人有时间完成哪个任务有关,当你为某人的时间支付时,会导致他们工作的优先级提前一些。这是经验丰富的开源开发者都理解的一个事实,至少他们中的某些人会将精力投入到承包者的工作上,仅仅因为它看起来将要完成,所以他们希望去帮助正确完成。或许他们不会编写任何代码,但是他们还是会讨论设计并评审代码,这些都非常有用。出于以上原因,承包者最好是那些已经参与到项目的人。

这样立刻凸显了两个问题:承包协议必须是私密的吗?如果不是,你应当为你在社区中造成的不安而感到担忧吗?你为某些开发者提供了承包合同,为什么不是其他人呢?

如果可以,最好将合同公开。否则,承包者的行为与社区中的其他人相比会看起来有些奇怪—或许他突然对一些过去从未表现出兴趣的特性展示出了不可理解的高优先级。当人们询问其原因时,他怎样才能避免说出他是根据合同编写代码,同时回答的让人信服。

与此同时,你和承包者都不应该表现的仿佛其他人应当把你的安排看得过重。我见过一些承包者招摇着进入开发列表,自认为他们的留言应该被更加郑重的对待,仅仅因为他们是支付薪水的。那种态度也是对于项目其他人的一种信号,承包者看重合同这件事—而不是合同导致的代码—本应当是重要的事情。但是从其他开发者的视角,只有代码有意义。在任何时候,注意力应该保持在技术问题上,而不是谁给谁付薪水的细节。例如,Subversion社区的一个开发者用一种优雅的方式处理承包。当在IRC讨论他的代码变更时,他会在旁白(通常是在私有备注,一种IRC privmsg,发送给其他提交者)中提及他是被支付薪水完成特定bug或特性。但是他也一直表现出无论如何他都会作出那些变更的印象,并很高兴金钱可以让他完成那些工作。他可以表露客户的身份,也可以不表露,但是无论怎样,他没有详述合同。他关于此事的备注只是一个对于如何完成工作的另类技术讨论的修饰。

那个例子也展示了开放承包合同带来益处的另一个原因。会有多个组织为开源项目资助承包,如果他们都知道其他人的目标,他们可以更好的调配资源。在上面的例子中,项目最大的创建者(CollabNet)没有以任何方式参与这种计件承包,但是当知道有人为某些bug修正提供资助时,CollabNet便将其资源转向到了其他bug上,从整体上大大提高了项目的效率。

其他开发者会憎恨这些因为薪水而为项目工作的人吗?通常情况下不会,这些得到支付的人都是社区值的尊敬的成员。没有人会期待承包工作会公平的分发给所有的提交者。人们理解长期关系的重要性:从事承包的不确定性会导致一旦你发现某人值的信赖,你就不太会只是因为公平性而找其他人。可以这样想一下:你第一次雇佣时,不会有抱怨,因为你必须选出某人—不能雇佣所有人不是你的错。此后,当你第二次雇佣此人时,那只是常识:你已经了解了他,上一次是成功的,为什么要承担不必要的风险?因此,只雇佣一个或两个人,而不是将工作分散开,这是非常自然的。

评审和接受变更

社区对于承包工作的成功也非常重要。他们为较大变更所投入的设计和评审过程不能只是事后处理。不应该把它当作工作的一个部分,并且完全交给承包者。不要把社区的仔细审查当作需要克服的障碍—而应该把它当作一个免费的设计委员会和QA部门。可以从攻击性的追逐中获益,而不仅仅是忍受。

案例研究:CVS密码认证协议

1995年,作为合伙人中的一个,我为CVS(并行版本系统,见http://www.cvshome.org/)提供支持和改进。我的搭档Jim和我,当时在非正式的维护着CVS。但是我们没有仔细考虑如何与已有的,主要是志愿者的CVS开发社区处理关系。我们只是假定他们会发送补丁,我们会应用补丁,那样就会一切正常。

那时,网络化的CVS还只能通过如rsh的远程登录程序完成。在CVS访问时使用与登录相同的密码显然存在安全风险,许多组织因此而放弃。一个主要的投资银行雇佣我们来添加一个认证机制,这样他们就可以使用网络CVS安全的连接远程办公室。

Jim和我得到这个契约并坐下来设计新的认证系统。我们面临的问题非常简单(当时美国对于加密算法代码有出口控制,所以客户知道我们无法实现较强的加密),但是因为我们没有设计这种协议的经验,我们还是作出了许多对于专家来说非常明显的错误。如果我们能够花时间写下提议并交给其他开发者评审,这些错误可以很容易的被发现。但是我们没有这样做,因为我们当时没有把开发列表当作可以利用的资源。我们认为人们将会接受所有我们提交的东西,而且—因为我们不知道我们所不知道的—我们不愿意在众目睽睽之下工作,例如频繁发布补丁,在一个特殊的分支作出较小、简单和易消化的提交等等。最后的认证协议并不是很好,当然,一旦建立起来,就很难在改进了,因为兼容性的考虑。

问题的根源是缺乏经验,我们可以轻易的认识到我们需要的知识。问题是我们对志愿者开发社区的态度。我们将对变更的接受当成了跨越障碍,而不是变更可以被改进的一个过程。因为我们很自信我们所做的任何事情都几乎会被接受(事实也是如此),所以放弃了让其他人参与的努力。

很明显,当你选了一个承包者,你一定希望他拥有此工作的正确技术技能和经验。但是,同样重要的是要选择一个拥有与社区其他开发者有建设性交流历史的人。你得到的不仅仅是一个人,也是一个代理人,他将会构建一套专业技能网络以确保他是以健壮和可维护的方式完成的工作。