Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does semantic versioning imply about parameter name changes?

Trying to explain the importance of semantic versioning to a friend, I faced the following dilemma.

Let's say we have library libfoo, version 1.2.3 that exposes the following function:

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

Now assume that this function and its documentation change to:

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

My first impression was to say that the next version would be 1.2.4, as the public interface did not change. For example, someone calling the function like that would not notice the change at all:

foo(3, 4)

But thinking a bit further, this may very well be an API break, given that Python allows one to specify parameters by their names. If someone were to call my function like:

foo(y=4, x=3)

this would not work any more with the version 1.2.4, breaking the semantic versioning contract.

On the other hand, such a change seems so small that I would feel bad about increasing the version to 2.0.0.

To summarize, does this constitute an API break? What should the next version number be in this case?

like image 316
ereOn Avatar asked Jan 27 '15 22:01

ereOn


1 Answers

Short answer: yes, I think that would constitute an API break and thus potentially increment the major version number. Note the caveats below, though.


When you expose a public/external API, you take on an extra "duty of care" to think carefully about changes to the interface. This includes, for example, putting off a potential improvement to avoid breaking backwards compatibility*. Any change that would affect any code legitimately** using your interface should be considered very carefully when you're maintaining an API.

The specification for semantic versioning is unambiguous:

Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API.

Changing the names of parameters, as you have identified in the question, introduces a backwards incompatibility for code passing arguments by keyword.

However, rather than say that this change should increment the major version, I would conclude instead that the change should not be made, or at least not in isolation - it's too minor a change to justify the major increment that potentially breaking existing valid code would entail. Except for the case that either:

  1. It's part of some larger bundle of important changes; or
  2. There is a really good reason for the change that isn't shown in your example (some show-stopping bug, or other feature that relies on it);

I would put off the change altogether. It's better to move more slowly and ensure that you continue to meet your semantic versioning contract, making such changes only with compelling grounds to do so.


From Python 3.8 you can specify positional-only parameters, with exactly this kind of issue being called out in the PEP as part of the justification (emphasis mine):

If a caller of an API starts using a keyword argument, the library author cannot rename the parameter because it would be a breaking change.

In this case, if the original definition had been:

def foo(x, y, /):

then renaming the parameters would not be a breaking change.


* As we're in the Python tag, consider integer division, that, despite being acknowledged as a mistake by the BDFL, remains in 2.x releases to this day.

** I say "legitimately" to exclude code not using it as officially documented, for example by accessing private-by-convention attributes - they should expect to get inconvenienced on occasion! Therefore if you'd predicted this change and it was clearly specified that only positional arguments should be used, this change would be OK, but that would be an odd choice.

like image 89
jonrsharpe Avatar answered Oct 11 '22 01:10

jonrsharpe