你是如何陷入瓶颈的?
我们遇到的最常见的扩展瓶颈是技术债务——初创公司经常说技术债务是他们增长的主要障碍。术语“技术债务”往往被用作一个笼统的术语,通常表示技术平台和堆栈需要改进。他们发现功能开发速度变慢、质量问题或工程人员感到沮丧。初创公司团队将其归因于他们在增长阶段缺乏技术投资而产生的技术债务。需要进行分析以确定技术债务的类型和规模。可能是代码质量很差,使用了较旧的语言或框架,或者产品的部署和运行没有完全自动化。解决方案策略可能是对团队流程进行微调,或者启动一项重建应用程序部分的计划。
重要的是要说明,谨慎的技术债务是健康的,也是可取的,尤其是在初创公司旅程的初始阶段。初创公司应该用质量或健壮性等技术方面来换取产品交付速度。这将帮助初创公司实现其第一个目标——可行的商业模式、经过验证的产品以及喜欢产品的客户。但是,当公司寻求扩展时,我们必须解决所采取的捷径,否则它会很快影响业务。
让我们检查一下我们遇到的几个例子。
公司 A——一家初创公司已经构建了一个 MVP,该 MVP 已经显示出足够的证据(用户流量、用户情绪、收入)来吸引投资者,并获得了下一轮融资。与大多数 MVP 一样,它是为了生成用户反馈而构建的,而不是为了构建高质量的技术架构。在获得融资后,他们没有重建该试点,而是继续在其基础上进行构建,通过专注于功能来保持吸引力。这可能不是一个直接的问题,因为初创公司有一个小型高级团队,他们了解尖锐的边缘,并且可以提供临时解决方案来维持公司的运营。
问题开始出现时,团队继续专注于功能开发,而债务却没有得到偿还。随着时间的推移,低质量的 MVP 成为核心组件,没有明确的改进或替换它们的途径。学习、工作和支持代码存在摩擦。有效地扩展团队或功能集变得越来越困难。工程领导人也非常担心原始工程师的流失,以及他们所掌握的知识的流失。
最终,缺乏技术投资达到了顶峰。团队变得瘫痪,表现为速度降低和团队沮丧。初创公司必须进行重大重建,这意味着功能开发必须放缓,让竞争对手赶上来。
公司 B——该公司由前工程师创立,他们希望做所有事情都“正确”。它是为了扩展而构建的。他们使用了最新的库和编程语言。它具有细粒度的架构,允许应用程序的每个部分使用不同的技术实现,每种技术都经过优化以完美扩展。因此,当公司发展到那个规模时,它将能够轻松地处理超速增长。
这个例子的问题是,它花费了很长时间来创建,功能开发速度很慢,许多工程师花费时间在平台上工作,而不是在产品上工作。它也很难进行实验——细粒度的架构意味着不适合现有服务架构的想法很难实现。该公司没有意识到高度可扩展架构的价值,因为它无法找到产品市场匹配来达到那个规模的客户群。
这两个例子都是极端的例子,基于 Thoughtworks 初创公司团队与各种客户合作的经验。公司 A 陷入技术债务瓶颈,使公司瘫痪。公司 B 过度设计了一个解决方案,减缓了开发速度,并削弱了它在学习更多知识时快速转向的能力。
这两个例子都体现了无法找到技术投资与产品交付之间的正确平衡。理想情况下,我们希望利用谨慎的技术债务来推动快速的功能开发和实验。当发现这些想法有价值时,我们应该偿还技术债务。虽然这很容易说出来,但要付诸实践却很困难。
为了探索如何创造正确的平衡,我们将研究不同类型的技术债务
典型的债务类型
技术债务是一个含糊不清的术语,通常被认为纯粹与代码相关。在本讨论中,我们将使用技术债务来表示任何技术捷径,即我们用对技术平台的长期投资来换取短期功能开发。
- 代码质量
- 脆弱、难以测试、难以理解或文档不足的代码将使所有开发和维护任务变慢,并降低编写代码的“乐趣”,从而使工程师失去动力。另一个例子是领域模型和相关数据模型不适合当前的业务模型,导致出现变通方法。
- 测试
- 缺乏单元测试、集成测试或 E2E 测试,或者分布不当(参见测试金字塔)。开发人员无法快速确信他们的代码不会破坏现有功能和依赖关系。这会导致开发人员批量更改,并降低部署频率。较大的增量更难测试,通常会导致更多错误。
- 耦合
- 模块之间(通常发生在单体应用中),团队可能会互相阻塞,从而降低部署频率,并增加更改的交付时间。一种解决方案是将服务提取到微服务中,这会带来自身的复杂性——在单体应用中设置明确的边界可能会有更直接的方法。
- 未使用的或价值较低的功能
- 通常不被认为是技术债务,但技术债务的症状之一是难以使用的代码。更多功能会创建更多条件,更多开发人员必须设计绕过的边缘情况。这会降低交付速度。初创公司正在进行实验。我们应该始终确保回头重新评估实验(功能)是否有效,如果无效,就删除它。从情感上讲,团队很难做出判断,但当你拥有量化功能价值的客观数据时,它会变得容易得多。
- 过时的库或框架
- 团队将无法利用新的改进,并且容易受到安全问题的攻击。这会导致技能问题,减缓新员工的入职速度,并让被迫使用旧版本的现有开发人员感到沮丧。此外,这些遗留框架往往会限制进一步的升级和创新。
- 工具
- 需要大量维护的次优第三方产品或工具。市场不断变化,可能出现了更高效的工具。开发人员自然也希望使用最有效的工具。购买与构建之间的平衡很复杂,需要在考虑剩余债务的情况下重新评估。
- 可靠性和性能工程问题
- 这会影响客户体验和扩展能力。我们必须小心,因为我们已经看到在为假设的未来情况进行扩展时,过早优化浪费了精力。拥有一个经过验证的用户价值的产品,比一个未经验证但可以扩展的产品要好。我们将在“扩展瓶颈:没有考虑到可靠性和可观察性而构建”一文中详细介绍这一点。
- 手动流程
- 产品交付工作流程的一部分没有自动化。这可能是开发人员工作流程中的步骤,也可能是与管理生产系统相关的步骤。警告:当你在自动化一个使用频率不足以值得投资的事情上花费大量时间时,也会出现这种情况。
- 自动化部署
- 早期阶段的初创公司可以使用简单的设置,但这应该尽快解决——小的增量部署推动了实验性软件交付。使用四个关键指标作为你的指导。你应该能够随时部署,通常每天至少部署一次。
- 知识共享
- 缺乏有用的信息是一种技术债务。它使新员工和依赖团队难以快速上手。作为标准做法,开发团队应该编写简洁的技术文档、API 规范和架构决策记录。它还应该通过开发者门户或搜索引擎进行查找。一种反模式是没有审核和弃用流程来确保质量。
这真的是技术债务还是功能性?
初创公司经常告诉我们他们被技术债务淹没了,但在仔细检查后,他们实际上指的是技术平台的功能有限,这需要通过规划、需求收集和专门的资源来进行适当的处理。
例如,Thoughtworks 的创业团队经常与客户合作,自动化客户入职流程。他们可能拥有一个单租户解决方案,自动化程度很低。这在一开始还不错——开发人员可以手动设置帐户并跟踪安装之间的差异。但是,随着添加更多客户,这对开发人员来说变得过于耗时。因此,创业公司可能会雇用专门的操作人员来设置客户帐户。随着用户群和功能的增长,管理不同的安装变得越来越困难——客户入职时间增加,质量问题也随之增加。此时,自动化部署和配置或迁移到多租户设置将直接影响 KPI——这就是功能。
其他形式的技术债务更难发现,也更难指出其直接影响,例如难以处理的代码或重复的简短手动流程。识别它们的最佳方法是征求每天都遇到这些问题的团队的反馈。团队的持续改进流程可以处理它,不需要专门的计划来修复它。