骗我一次……我还没有看到哪家公司没有在生产环境中运行旨在验证概念或快速原型的代码。创始人在一个周末里拼凑起来的东西不知何故成为了生产代码中的关键部分,但没有人知道如何摆脱它,因为进行更改需要重写大量代码库。
代码库是流动的,而且会泄漏。随着时间的推移,代码将被共享和重新利用。新代码将建立在旧代码之上。这是一张相互依赖的蜘蛛网。
这让工程师们感到紧张;我们被告知某些东西只是一个原型,但实际情况是,我们在可预见的未来只能在生产中维护这个原型。
因此,当我们为项目提出新工具时,工程团队的其他成员非 葡萄牙电报号码数据库 常合理地希望确保我们不会给他们扔定时炸弹。毕竟:无论构建什么,最终投入生产的可能性都很大,这意味着我们必须维护它。
虽然工程部门在引入新工具时需要谨慎,这一点完全可以理解,但公司必须能够快速构建和交付产品,以便从真实客户那里获得反馈,这一点也很重要。如果我们构建了错误的东西,我们希望尽早发现,并且以尽可能低的成本发现。
这两种需求都是真实的——但似乎彼此矛盾。
为了在快速交付和避免不必要的技术债务之间取得平衡,我们需要找到一种方法来实现两件事:
团队需要能够安全地为早期项目引入新工具和想法,以便他们能够快速构建、交付和迭代。
团队需要能够快速安全地更改(或完全删除)实验系统的组件,而无需重写整个代码库。
为了实现这一点,我们采用了一种称为“优化删除”的策略。
优化删除
如果我们针对删除进行优化,我们就会创建防护栏,防止原型泄漏到代码库的其他部分。本质上,我们试图以一种防止其泄漏到代码库的其他部分的方式编写代码。这对于降低构建原型的风险至关重要,因为正如Chris Biscardi 所说,“如果你不能删除代码,你就只能使用它了。”
为了优化删除,我们的代码中需要满足以下几点:
代码与其他生产代码完全隔离。一个很好的例子是为实验创建一个单独的存储库,该存储库可以单独提供服务,并通过子域或代理添加到其余代码库中。这保证了实验不会泄漏到其他代码中,因为它实际上是两个独立的应用程序。
代码仅通过明确定义的接口与其他代码库交互。例如,数据层只能通过 API 访问 — 代码库的其他部分不应该能够进入数据层以其他方式获取数据。这保证了只要 API 继续以相同的方式工作,就可以完全重写数据层。
代码库之间的链接应该有限且易于查找。如果前端调用 API,请不要在整个代码库的文件中放置一堆fetch调用;如果 API 移动或更改,以后很难重构。相反,将数据访问整合到一个集中的位置 — — 比如React 的 Context API、无服务器函数或其他一些实用程序助手 — — 这样就可以清楚地知道前端在哪里与其他服务联系。
如果我们能够满足这些条件,我们就能大大降低制造新产品的风险,因为如果我们错了,我们只需要更换工具本身,而不是整个产品。
在真实代码中是什么样的
因为抽象地谈论代码可能会令人沮丧,所以我们来看看来自真实项目的示例,这些示例展示了这在实践中是如何运作的。(为了使示例尽可能简单,不相关的代码已被删除。)
在我的团队目前正在开展的一个项目中,我们正在使用 Next.js 构建一个提取数据的前端。以下是我们的一个页面组件的样子: