Załóżmy, że masz interfejs IFoo
:
public interface IFoo {
void Bar(string s);
int Quux(object o);
}
W wersji 2 interfejsu API musisz dodać metodę Glarg
do tego interfejsu. Jak to zrobić, nie psując istniejących użytkowników interfejsu API i zachowując zgodność wsteczną? Jest to skierowane głównie do platformy .NET, ale może również dotyczyć innych platform i języków.
versioning
interfaces
Thecoop
źródło
źródło
Odpowiedzi:
Czemu?
Interfejsy zdefiniowane do użytku z interfejsem API mają dwie zupełnie różne role:
Teraz dla danej wersji interfejsu API ten sam interfejs może działać jako jedno i drugie. Jednak w przyszłych wersjach można to oddzielić.
Chcesz „zwrócić więcej”, tj. Wyodrębnić „bogatszy” obiekt z twojego API. Tutaj masz dwie możliwości:
Zdefiniuj nowy interfejs, jeśli to możliwe, oparty na poprzednim. Jeśli takie wyprowadzenie jest niemożliwe, utwórz osobne metody w celu zapytania o instancje nowego interfejsu lub użyj kompozycji:
źródło
DirectX dodał numery wersji do swoich interfejsów. W twoim przypadku rozwiązaniem byłoby coś takiego
Interfejs API nadal odnosi się do IFoo i IFoo2 tylko w metodach itp., W których wymagana jest funkcjonalność IFoo2.
Implementacja API powinna sprawdzić w istniejących (= wersja 1) metodach, czy obiekt parametru IFoo faktycznie implementuje IFoo2, jeśli semantyka metody jest inna dla IFoo2.
źródło
Dodanie nowej metody (lub metod) do interfejsu API powinno odbywać się w taki sposób, aby nie miało żadnych skutków ubocznych dla istniejącego interfejsu API. Co najważniejsze, ktoś, kto nadal korzysta ze starego interfejsu API tak, jakby nowy interfejs API nie istnieje, nie powinien mieć na niego wpływu. Korzystanie ze starego interfejsu API również nie powinno mieć nieoczekiwanych skutków ubocznych dla nowego interfejsu API.
Jeśli którakolwiek z istniejących metod interfejsu API zostanie zastąpiona nowymi, nie usuwaj ich od razu. Oznacz je jako przestarzałe i podaj wyjaśnienie, czego należy użyć w zamian. Dzięki temu użytkownicy Twojego kodu ostrzegają, że przyszłe wersje mogą go nie obsługiwać zamiast łamać kod bez ostrzeżenia.
Jeśli nowe i stare interfejsy API są niezgodne i nie mogą żyć razem bez niepożądanych efektów ubocznych, rozdziel je i udokumentuj, że jeśli nowy interfejs API ma zostać przyjęty, stary interfejs API musi zostać całkowicie wycofany. Jest to mniej pożądane, ponieważ zawsze znajdzie się ktoś, kto spróbuje użyć obu i denerwuje się, gdy to nie działa.
Ponieważ zapytałeś konkretnie o .NET, możesz przeczytać ten artykuł o wycofaniu w .NET, który prowadzi do
ObsoleteAttribute
(użytego w poniższym przykładzie):źródło
Zmiany w interfejsie publicznym wiążą się z awarią. Powszechną strategią jest robienie tego tylko w głównych wersjach i po okresie zamrożenia (więc nie dzieje się to na zasadzie kaprysu). Możesz uciec bez rozbijania klientów, jeśli dodajesz dodatki do nowego interfejsu (a twoja implementacja może zapewnić oba w tej samej klasie). To nie jest idealne, a jeśli będziesz to robić dalej, będziesz mieć bałagan.
Jednak w przypadku innych rodzajów modyfikacji (usuwanie metod, zmiana podpisów) utkniesz.
źródło
Interfejs jest umową, dlatego nie powinien mieć wersji. Co się stanie, jeśli piłkarz otrzyma nową umowę? Czy stary nadal jest ważny? Nie. Jeśli ktoś zmieni interfejs, umowa ulegnie zmianie, a poprzednia umowa (interfejs) przestanie obowiązywać.
Chociaż możesz użyć strategii IFoo2, w końcu stanie się to bałagan, gdy:
Fuj
Interfejs API jest inny. Daję bibliotekę kodu do użycia. W następnym miesiącu dam wam zaktualizowaną bibliotekę. Jak powiedział inny plakat, nie psuj tego, czego już używam, po prostu dodaj nową funkcjonalność / metody.
Jeśli chcesz coś zaktualizować, użyj klasy abtract zamiast interfejsu.
źródło