阅读视图

发现新文章,点击刷新页面。

远程工作、开源协同与饱和沟通

上周末在给 Apache Ratis 的代码库上 Maven Wrapper 的时候,项目作者 @szetszwo 对 Pull Request (PR) 当中代码的合规问题和实现问题提出了一些问题。虽然这些问题并不难回答,但是我第一时间的反应却是“这么明显的答案,实在是懒得回复”。进而我又想到,如果是线下集中办公或者面对面 workshop 的情形,这些问题不到五分钟就能讨论清楚,而这两类不同环境当中开发者的表现差异,正好是接触和适应远程工作与开源协同的一个门槛。由此,我想讨论一下远程工作、开源协同与饱和沟通的问题。

集中办公的效率

首先声明,对于自控力和自驱力强的开发者来说,远程办公能够有效地避免心流被打断。这也让管理者无需苦恼于《人件》当中介绍的种种“办公环境”的错误实践。此外,不用耗费额外的时间通勤,以及不限居住城市的条件,对特定候选人的吸引力是决定性的。应当说,开发者群体的远程办公、分布式办公是不可逆转的趋势。支持远程办公的企业在吸引到更多高水平开发者的同时,并没有降低人效,从而市场竞争最终必然推向广泛支持远程办公。

当然,支持远程办公不意味着必须远程办公,集中办公强大的惯性和沟通效率的优势仍然支持其存在的理由。

若干年前,我在线下跟 Apache Flink 的主要作者 Stephan Ewen 交流的时候,问过他社群当中的议案,会不会因为提议者来自不同组织而被差别对待。他说这在规则上是不会的,但是实际上,同一个组织的开发者,尤其是集中办公,有问题转过头三两句就能聊清楚的团体,能够更快地调整议案达成一致,在组织对项目有一定话语权的前提下,其提议被接受和实行的概率显然是更高的。

我曾经总结过中国开发者在开源社群当中交流应该有的层次感:

例如现在有一个议案,在几个发起人初步对齐之后,先在邮件列表或论坛上发布,交流过程中发现英文词不达意的,转到微信用中文快速同步,再不行就打电话或者面见。这样,是从大范围逐步缩小到小范围,大范围同步信息,小范围解决冲突。

这里面,“初步对齐”和“面见”都是集中办公下天然就能做到的事情,能够坐到一起办公,语言往往也默认不是一个问题。然而,当一个社群逐渐吸引到不同国家不同文化背景的参与者之后,能不能 fallback 到中文沟通,能不能用微信交流,就是一个巨大的挑战。对于许多开发者来说,用英文笔谈已属不易,更不用说线上视频英文对话,甚至想办法线下面谈。

我在不少开源社群的参与当中也有这样的经历。如果我发现一个开发者是中国人,且他在 GitHub 等平台上的回应慢、理解困难,我会尝试加他的微信,中文或者电话讲清楚问题。如果同城或者日后出差经过,还能面见做深入的沟通。这样的引导可以帮助开发者逐渐成长起来,或者在目前的能力水平下做出更大的贡献。

然而,如果这个开发者是外国人,我就几乎只有 GitHub 或邮件的形式联系他,等待他的回复,而无法用他所在地的国民社交应用联系,更不可能线下见面。此外,虽然许多人下意识的把外国人都认为是说英语的人,但是 native speaker 和跟你我一样的英语第二外语的开发者,用英语沟通起来的体验也大不相同。当对方的英语跟你只是另一种与 Chinglish 不同的“方言”,你真的会发现把问题说明白都很费劲。

除了这种有沟通需要时,集中办公能够提供的效率以外,集中办公占据了个人白天的大量的时间,从而自然会导致成员之间超越工作的饱和沟通。

这种饱和沟通一方面促进了成员之间的信任和团队的归属感,从而使得相互能够理解对方行为的动机,快速领会不言而喻的意思;另一方面,在目的性不那么强的闲谈当中,往往会迸发出意想不到的创意。

Apple 的乔布斯是著名的远程工作反对者,他曾经说过“创造力源于自发的会议,来自随机的讨论。你遇到一个人,问问他在做什么,听了就说‘哇’,然后很快就有各种各样的点子冒出来。”

我在某电商公司上班的时候,CRUD 的工作每天只需要花不到两个小时的时间。剩下的时间里我会梳理团队的微服务关系和依赖的基础设施,有什么问题走到责任人桌边,往往聊两句就能知道代码背后的故事和以前到现在面临的问题。有过这样的交流,日后真的需要他人帮助时,对方对你的认识也就不局限于“这个来找我麻烦、给我增加工作量的从未谋面的人”,而是能够基于之前共同吐槽过的问题和共识,商讨当下的麻烦该怎么解决。自然,沟通过程当中只要稍加留意,你也不难发现“房间里的大象”,如果你还能把利益相关者的意见都收集起来,可能就会看到一个显而易见的解决方案。

而对于远程办公和分布式的开源协同来说,这会非常困难。因为在线闲谈的时间成本非常高昂,文字的表达能力远不及语言加上肢体动作,更不用说文字留底在工作环境下多少会为人所忌讳。而电话连线工作或者团队视频会议打开摄像头,则是一种让人无所适从的“监视”。

这样,对于一个新的团队来说,往往从未有过建立起相互了解和信任的机会;对于一个曾经集中办公的团队来说,也常常会逐渐降低交流频率,只在有求于人或者事情已经搞砸了的时候才会寻求沟通。

分布式协同的方法

虽然集中办公有必要时的沟通效率和随机讨论的创造力的优势,但是远程办公却能够维持开发者的心流,同时减少了通勤的开销和对办公地点的要求。《人件》当中对“办公环境”的讨论,旨在解决集中办公下维持开发者的心流的问题。我们可以从另一个角度出发,探讨如何在分布式协同的环境下,保持沟通的效率。

第一种方法是强化协同流程。注意,强化流程不意味着增加流程,而是在设置了必要的流程以后,明确其检查点并加以执行。

例如,比起各自为战,等到出了问题再事后补救,组织或社群都应该对关键的决策进行收拢,典型的做法是参考 RACI 模型建模。这样,责任人(Responsible)负责主导方案的制定和实施,决策人(Accountable)进行审核,领域专家(Consulted)和其他相关人员(Informed)可以提出意见,或者在责任人的协调下承担相应工作。

集中办公环境下自然也需要有职责分工,但是由于可以直接堵门,往往职责分工不明确能够被发现和提出。分布式环境下,没有通用语言会导致更加严重的分裂,其后果也更难补救。

RACI 模型的作用是在高沟通成本的环境下,确定了设置目标和制定方法的模式,从而让团队能够在共同目标和共识方法论的情况下开展工作。一旦出现问题,也能够通过讨论是否影响目标达成,以及工作方法是否需要改变来展开,避免无谓的消耗。

在这一模型下,责任人撰写议案(proposal)来设置目标和制定方法。因此,在团队或社群当中共享撰写议案的模板就尤为重要。成熟的开源社群大多有议案流程和模板,例如:

可以看到,这些议案模板往往是以一段话简介 + 动机 + Goals/NonGoals 开头,再展开具体的设计和技术细节。我在第一次写 Flink Improvement Proposal 的时候,就因为过于关注实现,默认老板让我做的就是合理的动机,写完代码而非解决问题就是目的,而被老板带着改了三四轮议案,也从此深刻记住了动机和 Goals/NonGoals 在议案中的重要性。

Pulsar 社群最近的一个提案 PIP-256 就因为长达 46 页的第一版提案,只在最后六页含糊地写了 Goals 而被挑战。其前 40 页几乎是对相关领域的调研和基础知识的科普,更像一篇介绍性的博客而非一份需要采取行动的议案,无怪乎另一名成员两次提问到:

  1. What are the exact problems we have?
  2. What exactly do we plan to change?

第二种方法是活动和催化。流程只能改进解决已知问题的效率,而不能激发创造性的沟通。TiDB User Group 不定期的会举报一系列的活动,邀请用户和开发者分享自己使用和开发时的案例,通过案例的交流,另一名用户可能发现解决自己问题更优的方法,另一名开发者可能发现一个没被解决好的问题可以改进。作为社群协调员,敏锐地发现这些端倪,串联起成员之间的开放式沟通,就有可能催化出创造性的成果。

《人件》有一章专门讨论“构建社区”的话题,跟这里介绍的方法就是殊途同归的。毕竟集中办公也不是每个组织团队都真的会有自发的会议和随机的讨论,只不过解决起这个问题,集中办公的环境和分布式办公的环境面临的挑战不一样罢了。

不过,上面这两种方法,也跟任何手段一样,并非喊出口号做出形式就能生效:流程不总是切实执行的,缺乏内容的活动和揠苗助长的催化只会适得其反。最终要想在分布式协同当中提升沟通效率,仍然需要依靠观念的改变:为什么我应该和他人沟通?什么时候应该和他人沟通?沟通什么?和谁?最后,才是如何高效地沟通。

参考阅读

对于分布式协同当中沟通的话题,我在《饱和沟通:开源社群的消息传递准则》当中有过一轮讨论,可以参考阅读。同样值得推荐的是《制造开源软件》对避免私下讨论的论述和第六章沟通

饱和沟通:开源社群的消息传递准则

分布式系统的开发者知道,不同于本地方法调用总是被执行,要么成功要么失败,分布式系统之间各个组件的远程调用还存在第三种可能,那就是超时。

从消息发送者的角度看来,超时意味着没有确认信息返回。但是当前调用对应的一系列操作到底是已经成功,只是回复丢失,还是其中某些失败某些成功,或者全部失败,甚至是请求本身没发出去,这些情况一概无法断言。

大部分开源社群是分布式组织,社群成员分布在不同的地域乃至不同的时区。相比于线下集中办公的组织而言,分布式组织与分布式系统一样存在着“超时”的挑战。

线下集中办公时,负责同一个工作项目的人经常会坐在一起,有什么事情转过头、走几步也就当面说清楚了。工作关系紧密的几个人往往会共享午餐时间,休息娱乐时间。这种面对面的合作带来的信任感和大小事情都能当面沟通的效率,是分布式组织很难直接做到的。

不过,无法效仿线下集中办公的方式直接面对面沟通,并不意味着开源社群这样的分布式组织的沟通效率就总是低下的。从我在开源社群数年的观察和实践来看,要想做到在开源社群这样的分布式组织当中高效地协同,确保事情在异步沟通和分布式合作的情形下仍然能够稳步前进,一个不可缺少的点就是饱和沟通(Overcommunicate)。

饱和沟通的重点落在“饱和”,这意味着沟通反馈必须是及时的,甚至会稍微超出必要的限度。

我刚进入到开发者社群关系的角色的时候,曾经被问过这样一个问题:为什么你能够在 Flink 社群持续参与,直到成为 Committer 呢。稍加思索过后,我给出了这样的答复:因为在 Flink 社群里,我的提问会有人回复,我的补丁会有人评审,这是一个能够得到反馈的社群,我喜欢这样的正反馈循环。

要想在开源社群建立起正反馈循环,关键在于沉默的参与者能否主动发声,相对少数的维护者能否给予必要的回复。

前不久,我在推特上看到这样一条推文

现实:

  1. 提了 PR,经过了几轮 review,PR 的作者消失了,PR 就一直挂在那儿;
  2. 提了 PR,经过了几轮 review,maintainer 不跟进了,PR 就一直挂在那儿;
  3. 提了 PR,maintainer 根本没有任何反馈,PR 就一直挂在那儿。

这反映出开源社群当中沟通的缺失,已经成为众多参与者面临的共同问题。

我在《高效参与开源的诀窍》当中提出,新成员首先要明确加入开源社群,跟社群建立起联系。

虽然刚开始的一段时间可能会感到无从下手,先观察其他成员讨论的内容和做法也不失为一个选择,但是很快你就应当试着加入到讨论当中,针对你不懂的问题大胆的提出自己的疑惑。绝大部分社群成员愿意解答其他人的问题,或者引导你到能够解决问题的地方。经过这样的几轮沟通,社群成员对你也能建立起基本的了解,你也知道什么问题应该在哪里求助。反之,如果像我在《高效参与开源的诀窍》所举的反例那样,闭门造车式地想要搞个大功能,而社群完全不知道你在做的工作,那么社群前进的过程中就有可能无意间破坏了你所做的功能设计的假设,使得费劲心力设计的大教堂图纸付诸东流。

Kvrocks 的参与者 @xiaobiaozhao 在今年六月份的时候提出可以用 LuaJIT 替换 Lua 实现更好的执行性能。在得到两位项目维护者的回复和鼓励以后,他拿出一个原型以供测试。最终经过近一个月四名 Reviewer 一共五十余条消息的讨论和建议以后,成功地以后向兼容的方式用上了 LuaJIT 依赖。这是 Redis 上游都没有办成的事情。

这个过程当中,所有参与者都及时地在 GitHub PR Review 这个平台上同步自己测试的结果和改动意见,对于自己拿不准的地方提出自己的问题和阶段性的想法。当补丁合并被其他问题阻塞住一度搁置的时候,一旦阻塞问题解决,也能有人想起来重提这个补丁让几名 reviewer 再次判断是否可以合并。

这就是开源协同非常典型的一种合作方式。愿意投入时间发起或推进某项工作的成员,积极地与其他相关成员沟通获取必要的信息,做出自己力所能及的贡献,并同步结果和请求进一步的反馈。

我在进行 TiDB 测试迁移工作的过程中,会随时同步编码上的最佳实践以及与其他参与者协同的过程中得出的结论。这些结论在后续其他相关工作里被多次引用,迁移工作本身也被作为 tracking issue 管理工程的实践被其他项目所借鉴。在将近一年的过程中,tracking issue 和不少 subtask 都有我和其他社群成员的沟通,有些 issue 在估期和细节上的沟通甚至有些啰嗦,但是这种多次发送消息和确认的过程却实在地避免了不知道对方是否理解了自己意思的问题。

即使是在面对面的沟通当中,误会也时常发生。异步沟通的方式本来就缺少微表情和肢体语言的信息量,如果合作者对于相关信息的同步再三缄其口,假设其他人能够独立得出和自己一样的结论,那就是异想天开了。

当然,overcommunicate 一词也有两面性。如果饱和沟通超出了必要的限度,变成信息轰炸,对于所有参与者来说就成了一种负担和消耗。要想避免饱和沟通变成信息轰炸,可以从两个方面入手。

第一个,虽然饱和沟通要及时反馈进展和提出问题,但这并不等同于任何中间过程都要急火火地发布出来。由于异步协同天然的滞后性,阅读消息并发出回复的成本比起面对面沟通是要高出许多的。只有适当整合自己的观点,简明扼要地分点提出问题并说明期望的回复,才能减少接收者的阅读理解负担。

我在 Pulsar 社群提议开启 Update Branch 按钮以改善开发者体验的时候,就采用了这种方式。首先以一句话说明期望读者做的事情,表明是否支持这个提案,然后再有一个完整版本分点说明这个提案的背景、意义和可能存疑的方面。在信息爆炸的时代,大部分人都会先判断这件事情是否与自己有关,是否应该付出时间了解细节。这是 TL;DR 大行其道的原因,也是在饱和沟通时不得不顺应的环境。

第二个,饱和沟通绝不是 at 所有人或者随机找人搭话。参与社群一段时间后,你应该能够知道项目不同领域的大致划分。例如,谁是某个功能模块的专家,谁负责项目构建逻辑的维护,谁对 CI 的问题最清楚,谁是总体协调社群的领袖。如果你想让自己的提案得到回复,最好根据提案涉及的领域和决策的影响范围来确定干系人,把饱和沟通的策略应用在这些干系人上,而不是无差别地骚扰社群成员。

要想做到这一点,可以参考 RACI 模型来对当前工作及其干系人建模。RACI 模型把干系人分成四类:实际完成工作的责任人(Responsible)、参与投票的决策人(Accountable)、可以寻求帮助的领域专家(Consulted)和需要知悉这项工作正在发生的相关人员(Informed)。

例如,提出拆分 Pulsar SQL 的提案的过程中,我是实际完成工作的责任人。首先,我要密切联系的是参与投票的决策人,在 Pulsar 社群当中,这主要是关注整体模块演进的领袖,比如多次关注此事的 Matteo Merli 等。其次,我要尝试寻求帮助的是此前参与过相关工作的成员,尤其是向上游 Trino 社群提过 Pulsar Plugin 补丁的 Marvin 和补丁的 reviewer 们。最后,由于拆分方案涉及到打包和 CI 的变化,我需要在以 Pulsar Improvement Proposal (PIP) 的方式全社群可见的提出这个提案,知悉所有人。其中,我会专门跟当前 CI 的作者 Lari Hotari 打个招呼,并在修改打包内容的过程中发现有相关的提案,都告知他们有另一个和打包相关的提案正在进行。

例如,作为 Kvrocks 项目里替换 Lua 提案的决策人之一,首先我会跟其他决策人同步意见。其次我会关注责任人对进度的把握,目前是否有阻塞的环节。如果 review 过程中间遇到了我自己拿不准主意的内容,我会试着找领域专家提供意见。到了 Kvrocks 项目里要采用现代 C++ 风格改写现有代码的决策里,我会放缓这个决策的推进,确保主要的开发者都知悉代码风格取向的变化,充分表达自己观点以后再做决策。

如果作为 Consulted 或 Informed 的角色,则一般不需要你主动推动工作的进展,只需要提示可能存在的风险,说明清楚问题并响应提问即可。

开源运动几十年来,发展出了一套适合于开源社群这类分布式组织的一套协同工作方式。依靠开源协同的力量,开源共同体调动起全球范围内全行业的精英的积极性,一起开发高质量软件。越来越多的软件公司也试图借鉴开源协同的模式来提高软件开发的效率,越来越多的公司因为自己的业务依托于开源软件的发展而不得不了解开源协同的工作方式。

要想参与到开源协同当中来,就必须适应饱和沟通的工作方式,否则将始终游离于多样化的社群之外。要想学习开源协同的方式建设高效的分布式组织,实践饱和沟通的经验是一个很好的切入点。分布式组织独特的挑战,很大部分是由于地域和时区的隔阂带来的沟通难题,如果能以饱和沟通的经验在不同地域的成员之间建立起信任,保证工作不断地向前推进并且每个干系人都能被“饱和”覆盖到,那么解决其他组织管理问题,也将势如破竹。

❌