Disons que vous avez une interface IFoo
:
public interface IFoo {
void Bar(string s);
int Quux(object o);
}
Dans la version 2 de votre API, vous devez ajouter une méthode Glarg
à cette interface. Comment faire sans casser vos utilisateurs d'API existants et maintenir la compatibilité descendante? Ceci est principalement destiné à .NET, mais peut également s'appliquer à d'autres frameworks et langages.
versioning
interfaces
thecoop
la source
la source
Réponses:
Pourquoi?
Les interfaces définies pour une utilisation avec une API ont deux rôles entièrement différents:
Maintenant, pour une version donnée d'une API, la même interface peut agir comme les deux. Pourtant, dans les versions futures, cela peut être découplé.
Vous voulez "retourner plus", c'est-à-dire l'abstraction d'un objet "plus riche" de votre API. Ici, vous avez deux choix:
Définissez une nouvelle interface, si possible dérivée de la précédente. Si une telle dérivation est impossible, créez des méthodes distinctes pour rechercher des instances de la nouvelle interface ou utilisez la composition:
la source
DirectX a ajouté des numéros de version à ses interfaces. Dans votre cas, la solution serait quelque chose comme
L'API ferait toujours référence à IFoo et à IFoo2 uniquement dans les méthodes, etc., où la fonctionnalité IFoo2 est requise.
L'implémentation de l'API doit vérifier dans les méthodes existantes (= version 1) si un objet de paramètre IFoo implémente réellement IFoo2, si la sémantique des méthodes est différente pour IFoo2.
la source
L'ajout d'une nouvelle (ou de plusieurs) méthode (s) à votre API doit se faire de manière à ne pas avoir d'effets secondaires sur l'API existante. Plus important encore, une personne qui continue d'utiliser l'ancienne API comme si la nouvelle API n'existait pas ne devrait pas être affectée par celle-ci. L'utilisation de l'ancienne API ne devrait pas avoir effets secondaires inattendus sur la nouvelle API.
Si l'une des méthodes existantes de l'API est remplacée par les nouvelles, ne les supprimez pas immédiatement. Marquez-les comme obsolètes et expliquez ce qui doit être utilisé à la place. Cela avertit les utilisateurs de votre code que les futures versions pourraient ne plus le prendre en charge au lieu de casser leur code sans avertissement.
Si les nouvelles et anciennes API sont incompatibles et ne peuvent pas vivre ensemble sans effets secondaires indésirables, séparez-les et documentez que si la nouvelle API doit être adoptée, l'ancienne API doit être complètement retirée. C'est moins souhaitable car il y aura toujours quelqu'un qui essaiera d'utiliser les deux et sera frustré quand cela ne fonctionnera pas.
Étant donné que vous avez posé des questions sur .NET en particulier, vous pouvez lire cet article sur la dépréciation dans .NET, qui renvoie à
ObsoleteAttribute
(utilisé dans l'exemple suivant):la source
Les changements d'interface publique impliquent une rupture. La stratégie courante consiste à ne les faire que sur les versions majeures et après une période de gel (donc cela ne se produit pas sur un coup de tête). Vous pouvez vous en tirer sans casser vos clients si vous ajoutez des ajouts dans une nouvelle interface (et votre implémentation peut fournir les deux sur la même classe). Ce n'est pas idéal, et si vous continuez à le faire, vous aurez un gâchis.
Avec d'autres types de modifications (suppression de méthodes, modification de signatures), vous êtes bloqué.
la source
Une interface est un contrat, elle ne doit donc pas avoir de version. Que se passe-t-il si un joueur de football obtient un nouveau contrat? L'ancien est-il toujours valide? Non. Si l'on change d'interface, le contrat change et le contrat précédent (interface) n'est plus valide.
Bien que vous puissiez utiliser la stratégie IFoo2, cela finira par devenir compliqué lorsque vous aurez:
Beurk.
Une API est différente. Je donne la bibliothèque de code à utiliser. Le mois prochain, je vous donne une bibliothèque mise à jour. Comme l'a dit une autre affiche, ne cassez pas ce que j'utilise déjà, ajoutez simplement de nouvelles fonctionnalités / méthodes.
Si vous voulez versionner quelque chose, utilisez une classe abtract au lieu d'une interface.
la source