维护供第三方使用的API时,不可避免地需要进行更改。复杂程度取决于发生的更改的类型。这些是主要的方案:
- 现有API中增加了新功能
- API不推荐使用的旧功能
- API中的现有功能以某种方式更改
现有API的新功能
这是最容易支持的方案。向API添加新方法不应要求对现有客户端进行任何更改。对于需要新功能的客户端,这是安全的,因为它没有任何现有客户端的更新。
API不推荐使用的旧功能
在这种情况下,您必须与API的现有使用者进行沟通,以确保长期不支持该功能。在放弃对旧功能的支持(或直到所有客户端都升级到新功能)之前,必须同时保留旧的和新的API功能。如果是提供的库,则大多数语言都可以将旧方法标记为过时/不推荐使用。如果它是某种第三方服务,通常最好对旧/新功能使用不同的端点。
API中的现有功能以某种方式更改
这种情况将取决于更改的类型。如果不再需要使用输入参数,则只需更新服务/库即可忽略现在多余的数据。在库中,应该让重载的方法在内部调用需要较少参数的新方法。在托管服务中,端点将忽略额外的数据,并且它可以为两种类型的客户端提供服务并运行相同的逻辑。
如果现有功能需要添加新的必需元素,那么您的服务/库必须具有两个端点/方法。在客户端更新之前,您需要同时支持两个版本。
其他想法
Rather, the API is likely to extend the private objects we are using for our base API, but then we run into the same problem because added properties would also be available in the public API when they are not supposed to be.
不要通过您的库/服务公开内部私有对象。创建自己的类型并映射内部实现。这将允许您进行内部更改,并最大程度地减少外部客户端需要执行的更新量。
The problem is more that it seems like many or most changes require breaking the public API if the objects aren't more separated, but I don't see a good way to do that without duplicating code.
API是服务还是库,都必须在与客户端的集成点处保持稳定。您花费更多的时间来确定输入和输出应该是什么并将其作为单独的实体保存,这将为您节省很多麻烦。使API合同成为其自己的单独实体,并映射到提供实际工作的类。内部实现更改时节省的时间应能抵消定义额外接口所花费的额外时间。
不要将此步骤视为“重复代码”。虽然相似,但它们是值得创建的独立实体。尽管外部API更改几乎总是需要对内部实现进行相应的更改,但是内部实现更改不应总是更改外部API。
例
假设您要提供付款处理解决方案。您正在使用PaymentProviderA进行信用卡交易。稍后,您可以通过PaymentProviderB的付款处理器获得更高的汇率。如果您的API暴露了您类型的信用卡/账单地址字段,而不是PaymentProviderA的表示形式,则该API更改为0,因为该接口保持不变(希望无论如何,如果PaymentProviderB需要的数据不是PaymentProviderA所需要的,则您需要选择两者都支持,或者通过PaymentProviderA保持差价)。
I don't see a good way to do that without duplicating code
-您的新API始终可以调用旧API中的方法,反之亦然。