您不需要停止交付功能来修复技术债务

2020-06-15 08:09:48

如果你曾经在一家高增长的软件工程公司工作过,你可能会听到关于技术债务的对话是这样的:

人物A:“如果我们只做X…,我们的放映速度会快得多。”人物B:“这是有道理的--那你为什么不这么做呢?”人物A:“嗯,有这么多的专题工作,我们就是没有时间。”

“我们真的需要这样做。我们应该停止所有的功能工作,直到我们解决这个问题。“。

对于这些情况,我一直持观望态度--当我站在接收方(上面的B人)时,解决问题几乎总是合乎逻辑的,但并不总是得到它所需的“认可”!

那么这里有什么问题呢?既然这么明显和合乎逻辑的做法是正确的,为什么很难找到时间,或者说服人们允许我们开始偿还科技债务呢?

这个古老的流行词“技术债务”(或简称“技术债务”)通常被用作一个包罗万象的术语,用来描述我们希望我们构建的或正在工作的软件有更好的东西。软件通常不处于期望的状态,因为在其开发的早期阶段进行了捷径或权衡。有些人在这里把它比作货币债务--但这是我们在谈论的软件,所以我就不说了。

在几乎所有的情况下,被贴上技术债务标签的东西都是对软件的非功能性更改。比如重构代码以消除全局依赖注入、修复(或添加)测试、改进文档,甚至让测试套件在CI中运行,或者最终自动化您的部署。

因为这些不是功能更改,也不会改变您软件的行为,所以您的客户很可能看不到这些改进。因此,如果您的客户不会看到您想要在此技术债务上花费的数小时/数天/数周的工作有任何变化,那么您将提供什么价值?你为什么要把时间投入到这件事上呢?

向客户传达技术问题的业务价值或价值是分配时间解决这些问题的关键。一些人在这里有一个常见的障碍是固定的心态(“我们很想,但我们只是不允许修复这个问题”)。请记住,在任何组织中,人们都会做出决策--决策是关于权衡的,决策可能会受到影响、推翻和改变。更重要的是,组织在进化--昨天做出的决定可能不是明天做出的!

推荐:我最喜欢的一篇关于决策主题的文章是本·法蒂的“每次都做出正确的决定”。

如果传达价值是关键,那么你应该如何传达偿还科技债务的价值?这个问题没有万能的答案--但我在本文中的目标是概述一个框架,以帮助产品/工程团队对问题进行分类、分配时间,并清楚地了解为什么每段时间都会根据它将提供的价值进行适当的调整。

我希望此框架将帮助您与人员/“利益相关者”保持一致,使您能够更有效地传达价值,并最终解决您一直想要解决的技术债务问题!

“解决问题最简单的方法就是否认它的存在。”--艾萨克·阿西莫夫。

在您尝试使用我将介绍的框架之前,对于您遇到的每个技术债务问题,先问问自己:这里真的有问题吗?它可能不值得付清,除非:

它提高了输出的速度或质量,例如,修改构建配置将使我们的发布时间减少一半,从而使我们的部署频率提高一倍。

延迟的成本非常紧迫,例如,如果我们现在不解决这个问题,它将直接影响X个客户/Y%利润/Z%收入。

如果它不符合上面两个类别中的任何一个,希望您可以忽略它,如果不符合,我们将讨论这个问题。

在组织的每个计划级别,无论您的计划节奏/持续时间是多少,您都应该能够将所有工作分类或分配到以下四个存储桶中的一个:

功能改进-提供您的客户可以看到或使用的功能更改。通常,产品经理/所有者会根据客户的研究和输入,积极参与此存储桶的优先排序。例如:闪亮的新功能。

计划工作-在您的团队之外/在您的组织内部进行的更大规模工作的一部分,通常由将您的团队标记为该工作计划依赖关系的计划经理进行协调。示例:平台范围的本地化/国际化努力。

交付绩效-以可量化的方式提高交付速度或产出质量。示例:自动化您的部署过程,以便您可以更快/更频繁地将代码从干线/主分支投入生产。

计划外工作-当延迟的成本很紧急时,您可以优先处理此工作,并立即/与您正在进行的其他所有事情一起解决问题,而不是将它们推迟到您的积压工作/未来的循环中。包括错误、客户支持请求、生产事故等。例如:影响20%客户的生产中断。

通过将您的工作归入这四个类别/桶中的一个类别,沟通工作的价值应该会变得更容易,而腾出时间处理您的技术债务问题应该会更容易。

请注意,以上分类应适用于您的整个积压工作-而不仅仅是技术债务问题-因为分配时间处理技术债务问题意味着不会将时间分配给其他工作。还要注意的是,技术债务可能会被归类为交付绩效或计划外工作。

在上面,我说“在每个级别”是有原因的;能够在整个组织层次结构中使用一致的词汇进行交流将帮助您影响投资于解决技术债务问题的决策。

许多科技公司采用的模式是,每个团队/团队/“两个披萨团队”通常负责管理受组织层级影响的积压订单。如果您的组织就是这样运作的,让决策者的层次结构理解此框架将有助于您在术语、逻辑和理由上保持一致。

与任何模型或框架一样,也存在不适合其结构的边缘情况。乍一看,您可能无法忽略(“不做”)问题,并且可能无法将其归类为交付性能或计划外工作。请不要在第一眼就放弃-督促自己找到一种方法,通过稍微深入地研究问题的细节(或与同行/SME合作),找到将问题归结为其中一个问题的理由。如果再试一次还是不合适,没关系。

“代码很难测试”--这是那些棘手场景之一的一个例子,在这种场景中,可能很难忽略它,或者很难证明您将如何对其进行分类是不清楚的。在这种情况下,我建议采取以下方法:

对您的代码进行小的、渐进的改进--不要试图要求花时间在一个“大爆炸”项目上来解决它。

每个Pull Request(PR)都应该改进您的代码,改进您的测试,并提高测试覆盖率(或者至少不是倒退!)。CI系统中的质量关卡甚至可以强制执行一些规则,比如不让测试覆盖率下降超过X%,并要求最低覆盖率为Y%。

如果这看起来不是一种容易处理的方法,您可能需要找到一种方法来重新定义问题,以便将其分解成更小的块-也许可以忽略这些块中的一些,将其分类,还有一些可以按照上面提到的即付即用(Pay-as-You-go,PAYG)方法进行处理。

一旦您将工作分类到四个存储桶中的一个,下一步就是“分割馅饼”或为每个存储桶分配估计时间。

这是我成功使用的一种方法:从提名数字开始,与利益相关者一起评估,然后在适当的时候进行调整。

如果没有利益相关者的参与,您就无法成功地分配百分比-主要是因为这些百分比通常是可以协商的,但也涉及许多决策,因此需要权衡。

第一个要确定的数字是计划外工作;这不应该是你决定的,而是应该以你拥有的数据为基础,这些数据让你可以推断出你对前瞻性时间段的期望。例如,如果您计划每季度一次,您可以查看上个季度花费的时间,以及(特别是对于受季节性影响的企业)上一年同一季度花费的时间。如果利益相关者试图通过谈判降低这个数字,请向他们介绍一下您是如何确定这个数字的,并帮助他们了解您的实际情况。

第二个要建立的数字是交付性能。为什么?基于上面的框架,我们想要从一个雄心勃勃但有充分基础的数字开始。每个人都应该被激励去减少计划外的工作,而交付性能就是可以做到的地方(稍后会有更多的介绍)。如果您的计划外工作“太大”(每个企业都有不同的容忍度),请考虑增加您的交付绩效分配,直到这个数字变得更容易接受。如果您向下调整此数字,请确保与相关利益相关者沟通该权衡。推荐:关于拥抱风险的Google SRE图书主题在确定企业内的风险容忍度方面有一些很好的想法-这在试图确定应该为交付绩效分配多少时间时可能会很有帮助。虽然对于一些团队或组织来说,使用错误预算可能是一个非常有效的选择,但同意一个管理错误预算和实施/测量SLO的系统本身通常是一个挑战。我在本文中介绍的分配框架有一些重叠,但在某些方面,可能会提供另一种分配时间的方法来解决一些质量/可靠性问题,否则这些问题将使用错误预算来解决。

第三个要建立的数字是计划工作。这些问题通常来自你业务的其他团队或部门,其中一些比另一些更具讨价还价的余地。试着根据您认为在下一段时间内必须完成的事情来调整此桶的大小。

最后一个数字是功能改进;至此,您已经完成了规模调整,因为您正在处理剩余的百分比。您可能听说过术语价值流-团队的活动应该与交付客户的请求保持一致。这个桶通常是直接解决客户想要“看到”的东西的主要桶。如果此存储桶的大小对于您认为需要交付的价值来说太小,或者太小,无法满足您的客户在新功能交付方面的期望-我们将在短期内承担为此存储桶争取更多时间的杠杆。

一旦您完成了每个存储桶的初始大小,您将需要考虑如何根据与利益相关者的一些讨论对其进行调整/调整。在这个框架内有两个“杠杆”需要考虑:

理想情况下,任何被归类为交付绩效的工作都将减少下一个计划期或工作节奏中的计划外工作量。

推荐:请查看Nicole Forsgren博士、Jez Humble和Gene Kim所著的Accelerate一书-这是一本关于衡量和思考如何改进软件交付性能的非常棒的指南,其中包含对软件交付性能的出色定义,以及交付期、部署频率、平均恢复时间(MTTR)和更改失败百分比等4个关键指标。

交付性能工作应减少MTTR(平均恢复时间)。即使计划外工作桶中的错误或问题数量没有立即减少,解决它们所需的时间应该会减少-因此减少了分配给计划外工作桶所需的总时间。

交付绩效工作应提高产出质量,从而降低变更失败率。理想情况下,我们希望看到导致计划外工作的问题数量随着时间的推移而减少,而提高输出质量(在准确性、可靠性、性能、安全性等方面)就应该做到这一点。

根据环境的不同,有时将减少MTTR放在降低更改失败率之前会更有意义-例如,如果您的恢复能力需要几天时间,并且故障数量很少但不变,那么在您选择减少他们看到的故障数量之前,通过选择减少MTTR并更快地解决这些未来问题,您可能会为客户带来更多价值,因为停机或错误的持续时间可能比数量的影响更大。我们的目标是使用这两个变量,但根据客户的价值来构建决策过程。

我认为计划工作和功能改进之间的平衡是一种分配杠杆。通过与项目干系人合作,有时您能够推迟或重新分配您的团队被要求做的工作-只要做出该决定的理由清楚明了,并且这些干系人同意进行权衡。

计划通常是由多个项目、团队和依赖项组成的庞大而复杂的工作实体。重要的是要保持平衡,这样你就能预见到拦网队员的到来,避免成为其他球队的拦网队员。项目经理或驱动程序很容易要求您的团队提前完成相关工作-但从您的角度来看,将工作推迟一周/月/季度可能意味着您如何分配时间,以及最终您的团队可以为客户提供的价值。

考虑到计划外工作在某种程度上是固定的,减少计划外工作的杠杆主要是交付性能-当试图找到更多的时间来分配给功能改进时,我建议与计划干系人合作,允许您减少分配给计划工作桶的时间。你应该能够通过解释你拥有的存储桶分配,以及为什么你认为拒绝他们的要求是目前对你的客户最好的事情来实现这一点。

由于这种杠杆的结构方式,他们正在进行的权衡实际上是将价值传递给特定于您的产品的客户,而不是致力于更大的计划(这本身可能会也可能不会为客户提供更明显的价值)。

一旦您的团队完成了将待办事项分类到4个存储桶中的一个,并为每个存储桶分配了一定百分比的工作时间,您如何才能实际执行呢?

每个团队将是不同的-团队规模、经验水平、任期/主题专业知识等因素都会影响谁在什么方面工作的决定。

但是,在将分配给团队的时间分配给个人(或结对编程环境的情况下,为结对编程)分配时间时,您应该考虑一些事情:

团队中的每个人都应该拥有产出的质量。这包括准确性、可靠性、性能、安全性等。

让中小企业继续专注于一个领域只会隐藏/推迟风险和成本-例如,如果他们离开/生病/不可用,就会缺乏业务连续性,他们离开时的知识转移成本,如果他们没有正确/完全地离开,就会缺乏知识转移,等等。

有时,您可能会权衡延迟风险,以换取快速完成任务--这是可以的,但您应该确保您的团队/利益相关者意识到并一致做出该决定。

如果你确实考虑采用这个框架,我真的鼓励你在开始之前想一想如何衡量你的成功。

例如,如果您使用的是像Jira这样的问题跟踪器,则可以考虑添加一个字段或标签,使您可以将问题分配给四个存储桶中的一个。

在您的下一个周期/冲刺之前,您应该能够快速报告您想要的故障是什么-在该周期结束之后,您应该能够分析您是如何做到的。这里经常被问到的一个问题是,是跟踪问题的总数,还是跟踪估计的总和(例如时间或工作量)-这实际上取决于您的团队是如何工作的,以及您认为什么会提供更好的工作回报。不要追求完美的系统--只要选择你认为会提供足够实用工具的东西,就可以让你清楚地了解你是如何追踪的。

标记和跟踪你在每个桶上的进展情况对于计划外的工作特别有用-因此,你可以更有规律地观察它,而不是每个周期一次,以了解它对你的周期的影响是比预期的要大还是小。

首先,组织/团队/积压都会发生变化,您的计划和时间分配方法也应该有所变化。使用持续改进的心态,使度量/数据驱动的决策成为您工作方式的一部分,并运行诸如计划/冲刺回顾之类的例行公事,将帮助您将时间分配向更好的方向发展。

其次,本着持续改进的精神:如果你觉得这篇文章对你有帮助或有阻碍,请随时联系-我很想听听什么对你有用,什么对你不起作用。谢谢你的阅读!