Keystone 接口

2020 年 4 月 29 日

软件开发团队发现,如果他们尽可能频繁地集成他们的工作,生活会轻松很多。他们还发现,频繁发布到生产环境中很有价值。但是团队不希望向用户公开尚未开发完成的功能。处理这种矛盾的一种有用技术是构建所有后端代码,进行集成,但不构建用户界面。该功能可以集成和测试,但 UI 会一直保留到最后,就像拱顶石一样,它被添加进来以完成该功能,并将其展示给用户。

这种技术的一个简单示例可能是为客户提供加急订单的选项。此类订单需要根据客户居住地以及该地区运营的快递公司进行定价。所涉及货物的性质会影响仓库中使用的拣货方式。某些客户可能有资格获得加急订单,这也可能取决于交货地点、一年中的时间以及订购的货物类型。

总而言之,这是相当多的业务逻辑,特别是因为它将涉及与各种仓储、目录和客户服务系统的复杂集成。这样做可能需要几周时间,而其他功能则需要每隔几天发布一次。但就用户而言,加急订单只是订单上的一个复选框。

为了使用复选框作为拱顶石来构建此功能,团队在多个生产版本的过程中对底层业务逻辑和与内部系统的接口进行开发工作。用户不知道所有这些潜在的代码。只有在最后一步,才需要使拱顶石复选框可见,这可以在相对较短的时间内完成。这样,所有潜在的代码都可以集成并成为投入生产的系统的一部分,从而减少了长期存在的特性分支带来的问题。

潜在代码确实需要进行与激活时相同程度的测试。如果系统的架构设置为大多数测试不是通过用户界面完成的,则可以做到这一点。单元测试测试金字塔 的其他较低层应该很容易以这种方式运行。即使是 广义栈测试 也可以运行,前提是有一种机制可以使它们成为 皮下测试。在某些情况下,UI 本身会有大量的行为,但如果设计允许可见的 UI 是一个 谦卑对象,那么这也可以进行测试。

并非所有应用程序都以可以通过皮下方式进行广泛测试的方式构建 - 但即使没有使用拱顶石的能力,为此付出的努力也是值得的。即使使用最好的工具来自动化该过程,通过 UI 运行的测试也总是更难设置。将更多测试转移到皮下测试和更低级别的测试,尤其是单元测试,可以显着加快 部署流水线 的速度,并实现 持续交付

当然,大多数 UI 不仅仅是一个复选框,尽管通常它们的工作量并不比拱顶石多多少。在 Web 应用程序中,复杂的功能通常是一个独立的网页,可以完整地构建和测试,而拱顶石只是一个链接。桌面可能有几个屏幕,其中拱顶石是使它们可见的菜单项。

也就是说,在某些情况下,UI 不能打包成一个简单的拱顶石。在这种情况下,就该使用 功能标志 了。然而,即使在这种情况下,考虑拱顶石也是有用的,因为它可以确保功能切换只应用于 UI。这避免了在后端代码中散布大量的切换点,降低了应用切换的复杂性,允许使用 简单的切换机制,并在需要时更容易移除。

最后开发 UI 存在一个普遍的风险,即后端代码的设计方式可能在构建 UI 后无法正常工作,或者 UI 直到后期才得到应有的关注,导致缺乏迭代和糟糕的用户体验。出于这些原因,拱顶石方法在鼓励通过薄垂直切片构建产品的整体方法中效果最佳,这些切片可以快速发布小而完整的功能。

我在这里使用了用户界面的例子,但当然,同样的方法也可以用于任何其他接口,比如 API。通过最后构建消费者的接口,并保持其简单性,我们可以以小的块构建和集成大型功能。

暗启动 是一种变体,其中新功能在构建完成后立即被调用,但不会向用户显示任何结果。这样做是为了衡量对后端系统的影响,这对于某些更改非常有用。一旦一切顺利,我们就可以添加拱顶石。

致谢

我第一次接触到这种技术的拱顶石比喻是在 Kent Beck 的第二版《解析极限编程》中。Pete Hodgson、Brandon Duff 和 Stefan Smith 提醒我,我已经忘记了这一点。

Dave Farley、Paul Hammant 和 Pete Hodgson 对这篇文章的草稿发表了评论。