反馈闭环

从体验日志的一侧去闭合客户反馈循环的方法

阅读约 1 分钟

一个客户反馈循环真正闭合,是在提出反馈的那个人被告知它后来怎么样了的时候。不是在它被记录下来的时候,不是在它被排上优先级的时候,甚至不是在它上线的时候。而是在被告知的那一刻。大多数团队能把前三个步骤做得很好,最后一个却完全不做,然后奇怪为什么发反馈的人渐渐不再发了。

这篇文章讲的正是最后这一步,以及一个具体的主张:体验日志才是应该用来闭合这个循环的地方,因为它是唯一一个在循环能够被闭合的那个时刻就已经存在的成果物。

什么是客户反馈循环

客户反馈循环,是从一个用户告诉你某件事,到那个用户得知你对此做了什么,这中间的整条路径。它有四个步骤:收集反馈、决定怎么处理、发布结果、告诉提出请求的人。在第四步发生之前,这个循环都是开着的。一个收集反馈、也发布了修复,却从不告诉任何人的团队,拥有的只是一个收件箱,而不是一个循环。

步骤会发生什么通常在哪里断裂
收集反馈到达:小组件、支持团队、销售、访谈什么都不会断;每个团队都会做这一步
决定被分类、和重复项合并、被接受或被拒绝拒绝的结果从来不会被传达出去
发布有人把它做出来,并且上线了与请求的关联在合并时就丢失了
告知请求者得知它已经上线被跳过,或者只对声音最大的请求者去做

这篇文章讲的正是第四行。它之所以断裂,是出于结构性的原因,而不是文化上的原因:等到一个功能真正上线时,引发它的那个请求,已经处在和已发布的东西完全不同的一个系统里,而没有人的工作职责是把这两者连接起来。这个循环要从更早的地方开始,也就是最初是怎样提出请求的;如何征集客户反馈介绍了措辞和时机。

为什么反馈循环会一直开着

反馈循环之所以一直开着,是因为请求和已发布的变化生活在不同的地方,而它们之间的关联,如果存在的话,也是靠手工建立的。请求在一个反馈工具、一个支持团队的收件箱,或者一份电子表格里。变化在一个 pull request 里。公告则在体验日志或一封邮件里。三个系统,三位负责人,从第三个回到第一个的那条关联,靠的是某个人在几个月后凭记忆想起来到底是谁提出的请求。

还有第二个原因。告知这一步通常被当成一项营销任务(“宣布这个功能”),而不是一项支持任务(“回复这个人”)。公告发给所有人,却没有触达任何一个具体的人。三月份要求这个功能的人,读到六月份的公告时——如果他读了的话——会把它当成新闻,而不是一个回复。只有当这条消息是明确针对本人的时候,这个循环才会闭合。

为什么要从体验日志一侧去闭合循环

因为体验日志的条目,正是那个在恰好正确的时刻存在、包含恰好正确的措辞、由恰好正确的人来撰写的唯一成果物。它在变化上线时才存在,此前并不存在。它用读者的语言说明了什么发生了变化,而这正是请求者需要的那条消息。而且它是由刚刚读过那个 pull request 的人写下来的,这也是原始请求与它之间的关联依然可见的唯一时刻。

比较一下其他的替代方案。从反馈工具一侧闭合循环,意味着反馈工具必须知道这个功能是什么时候上线的,也就意味着需要有人手工去更新一个状态。从 pull request 一侧闭合,意味着在合并的那一刻——变化还没真正上线的时候——就去告诉客户,而一旦部署被延迟,这就会变成一个带着时间戳的、被打破的承诺。从营销公告一侧闭合,则意味着要等一份公告出来,而大多数已发布的变化,从来都不会有公告。

体验日志正好处在中间:在合并之后,在发布的那个时刻,措辞也已经完成。

循环是如何一步一步闭合的

这是我们运行的这套机制。这里把它描述成一份规格说明,而不是一次产品导览,因为每一步都可以靠手工或者其他工具来完成;真正重要的是顺序。

  1. 反馈变成即将修复它的那个仓库里的一个 issue。 一次小组件提交会被记录为一个带标签的 GitHub issue(feature-request 或 bug、一个优先级,以及 from-widget),提交者的邮箱地址不会写进 issue 正文。这个 issue 就生活在代码旁边,好让第三步能够找到它。手工提交的 issue,比如用功能请求模板填写的那种,不在这条路径上:第五步不会在它上面发评论,所以这个循环需要你自己去闭合。
  2. 修复引用这个 issue。 pull request 里写着 Fixes #142,这是 GitHub 自己的关闭关键词。没有任何新东西要学,这和开发者已经在写的句子完全一样。
  3. 体验日志的条目从已合并的 pull request 起草而来,并携带着这条关联。 在合并时,草稿被创建出来,#142 从 PR 正文中被读取出来,并附加到这份草稿上。这条关联是在成本还很低的时候,由机器从已经存在的数据里建立起来的。
  4. 一个人来审核这条条目。 措辞、目标读者、以及它到底应不应该被公开发布。一份被放弃的草稿不会闭合任何东西,这是对的:一次恰好引用了某个 issue 的内部重构,并不是新闻。
  5. 一旦获得批准,请求者就会被告知。 一条评论会被发布在由他们的反馈转成的那个 issue 上,“Shipped —” 后面跟着这条条目的标题,以及一个指向已发布条目的链接,同时小组件也会向提交者展示同一条已上线的条目。只发一次,绝不发第二次,而且只在有人真正发布了这条条目之后才发。同一条条目也会通过信息流和小组件传递给所有没有提出请求的人。

第五步的这个顺序,正是整个设计的核心。在合并时就告诉请求者会更早、也更容易,但这样做出错的频率,几乎会和部署被延迟的频率一样高。Feature flag 甚至会打破这个顺序本身,因为”已批准并发布”完全可能发生在这个功能对请求者的账户来说依然不可见的时候;feature flag 和功能请求 讲解了一旦有 flag 掺和进来,这一步到底需要多做哪一层额外的核查。

对客户来说,一个已经闭合的循环是什么样的

它看起来就像一条回复。客户通过一个小组件发送了一个请求,然后有一天,小组件把它显示为已上线,还附上了一条用他们的语言来描述这件事的条目链接;在 GitHub 上,issue 也会以评论的形式收到同样的消息。他们没有订阅任何新闻通讯,没有去查看路线图,也没有去搜索体验日志。他们只是被告知了。

正是这种体验,促成了第二次反馈的发生。人们会向那些真正回应的产品发送反馈。体验日志范例页面收录了那些用户明显会不断带着新请求回来的团队的条目,它们的共同点并不是工具,而是这些条目读起来就像是一条回复。

如何衡量一个反馈循环

衡量那些至少告知了一位请求者的已发布变化所占的比例,以及从发布到告知之间经过的时间。这是两个数字,只要那条关联存在,衡量起来就很容易;如果不存在,就完全无法衡量。

  • 闭合率:本月发布的体验日志条目里,有多少条链接到了至少一个请求,其中又有多少条真正通知了请求者。如果第二个数字远远低于第一个,说明通知环节出了问题;如果第一个数字本身就很低,说明请求没有从 pull request 中被引用,而修复方法就是在 PR 模板里加上一句话。
  • 发布到告知的时间:从条目上线到请求者被告知之间经过的时间。有了上面这套机制,这个时间是几秒钟。靠手工做,通常是几周,或者永远不会发生,而”永远不会发生”正是那个真正重要的数字。

不要用收集到的反馈数量来衡量这个循环。收集是最容易的一步,一个去衡量它的团队会去优化它,而这只会产生更多开着的循环。

路线图放在哪里合适

公开路线图是一种提前闭合循环的方式:它告诉请求者,在这件事上线之前,他们的请求就已经被听到了。它很有用,但不能替代最后那一步。“计划中”是关于未来的一个承诺;“已发布”则是关于当下的一个事实。从同一批 issue 出发,用每一列一个标签的方式来运行公开路线图,这样同一个请求就能从计划中移动到已发布,而不需要在任何地方重新录入。移到已发布是一次标签变更(roadmap:shipped),条目获批时不会有任何东西替你完成,所以要在同一次审核中一并处理。

FAQ

客户反馈循环的四个步骤是什么? 收集、决定、发布、告知。在第四步发生之前,这个循环都是开着的。许多框架会在中间加上分析和排优先级的步骤;它们只是”决定”这一步的细化,没有一个真正闭合了什么。

当你拒绝一个请求时,也应该告诉客户吗? 应该,而这正是循环里最容易被忽视的那条消息。一句清楚的”我们不会做这件事,理由是这样”能结束等待。沉默只会让循环永远开着,客户则会不停地去查看进展。

闭合循环和宣布一个功能有什么不同? 公告是发给所有人的。闭合循环则是对那些提出过请求的人,通过他们当初提出请求的那个渠道,做出的一次回复。两件事都要做;它们是写给不同读者的不同消息。

如果请求者不在 GitHub 上怎么办? 大多数都不在,这没关系。小组件会一直向他们展示所提交内容的状态,包括已上线的条目和它的链接,所以除了当初写下反馈的那个页面,他们什么都不需要。issue 上的评论,是给那些能看到仓库的人看的。

这个循环在 GitLab 或 Bitbucket 上也能用,而不一定要用 GitHub 吗? 小组件和体验日志本身可以,但第五步那条自动评论目前还不行。一个用 GitLab 或 Bitbucket 的团队,依然能收到每一条提交,依然会把它记录成一个 issue,也依然会在小组件里向请求者展示状态,只是把这个循环具体闭合回那个 issue 本身,在这类集成出现之前,需要你自己手动去做。


本文的技术内容未经独立审核。如有错误,请告诉我们,我们会更正。

changeloop 相关页面: 开发者文档, changelog 示例

changeloop
打造闭环 changelog 的团队。用户提出需求,你的团队交付,提出需求的人得知结果。