Brechen von API-Änderungen: Wie kann ich Bibliotheksbenutzern den Übergang erleichtern?

8

In der Vergangenheit habe ich die Standardmethode zum Hinzufügen von @DeprecatedAnmerkungen zu API-Methoden verwendet, die in einer späteren Version entfernt werden.

Jetzt bereite ich eine Hauptversion für eine Bibliothek vor, bei der viele API-Teile entfernt und umbenannt werden.

Um den Übergang für vorhandene Benutzer zu vereinfachen, kann es möglicherweise hilfreich sein, wenn die neue Bibliotheksversion neben der alten Version verwendet werden kann.

Vorteile

  • Das dynamische Umschalten zwischen Versionen kann implementiert werden
  • Anwendungen können auf die vorherige Version zurückgreifen, wenn in der neuen Version Fehler gefunden werden (nützlich in der Beta-Phase).

Dazu könnte ich einfach die neue Bibliotheksversion in ein neues Paket von com.mycompany.librarynach verschiebencom.mycompany.library.v2

Ist dies eine gängige Praxis oder gibt es andere Empfehlungen für eine solche gleichzeitige Verwendung von Java-Bibliotheken?


Hintergrund:

Die Bibliothek ist ein einfacher Dokumentkonverter. Neben einem Konvertierungsmodus (in, out) verfügt er über viele Konfigurationseigenschaften und einige Ereignishandler. Wenn ich die Verwendung nebeneinander anbiete, können Verbraucher sie dynamisch instanziieren und konfigurieren:

if (useVersion2) {
  com.mycompany.library.v2.Converter c = new com.mycompany.library.v2.Converter();
  // configure and run
  c.setOption(...);
  c.convert(in, out); 
} else {
  com.mycompany.library.Converter c = new com.mycompany.library.Converter();
  // configure and run
  c.setOption(...);
  c.convert(in, out);
}

(Frage von /programming/37192945/ verschoben )

mjn
quelle
1
Was wirst du in Version 5 tun? 5 'if / else if', ein 'switch'? ... Denken Sie langfristig und denken Sie, als wären Sie nicht da, um den Code loszuwerden. Möchten Sie Hilarius sehen, wenn / sonst überall?
Laiv
@Laiv Codebeispiel zeigt, wie vorhandene v1-Benutzer - für einen kurzen Zeitraum - beide Versionen in dieselbe Anwendung aufnehmen können, bis sie mit ihrer Migration zu v2 fertig sind (siehe
Fragentitel
for a short time period. Wir wissen beide, was es temporär in der Softwareentwicklung bedeutet. Tun wir nicht? ;-)
Laiv
1
Ich kann nicht für andere sprechen, aber es fällt mir schwer, einen Umstand zu finden, wenn ich mehrere Versionen derselben Java-API gleichzeitig verwenden möchte.
Eric Stein
2
Sie können die @DeprecatedAnmerkung zu Ihrem Code hinzufügen . Wenn Benutzer in der Version aktualisieren, sehen sie, dass der Code veraltet ist und sie sollten sich ändern. Entfernen Sie danach den gesamten Code.
Zymus

Antworten:

3

Dieser Ansatz ist ziemlich verbreitet. Es ermöglicht einen reibungslosen Übergang zu einer neuen API und eine sichere Weiterentwicklung zu neuen Implementierungen.

Natürlich hat der Wenn / Dann-Ansatz, wie er von Laiv in seiner Antwort hervorgehoben wurde, einige Nachteile. Es ist langweilig. Es ist leicht, Dinge zu vergessen oder zu verwechseln. Idealerweise könnte die Verwendung von Verpackungen, Fabriken oder Adaptern einige schönere Alternativen bieten. Aber oft ist es umso besser, je einfacher es ist.

Martin Fowler und Pete Hogdson haben kürzlich in einem ausgezeichneten Artikel über dieses Thema theoretisiert, in dem sie beschreiben, was sie als "Feature-Toggle-Muster" bezeichnen. Es könnte Sie interessieren, da verschiedene Implementierungsstrategien - wie die Verwendung eines "Toggle-Routers" - und Nutzungsszenarien ausführlich beschrieben werden.

Hinweis: Ich persönlich habe keine Feature-Toggles gefunden. Ich komme aus der C ++ - Welt und bevorzuge die einfache und robuste Alternative, bei der Namespace-Aliase und Klauseln verwendet werden, um zur Kompilierungszeit die zu verwendende Version auszuwählen. Es ist jedoch sprachspezifisch und ermöglicht außerdem keine dynamische Konfiguration, wenn die Funktion umgeschaltet wird. Wie gesagt, manchmal ist es umso besser, je einfacher es ist ;-)

Christophe
quelle
2

Die Nachrüstbibliothek ist dafür ein gutes Beispiel. Es ist noch nicht lange her, dass sie eine stabile Version 2 eingeführt haben, die wirklich gut ist, auch wenn sie einige Brüche mit sich gebracht hat.

Einige der bemerkenswerten Dinge, die sie taten, waren:

  1. Die neue API hat viel Wert und behebt viele der Mängel der älteren Version. Dies bedeutet, dass Ihre neue API sehr gut sein muss. Nicht nur in Bezug auf die Funktionsweise, sondern auch, damit es schön und einfach aussieht, falls dies jemals ein Problem war.

  2. Die Beta-Version für die neue API wurde veröffentlicht, damit die Benutzer frühzeitig von den Änderungen erfahren und sogar ein gutes Feedback geben können.

  3. Der Übergang war auch nicht so schmerzhaft. Sie führten die Versionsnummer in den Paketnamen selbst ein, was bedeutet, dass einige Änderungen nur eine Änderung der Importanweisungen erforderlich machten. Ja, einige Klassen wurden entfernt und einige eingeführt, aber es fühlte sich nicht zu drastisch an. Dies hängt auch davon ab, wie der Benutzer seine Codebasis organisiert hat, was teilweise außerhalb des Bereichs des API-Entwicklers liegt.

Darüber hinaus werden Migrationshandbücher bevorzugt. Retrofit, eine beliebte Bibliothek, viele Artikel dazu sind online verfügbar.

razzledazzle
quelle
0

Ich denke nicht, dass das Teilen von Code mit if/elseein guter Ansatz ist.

Denken Sie langfristig. Was machst du mit weiteren Versionen? )

Wie kann Benutzercode im Laufe der Zeit sein?

Bei kleineren Versionen oder Testberichten wird erwartet, dass die Kompatibilität erhalten bleibt. @Deprecated enthält einen Kommentar, in dem der Entwickler aufgefordert wird, diesen Code nicht zu verwenden. Es wird auch vorgeschlagen, welche Komponente / Methode / Klasse stattdessen verwendet werden soll. Schließlich teilen viele von ihnen mit, dass veralteter Code in weiteren Versionen nicht unterstützt wird. Oder werden möglicherweise nicht unterstützt (sie wissen es noch nicht).

Bei neuen Versionen (größere Neugestaltung von Änderungen) ist es jedoch nicht sinnvoll, veralteten Code beizubehalten, da dies die Wartung erschwert. Legacy-Code kann auch von den vorgenommenen Änderungen betroffen sein. Direkt oder nicht.

Es macht auch die Verwendung unklar. Auch wenn veralteter Code mit Anmerkungen versehen ist.

Wenn es sich bei Ihrem Fall um eine wirklich große Änderung oder Überarbeitung handelt, würde ich die Benutzer eher ermutigen / zwingen, auf die neue Funktion umzusteigen.

Wenn die neue Bibliothek nicht stabil ist, kann der Benutzer die Abhängigkeit herabstufen und daran festhalten, bis neue lib-Fehler behoben sind.

Als Entwickler erwarte ich Änderungen von einer Version zur anderen. Wenn ich mich für die neue entscheide, akzeptiere ich, um mit solchen Änderungen umzugehen.

Im schlimmsten Fall kann ich zum vorherigen zurückkehren.

Ich würde mich nicht auf Ausdrücke wie "ist zeitlich" legen. Weil wir alle wissen, wie es endet ...

Eher zu verhindern, dass der Benutzer in solche Bestätigungen gerät, die zu schwer lesbarem und schwer zu pflegendem Code führen

Laiv
quelle