优秀开发者体验的核心原则
基本概念
优化开发者体验主要关注三个核心方面:
周期时间(又称迭代时间):从开发者产生意图到实现该意图所需的时间。
专注度(又称"心流"):开发者保持专注于当前任务而不被打断的能力。
认知负载(又称所需知识和决策):开发者完成任务需要掌握的知识量以及必须做出的决策数量。
周期时间详解
软件开发包含大大小小的循环周期。最小的周期如"我打算写这行代码"或"我打算运行这个命令行工具查看输出";最大的周期如"我打算通过创建产品并让用户使用来解决问题"或"我们打算用100人一年的时间重新设计系统"。
加速大周期的方法通常是加速小周期。如果只关注加速大周期,结果质量往往会受到影响。例如,如果一个团队需要两周才能将任何更改部署到生产环境,简单地要求"不惜一切代价加快部署"会导致团队走捷径,损害最终结果的质量和软件的可维护性。
深入调查会发现存在耗时过长的小周期:代码审查响应缓慢、测试运行时间过长、部署工具难以使用等。加速小迭代总是安全的(只要确实存在问题)。例如,如果代码审查耗时过长,通常会发现审查者响应不够快。解决方案是专注于缩短审查者响应时间,而不是整体代码审查时间。
代码审查本质上是质量流程,需要高质量的结果。有时需要在开发者和审查者之间进行五轮来回修改才能获得良好结果。关键是让每一轮都快速完成。
这适用于软件开发的各个部分。如果发现编码耗时过长,值得关注构建时间、本地测试运行时间、获取决策信息的速度等。
每个周期都是某种形式的"观察、决策、行动"循环。改善开发者体验的最佳方法之一是让开发者更容易观察事物,在需要时直接将所需信息呈现在面前。
专注度详解
软件开发是需要长时间深度专注的活动。开发者正在构建关于工作内容的复杂心理结构,并用该结构做出决策和编写代码。这种专注状态通常被称为"心流状态"。
当开发者被打断过于彻底或频繁时,这种复杂的心理结构会消失,返回任务时需要重新构建。我们称这种中断为"上下文切换",此时开发者的主要关注点不再是编写代码。强制上下文切换可能需要10-15分钟才能完全重建之前的心理结构。
中断导致上下文切换的时间因人而异,从30秒到2分钟不等,也取决于中断的性质。需要大量脑力工作的复杂故障消息很可能会打破专注度,无论阅读需要多长时间。
如果中断引起不良情绪反应,干扰性会更强。令人沮丧的消息或工具行为会破坏专注度,即使中断只有5秒。
改善心流的方法包括:确保工具不会强迫开发者在编码、测试或调试时从事复杂非相关任务;保证开发者有多个不受打扰的专注时间;避免工具、系统或流程做出令开发者沮丧的行为。
另一个关键点是:开发者是否清楚了解工作目的并有明确方向?如果任务不明确,自身的困惑会经常打破专注度。
专注度领域也需要将清晰信息直接呈现在开发者面前,用于观察、决策和行动。不要让他们中断工作去寻找所需数据。
认知负载详解
减少所需知识
虽然开发者应该尽可能了解工作内容,但通过移除完成任务必须知道的内容,可以显著提高开发者的生产力和体验。从编写1和0到汇编语言,再到Java或Python等高级语言,生产力大幅提升。
大多数拥有开发者基础设施的团队在这方面表现不佳。他们制作的工具要求开发者深入理解才能工作。如果开发者只需要与少量工具交互,这还可以接受,但实际上开发者需要与数百个工具交互。
减少选择
开发者只需要做出他们需要做的选择。有些开发者认为必须允许他们对系统做出所有选择:编程语言、包管理器、构建工具、代码缩进方式、监控系统、部署系统等。
极端情况下,想象每次开始处理系统更改时,都必须全面研究选择什么编程语言、从10个功能相同的库中选择哪个、使用什么构建工具、与每个人争论制表符与空格、决定使用什么代码审查工具等。这样永远无法完成任何工作。
在公司内部,我甚至认为不应该允许开发者做出他们不需要做的决定。这听起来极端,但正确实施时会带来优秀的开发者体验。
问题在于,开发者通常认为需要对实际上不需要的事情做决定,但几个月或几年后才会看到后果(或者无法理解决策如何影响更大的业务)。例如,不应该允许开发者选择世界上任何编程语言来完成任务——这会迫使他们开发一堆围绕该语言的新库或基础设施,而不是专注于实际需要完成的任务。
然而,必须谨慎应用这一原则——需要允许开发者做出他们需要做的决定。每个人使用编辑器和周围工具的方式差异很大,因为人们的思维方式差异很大。不能对工作流程的某些部分施加太多硬性约束。
另一个需要注意的问题是:如果基础设施限制了开发者可以做的决策,就需要在集中维护该基础设施方面做得非常好。也就是说,需要一个核心团队持续做出这些决策并对结果负责。
做好的关键是深入理解开发者的需求和他们所工作系统的需求。需要深入理解他们解决的问题类型,以便知道哪些决策需要或不需要做出。并且需要能够适时适当调整(改变策略),而不是完全放开导致混乱。
事实上,大多数开发者并不希望对系统做出每个决定,然后被迫进行一堆自定义底层工作才能开始任务。
开发者体验的挑战
开发者体验的大多数困难方面是人的方面,而不是技术方面。主要困难包括:
理解问题:当前最重要的是改进开发者体验的工作?如何充分理解这些问题以便构建正确的解决方案?
管理变更:如何推出新变更?如何让人们采用新系统或行为?如何处理对变更感到不安的人?
提供杠杆作用:为开发者构建的工具和系统使用/采用所需的工作量不应超过它们节省的工作量。
说不:不能一次性解决世界上所有问题。必须能够确定优先级。有时团队会要求某些实际上会损害公司开发者体验的工具或功能。
将痛苦施加给造成痛苦的人:如果一个团队做的事情给另一个团队带来困难,而制造困难的团队自己从未感受到任何困难,那么痛苦将无限增长。
理解问题
最重要的是:问题来自用户,解决方案来自系统开发者。绝不能颠倒这种关系。
有时用户包括对你应该构建什么有强烈意见的高级主管或技术负责人。仍然需要坚持立场,从他们那里获取问题信息,同时基于从所有不同用户收集的良好数据设计解决方案。
也很容易认为"我是开发者,所以我知道开发者想要什么",完全跳过与用户交谈。这行不通,因为开发者的工作方式各不相同,需求也与你大不相同。
反馈和投诉
构建某些东西后,寻找关于系统的数据和反馈非常重要。虽然我们热爱自己构建的东西,但应该始终寻找开发者遇到的问题以便解决——包括我们刚做的东西的问题!
需要理解的是,在开发者体验领域,人们很少发送正面反馈。当开发工具"正常工作"时,开发者大多不会想到它们。他们专注于正在做的任务,而不是你的工具,这应该是正常状态。
此外,不是每个开发者都是优秀的反馈提供者。通常他们只是与工具有过非常沮丧的经历,会提供一些不太顾及你感受的情绪化反馈。
处理严厉反馈的关键是:让用户知道他们被听到了。如果工具确实存在缺陷,同意用户的观点!不需要侮辱自己或自己的工作,只需对自己拥有的东西状态保持诚实。
管理变更
变更厌恶
改善开发者体验时必须处理的主要因素之一是我们所称的"变更厌恶"。对系统所做的任何变更在推出时都会收到某些人的负面反馈。这不是因为变更本身有问题,而是因为用户习惯了旧的工作方式,不喜欢发生改变。
识别人们的反馈是单纯的变更厌恶还是关于有价值事物的真实反馈有几种方法:变更厌恶通常持续3到10天;变更厌恶反馈通常是情绪化的。
管理变更时要避免的是制造太多变更厌恶导致反抗。反抗基本上表现为很多人愤怒地去找你的管理层并停止你的工作。如有疑问,向更少的人推出更小的变更,以较慢的速度扩展。
增量推出
除了增量开发和设计,还需要知道如何增量推出变更,以便不是所有用户同时经历所有变更。这基本上有三个组成部分:管理发布以尽可能减少干扰;选择良好的初始用户群进行推出;了解何时扩展群组以及扩展速度。
最小干扰意味着:不要破坏用户的系统;不要求用户手动工作来采用变更;必要时提供清晰文档;确保系统提供非常清晰的错误消息。
选择初始群组主要关于谁将提供有用的反馈,以及需要多少人才能获得该反馈。扩展速度取决于几个因素:获得多少反馈;每个新团队需要多少手动支持或手动入职工作;变更的破坏性或引起的变更厌恶程度。
推动采用
假设增量推出做得很好,但就是无法让人们使用新东西。如何解决?
首先,必须确保真正理解了问题,并且这是开发者知道并真正希望解决的问题。然后必须确保解决方案真正处理了该问题,不会给开发者带来很多新问题。
在整个公司实现100%采用的唯一解决方案是:让工具使用步骤为零。
这意味着将功能直接集成到工作流程中,而不是给开发者新的手动操作。如果使用需要一步,可能达到80%采用率;如果需要两步,能达到30%就很幸运;如果需要阅读长文档并遵循复杂说明,就知道为什么没人使用你的东西。
不应该从一开始就让工具使用步骤为零。这在工具生命周期开始时是不值得的。但一旦做对了,“零步骤"就是推动100%采用的 mantra。
提供杠杆作用
开发工具或改进开发者体验的整个意义在于,为团队/公司节省的努力应该超过创建和维护工具所投入的努力。
在软件中,减少维护工作比减少创建工作更重要。因此不仅要考虑工具的即时影响(和构建的即时成本),还要考虑随时间推移它将节省多少努力(以及维护工具需要多少成本)。
不同公司对此计算有不同的"时间范围”。在Google,我们通常将时间范围设为两年,因此任何开发者生产力的投资必须在两年内"回本"。
人类时间
这个领域最常见的错误之一是通过某些优化节省机器时间(CPU使用、内存使用和磁盘空间的随时间成本),而忘记节省了多少人类时间。在大多数情况下,一小时人类时间的成本比所涉及的所有机器时间一小时的成本贵数百倍。
有许多合理理由优化机器时间,但改善开发者体验很少是其中之一。考虑开发者生产力改进的成本和价值时,首先考虑将节省多少人类时间。
服务开发者
如果从事开发者生产力工作, mantra之一应该是"我们为开发者服务,而不是开发者为我們服务"。太容易发布某些让开发者做的工作比节省的工作还多的工具,或者只是比他们应该做的工作更多。
如果从事开发者体验工作,让工具以这种方式行为需要更多工作。发布强迫开发者完成所有工作的东西要容易得多。但这违背了我们正在做的事情的全部目的——提供杠杆作用。
说不
从事开发者体验的团队往往与客户关系密切。如上所述,客户可能包括公司中拥有很大权限的高级领导。此外,客户是开发者,往往对自己想要什么有强烈意见,有众多复杂需求,并且面临为自己项目交付结果的时间压力。
平衡这一点的是,人类在开发者体验上可以做的工作量是有限的。因此,当请求来到团队时,必须能够提供三种答案之一:“是,我们现在就做”、“我们稍后做"或"抱歉,我们不会做这个”。可以简称为"是"、“现在不行"和"不”。
是
在许多情况下,应该能够说"是,我们现在就做"。在开发者体验领域,有很多合理、有价值的计划外工作出现。通常这是对工具或系统的小型、无争议修复,可以在一两个小时内处理。也有一些出现的事情需要一两天但提供即时和明显的杠杆作用,不需要等待进入规划过程。
为了能够对少量即时工作说"是",必须在规划过程中允许计划外工作。如果做季度计划分配团队100%的时间,会破坏与公司其他部门的关系。
现在不行
对于需要超过几小时或几天的工作,需要需求研究,可能有争议,难以推出等,必须有某种流程接收客户请求并为其确定优先级以便深入工作。开发者体验团队及其经理不能对每个请求都说"是"。如果这样做,发生的是永远无法交付任何具有巨大价值和高品质的东西。
关于优先级排序有很多要知道的,但应基于对问题的理解、解决方案将提供的杠杆作用量以及创建和维护解决方案所需的总工作量。
这里最棘手的部分之一是,开发者体验团队上的工程师通常是接收这些请求的"前线",他们必须有某种方式礼貌地将请求推迟到"现在不行"类别(通常称为"待办事项")。
不
对客户说"我们永远不会做这个"是最难的回应的。感觉像是在不友善。然而,必须能够对确实会损害公司开发者体验多于帮助的请求说"抱歉,不"。
例如,可能正在替换旧系统,努力需要一年,从理解问题中知道新系统将为开发者体验带来巨大改进。一个团队来说,“我们需要你在旧系统上投入整整一个季度的工作来改善我们的体验。“大多数时候,这根本就是"不”。
然而,只有在客户有其他方式完成实际需要做的事情时才能说"不”。如果把工具做成公司做事的唯一方式,并且客户必须有某个功能才能工作,那么无论如何都必须实现该功能。这就是为什么我主张任何开发者体验系统都应有多个层次:低层级的一套工具、库和基础设施,允许人们做任何需要做的事情,但使用复杂;高层级平台使用简单,但要求客户以非常特定的方式工作才能利用它。
通常高层级平台将覆盖80%的用例,20%的用例需要"打破玻璃"使用平台下的现有工具。
这个系统的伟大之处在于,高层级平台可以(并且应该)非常积极地对会损害使用平台体验的功能请求说"不"。当然,高层级平台的所有者必须对问题有很好的理解,以便知道真正需要构建什么。但高层级平台的整个要点是为公司80%的开发者用例提供令人难以置信的体验,这意味着整个体验需要精心策划,需要能够对许多会降低使用体验的功能请求说不。
友善
关于友善的说明:对交谈的人说"不"(甚至"现在不行")可能感觉刻薄。但通过对你不应该同意的事情说"是"来伤害所有你没有交谈的人的开发者体验,更加不友善。
将痛苦施加给造成痛苦的人
如果一个团队可以做某事给另一个团队带来困难(“痛苦”),而制造困难的团队自己从未因此经历任何困难,那么创造的痛苦量只会不断增长。
这不是关于团队有恶意。没有人想伤害同事。这是关于自然激励以及人类如何回应这些。
假设有一个团队拥有一个被其他十个团队使用的库。库团队有自己的目标、截止日期和优先级。他们专注于完成这些必须做的事情。如果允许他们每天向客户发送破坏性变更而自己没有任何后果,那么他们会每天发送破坏性变更,因为这是实现目标最有效的方式。
团队可能经历的不同形式的"后果"效果各异。最重要的是他们经历这些后果的速度以及经历的困难程度与他们强加给客户的困难量相比。
令人惊讶的是,在这种情况下,像不良绩效评估或人们对团队生气这样的人类后果效果最差。它们在痛苦造成后发生得太晚,并且不会改变导致团队以这种方式行事的真实世界激励。它们只是让团队感到受压迫。
责任
解决问题的正确方法是改变谁必须做工作,这会改变激励和团队的基本"物理定律"。我发现最一致有效的规则是:如果一个团队想要做出改变,他们负责代表公司执行该改变。
如果你是库团队并且想要进行破坏性变更,必须重构所有客户的代码库以采用新的破坏性变更。如果你是网络安全团队并且希望在公司所有代码库上实施新控制,必须自己在所有这些代码库中安装并确保其工作。
这需要大量工具使其成为可能。必须能够使用集中式工具在公司范围内进行大规模变更。必须有某种集中方式知道推出某些变更时是否在破坏人们。必须能够理解依赖你的库或系统的每个消费者,以便知道需要在何处进行变更。这里有很多工作要做。但它显著改变了业务文化、基础设施团队(包括开发者体验团队)的有效性以及公司开展工作的整体能力。
限制
关于这种范式有很多要知道的。例如,基础设施提供者与其客户之间必须有关于什么变更将自动化以及当变更破坏时谁负责修复的合同。
确实希望推动核心团队尽可能自己重构——他们倾向于避免查看客户的代码库,因为面对不熟悉的代码库很困难。因此必须推动团队实际集中工作。
然而,核心团队实际能做的事情是有限的。有合理的时候客户必须手动工作来采用变更。需要确保核心团队首先尽可能自动化。如果需要客户手动工作,需要确保提供的说明尽可能清晰——理想情况下,自己至少尝试一次以确保实际上可以完成、有意义等。还必须控制在任何给定时间公司需要多少手动工作。
尽管如此,有时自动化不值得。如果变更需要两个团队做三小时工作来采用,而自动化需要自己团队20小时工作,不要做。
最后的话
这些是我能想到的关于如何创造优秀开发者体验的所有基本原则。关于以上每一点还有更多要知道的,足够写一本书或连续谈十小时(至少)。但以上涵盖了每个领域需要知道的所有核心概念。
当然,也希望确保开发者工作的结果是高质量的,因为软件的最终目的是尽可能帮助人们。并且希望确保最终系统简单(意味着易于阅读、理解和正确修改),以便随时间推移轻松维护。然而,这些点主要是在实施上述系统时要牢记的。它们主要通过每个软件开发者理解并在日常工作中应用软件设计的基本原则来实现,而不是通过工具。工具对于使这些事情发生非常重要,工具开发者不能忘记它们,但不像你只是向世界发布新工具、库、基础设施或平台,这些品质就神奇地出现在每个代码库中。它们是公司每个软件工程师持续的责任。