6

セマンティック バージョニングの重要性を友人に説明しようとしたとき、次のようなジレンマに直面しました。

次の関数を公開するlibfooversionの library があるとします。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)

しかし、もう少し考えてみると、Python では名前でパラメーターを指定できるため、これはAPI の中断である可能性が非常に高いです。誰かが私の関数を次のように呼び出すとしたら:

foo(y=4, x=3)

これは version1.2.4では機能しなくなり、セマンティック バージョニング コントラクトが破られます。

一方で、このような変更は非常に小さいため、バージョンを に上げるのは気が引け2.0.0ます。

要約すると、これは API の中断を構成しますか? この場合、次のバージョン番号は何にする必要がありますか?

4

2 に答える 2

5

簡単な回答: はい、それは API の中断を構成するため、メジャー バージョン番号が増加する可能性があると思います。ただし、以下の注意事項に注意してください。


パブリック/外部 API を公開する場合、インターフェースの変更について慎重に検討するという追加の「注意義務」を負うことになります。これには、たとえば、下位互換性を損なうことを避けるために潜在的な改善を延期することが含まれます*。API を維持している場合は、インターフェイスを使用するコード**に正当に影響を与える変更を慎重に検討する必要があります。

セマンティック バージョニングの仕様は明確です。

後方互換性のない変更がパブリック API に導入された場合、メジャー バージョン X (Xyz | X > 0) をインクリメントする必要があります。

質問で特定したように、パラメーターの名前を変更すると、キーワードで引数を渡すコードに後方互換性がなくなります。

ただし、この変更がメジャー バージョンをインクリメントする必要があると言うのではなく、代わりに、変更を行うべきではない、または少なくとも単独で行うべきではないと結論付けます。既存の有効なコードを壊す可能性があるというメジャーなインクリメントを正当化するには、あまりにもマイナーな変更です。伴う。次のいずれかの場合を除きます。

  1. これは、重要な変更の大きなバンドルの一部です。また
  2. あなたの例に示されていない変更には本当に正当な理由があります(いくつかのショーストップバグ、またはそれに依存する他の機能);

私は変更を完全に延期します。よりゆっくりと動き、セマンティック バージョニング契約を引き続き満たしていることを確認し、そのような変更はやむを得ない理由がある場合にのみ行うことをお勧めします。


Python 3.8からは、正確にこの種の問題が正当化の一部としてPEPで呼び出されて、位置のみのパラメーターを指定できます (私の強調):

API の呼び出し元がキーワード引数の使用を開始した場合、ライブラリの作成者はパラメーターの名前を変更できません。これは重大な変更になるためです。

この場合、元の定義が次の場合:

def foo(x, y, /):

その場合、パラメーターの名前を変更しても重大な変更にはなりません


* Python タグにあるように、整数除算を検討してください。これは、BDFL によって間違いとして認められているにもかかわらず、今日まで 2.x リリースに残っています。

**私が「合法的に」と言うのは、公式に文書化されているように使用していないコードを除外するためです。したがって、この変更を予測していて、位置引数のみを使用する必要があることが明確に指定されていた場合、この変更は問題ありませんが、それは奇妙な選択です。

于 2015-01-27T22:27:45.650 に答える
-1

この種の変更は、リリース スケールのさまざまな領域に分類される可能性があります。

主な変更点 (1.x から 2.x へのインクリメント)

これは API 契約に違反し、大きな変更とみなされます。ただし、これに対する大きな注意点は、これが唯一の変更であるかどうかです。もしそうなら、私はこれをメジャーなバージョン変更にはしません。一方、これが API 契約を破る多くの変更の 1 つである場合、メジャー バージョンの増加は正当化されると思います。

軽微な変更 (1.2 から 1.3 への増分)

Pythonドキュメントからの借用:

マイナー バージョン番号は、大規模な変更を減らすためにインクリメントされます。

私にとって、これは小さな変更です。あなたが述べたように、ユーザーがパラメーターに名前を付けていない場合、ユーザーは変更が発生したことにさえ気づきません。

マイクロ変更 (1.2.3 から 1.2.4 への増分)

これは、変更のバグ修正レベルです。foo(x, y)バグであるために に変更する場合foo(a, b)、この修正により、マイクロ ポイントのインクリメントが正当化されます。


そのような変更についての私の意見は、マイナーチェンジにすることです。これは確かに「大規模な」変更ではありませんが、エンド ユーザーにコードの変更を強制する可能性があります。それ以外の場合はまったく同じように動作し、まったく同じデータを返し、まったく同じデータをパラメーターとして受け取りますが、それらを異なる名前に適用するだけの関数呼び出しでのみパラメーター名を変更しているため、メジャー変更として分類しません。関数内。

于 2015-01-27T22:21:32.187 に答える