试图向朋友解释语义版本控制的重要性,我面临以下两难困境。
我们假设我们有库libfoo
,版本1.2.3
,它公开了以下功能:
def foo(x, y):
"""
Compute the sum of the operands.
:param x: The first argument.
:param y: The second argument.
:returns: The sum of `x` and `y`.
"""
return x + y
现在假设此函数及其文档更改为:
def foo(a, b):
"""
Compute the sum of the operands.
:param a: The first argument.
:param b: The second argument.
:returns: The sum of `a` and `b`.
"""
return a + b
我的第一印象是说下一个版本是1.2.4
,因为公共界面没有改变。例如,有人调用这样的函数根本不会注意到这一变化:
foo(3, 4)
但是想一想,这可能是一个 API中断,因为Python允许用户通过名字来指定参数。如果有人打电话给我的功能:
foo(y=4, x=3)
这不再适用于版本1.2.4
,打破了语义版本控制合同。
另一方面,这种变化看起来很小,我觉得将版本增加到2.0.0
感觉不好。
总结一下,这是否构成API中断?在这种情况下,下一个版本号应该是什么?
答案 0 :(得分:4)
简短回答:是的,我认为会构成API中断,因此可能会增加主版本号。不过请注意下面的注意事项。
当您公开公共/外部API时,您需要额外的"谨慎责任" 仔细考虑接口的更改。这包括,例如,推迟潜在的改进,以避免破坏向后兼容*。 在您维护API时,应该非常谨慎地考虑使用您的界面合法影响任何代码的任何更改。
specification for semantic versioning毫不含糊:
如果向公共API引入任何向后不兼容的更改,则必须增加主要版本X(X.y.z | X> 0)。
如问题中所述,更改参数名称会导致按关键字传递参数的代码向后不兼容。
然而,不是说这个改变应该增加主要版本,我会得出结论,不应该做出改变,或者至少不是孤立的 - 它太小了一个改变来证明可能破坏现有有效代码所需的主要增量。除了以下情况之外:
我会完全推迟改变。移动速度越慢越好,并确保您继续满足语义版本控制合同,只有在有充分理由的情况下才能进行此类更改。
* 正如我们在Python标记中所做的那样,考虑整数除法,尽管being acknowledged as a mistake by the BDFL仍然存在于今天的2.x版本中。
** 我说'#34;合法地"排除不使用官方文档的代码,例如通过访问私有属性 - 他们应该偶尔会遇到不便!因此,如果你预测到这种变化并且明确指出只应该使用位置参数,那么这种改变就可以了,但这将是一个奇怪的选择。
答案 1 :(得分:0)
此类更改可能会在发布规模上落入许多不同的领域。
这会破坏您的API合同,并有资格作为重大变更。然而,对此的巨大警告是,这是否是唯一的改变。如果是的话,我不会让这个版本发生重大变化。另一方面,如果这是许多也会破坏您的API合同的变更之一,我相信主要版本增量是合理的。
借用Python documentation:
次要版本号[是]增加,以减少惊天动地的变化。
对我来说,这是一个小小的改变。正如您所述,如果用户没有命名他们的参数,他们甚至不会注意到发生了更改。
这是您的错误修复级别的更改。如果您要将foo(x, y)
更改为foo(a, b)
,因为它是一个错误,那么此修复将证明微点增量是正确的。
我对此类更改的看法是将其改为次要。它肯定不是一个“惊天动地”的变化,但它确实可能会迫使最终用户更改代码。我不会将其归类为主要更改,因为它仅在函数调用上更改参数名称,否则行为完全相同,返回完全相同的数据,并获取与参数完全相同的数据,但只是将它们应用于不同的名称在功能中。