一个远程办公的团队比坐在一个办公室里的团队需要更强的纪律。首先,我指的是沟通的纪律。在teamed.io, 我们已经远程开发软件有五年之久。我们通过问题清单系统(原文为ticketingsystem如Github, JIRA, Trac,Basecamp 等)来严格地管理任务,并且不鼓励任何不正式的沟通方式,如Skype, HipChat, 邮件或者电话。每一个ticket对我们来说都是一个有自己生命周期、参与者和目标的独立任务。这些年,我们有一些教训想分享给大家。如果你的团队也是远程办公,你会发现这些内容很有用。
1. 保持“一对一”
每一个ticket(即bug)都是两个人之间的连接:问题阐述者和问题解决者:如果这是一个bug,我汇报它——你解决它。如果这是一个问题,我要求一个解释——你解答。如果这是一项任务,我命令你去做——你完成它。无论怎样,都存在两个主要角色。不管有在ticket解决的过程中涉及多少人,只有这两种人具有正式的角色。
ticket汇报者的责任就是为该问题辩护。当我报告一个bug时,我必须坚称它存在——这是我的工作。其他人可能会说我错了,问题不存在。他们可能说他们无法复现这个问题,或者说我对一个任务的描述太模糊,没人能看得懂。可能还会存在许多其他争论。但是我的工作就是竭尽全力去保证这个“票”的存在。显然,当一个bug无法被复现时,我不得不关掉它。但是在那之前,我就是它的守护天使。:)
另一方面,ticket解决者的责任是为解决办法辩护。当一个ticket被分配给我,我不得不去解决它,那么我的工作就是去说服问题汇报者我的解决办法很好。他可能会说我的解决办法还不够,不是最有效率的,或者考虑不全面。我的工作就是坚称我是对的,而他是错的。当然,这得在一定合理范围之内。为了建立一个能被接受的解决办法,我首先得理解问题,研究所有可能的选择,并提出一个最优雅的实现手段。但这一切都是次要的。我要最先关注的事情是如何说服问题汇报者。我要永远记着,我的首要目的是关闭这个ticket。
我这里是想说,无论在问题的讨论中涉及多少人,永远记住真正发生的状况是——一个人向另一个人兜售自己的解决办法。剩下所有其他人都是在帮忙或者干扰(如下)。
2. 关闭问题!
记住,一个ticket不是聊天,你不是在那里说话,而是去关闭它。当一个ticket被分配给你,专心地去尽快关闭它。
另外,请记住,你越快地关闭ticket,你在项目里做的工作就越好。生命周期长的ticket是管理人员的噩梦。很难追踪和控制它们,也很难弄明白究竟是怎么回事。你是否见过那些在开源项目里长达两年的ticket有着上百个评论却没有可交付的成果?这是项目经理和问题参与人员的错误。每一个ticket都必须简短且专注——1)一个问题,2)一个精炼的提问,3)一个简短的解答,4)一个解决办法,5)被关闭。这是一个理想的情景,谢谢大家。
一旦你意识到你的ticket正在转变成冗长的讨论,那就尽快关闭它。如果问题汇报者不喜欢我的解决办法,那我怎么关闭它呢?想一个能让汇报者满意的临时的解决办法,使你能关闭问题。在你的用语里使用“待办事项”或者权宜之计——它们总比一个悬而未决很久的ticket要强的多。
一旦你发现解决办法已经有了,并且很充分,可以关掉ticket了,那么就去告诉问题汇报者去关掉它。要直截了当的说,不要左右言他道:“如果你不介意的话,这个解决办法应该可以接受了吧。”一定要目的明确清晰地表达。比如:“@jeff,如果你没有其它问题 ,请关闭这个ticket。”
3. 别关闭它!
每次你提一个bug,创建一个新的ticket,你都在消耗项目资源。每一个bug报告都意味着项目的花销:1)你用来找问题并汇报它的时间;2)项目经理用在处理ticket并找人修复它的时间;3)ticket解决者用来理解你的报告,提供解决办法的时间;4)所有其他参与讨论的人的时间。
如果你在一个问题还没有妥善解决的时候就关闭了ticket,就等于把钱扔进了垃圾桶。一旦ticket被创建了,就没有回头路。我们不能说,“算了,不去管它,反正不重要了。”你的ticket已经消耗了项目时间和预算资源,因此为了使其变得有用,你得确保有解决办法才行。
可以是一个暂时的解决办法,可以是项目文档里的一个单线改变,可以是代码里的一个“待办”标记,好像在说:”我们知道这个问题,但是因为我们比较懒所以不能解决它。”任何办法总比 没有强。
换一个不同的角度看待问题。当你创建那个ticket,你就意识到一些事。你知道这个产品哪里不对。这就是你报告bug的原因。如果你不经任何人修改代码就关闭了ticket,过几天或者几年其他人会发现同样的问题。于是项目又要为一个同样的问题开展相似的ticket讨论而付出开销。即使你确信你在乐器代码里发现的问题不是真正的问题,你也要跟ticket解决者说,把问题记录在源代码里,以防未来发生同样的困扰。
4. 避免噪音——你的评论要指定到人
每当你在ticket里发一条消息时,要指定给一个人。否则,如果你只是因为想表达自己的意见,你的评论就会成为交流的噪音。记住,一个ticket是两个人之间的对话——其中一个人报告问题而另一个人试图解决它。像“咱们试试另一种方法”或者“我记得我之前碰到过类似的问题”这种评论是非常烦人和让人分心的。说实话,没人真的需要或在意“看法”。我们在ticket里只是需要解决办法而已。
如果你觉得解决办法足够好,可以关闭ticket了,就要把你的评论指定给ticket报告者。然后说“@jeff,我觉得给你的这个解决方法挺好的,因为…”这样,你也帮助了分配到ticket 的人关闭ticket并继续工作。
如果你认为解决办法是错的,把你的评论指定给分配到ticket 的人,然后说“@jeff,我认为你的解决办法不好,因为...”这样,你就帮助ticket报告者使它保持开启状态,直到有合适的解决办法出现。
同样,别用笼统的意见来“污染空气”。相反,要非常明确地支持某一方——你要么喜欢解决方法,想关闭ticket,要么不喜欢它,想让ticket保持开启。两者中间其它的都是让情况更复杂,完全不能促进项目的进展。
5. 有断点时要汇报
虽然我觉得这是显而易见,但是我还是要重申:每个bug必须是可复现的。每次你报告一个bug,你都应该解释产品到底哪里坏了。是的,你的工作就是证明软件不像预期那样运转,或者没有被恰当地记录,或者不符合要求等等。
每一个bug报告都需要遵循同一个简单的公式:“这是我们现在有的,这是我们本应该有的,所以需要修复。”每一个ticket,无论是一个bug,一个任务,一个提问,或者建议,都应该按照这个格式来写。你提交了ticket,等于推动项目从A点前进到了B点。如果在A点时有问题,而如果在B点时对我们大家都有好处,那么很显然你需要解释A点和B点是在进度的哪个位置。如何找到bug这件事非常值得你解释一下——如何复现一个问题并且修复它。
即使当你只是想提问,你也应该遵循那个格式。假如你想提问,那就意味着项目的文档不足以供你找到答案,这也就是所谓的“断点”。因此你需要报修。与其在报告中说“我应该怎么用class X?“ 不如说”当前文档不完整,无法解释我应该怎么用class X的问题。请修复。”
如果你不能解释怎么找到bug的,也可以说:“我发现这个class不能像预期那样运行,但是我不知道怎么复现这个问题或者解决它。”这样你可以清晰地告诉大家你知道你的bug报告不完美。那么问题修复者首先要做的就是提炼问题并想办法复现它。如果不能找到复现的方法,显然你的bug就要被迫关闭了。
让我再最后重申一遍:每一个ticket都把项目从一个有问题的A点拉动到问题已修复的B点。而你作为一个ticket报告者的工作,就是画两点之间那一条直线——清晰明了地画。