Sürüm oluşturma API'ları


9

Bir API tabanı tarafından desteklenen büyük bir projeniz olduğunu varsayalım. Proje ayrıca son (ish) kullanıcıların kullanabileceği genel bir API gönderir.

Bazen projenizi destekleyen API tabanında değişiklikler yapmanız gerekebilir. Örneğin, API değişikliğine, yeni bir yönteme ihtiyaç duyan veya nesnelerden birinin veya bu nesnelerden birinin biçiminin API'ye veya API'den geçirilmesini gerektiren bir özellik eklemeniz gerekir.

Bu nesneleri genel API'nizde de kullandığınızı varsayarsak, genel nesneler de bunu yaptığınız zaman değişecektir; bu, istemcileriniz ayrıştırma kodlarının çalışması için aynı kalan API nesnelerine güvenebileceğinden istenmeyen bir durumdur. (öksürük C ++ WSDL istemcileri ...)

Dolayısıyla potansiyel çözümlerden biri API'yi sürümlendirmektir. Ancak API'yi "sürüm" dediğimizde, bunun, API nesnelerini sürümlendirmenin yanı sıra, her değiştirilen yöntem imzası için yinelenen yöntem çağrıları sağlaması gerektiği anlamına gelmesi gerekir. Böylece benim api her sürümü için düz bir eski clr nesne olurdu, ki bu yine istenmeyen görünüyor. Ve bunu yapsam bile, her nesneyi sıfırdan inşa etmeyeceğim çünkü bu büyük miktarlarda çoğaltılan kodla sonuçlanacaktır. Bunun yerine, API'nin temel API'miz için kullandığımız özel nesneleri genişletmesi muhtemeldir, ancak daha sonra aynı sorunla karşılaşırız çünkü ek özellikler olması gerekmediğinde genel API'da da kullanılabilir.

Peki bu duruma genellikle uygulanan akıl sağlığı nedir? Git for Windows gibi birçok kamu hizmetinin sürümlü bir API barındırdığını biliyorum, ancak çeşitli sürümlendirilmiş yöntemleri ve giriş / çıkış nesnelerini kapsayan büyük miktarda yinelenen kod olmadan bunu destekleyen bir mimari hayal etmekte sorun yaşıyorum.

Anlamsal sürüm oluşturma gibi süreçlerin , genel API kesintilerinin ne zaman gerçekleşmesi gerektiği konusunda biraz akıl sağlamaya çalıştığının farkındayım . Sorun, nesnelerin daha fazla ayrılmazsa, birçok veya en çok değişiklik genel API'yi kırmayı gerektiren gibi görünüyor, ancak kodu çoğaltmadan bunu yapmanın iyi bir yolunu görmüyorum.


1
I don't see a good way to do that without duplicating code- Yeni API'nız her zaman eski API'nizdeki yöntemleri çağırabilir veya tam tersi.
Robert Harvey

2
AutoMapper to rescue, ne yazık ki evet - her sözleşmenin farklı sürümlerine ihtiyacınız var, sözleşmeniz tarafından referans verilen tüm nesnelerin bu sözleşmenin bir parçası olduğunu unutmayın. Sonuç olarak, gerçek uygulamanızın kendi tek model sürümüne sahip olması ve tek sürümü çeşitli sözleşme sürümlerine dönüştürmeniz gerekir. AutoMapper burada size yardımcı olabilir ve dahili modelleri sözleşme modellerinden daha akıllı hale getirebilir. AutoMapper yokluğunda, dahili modeller ve sözleşme modelleri arasında basit çeviriler oluşturmak için genişletme yöntemleri kullandım.
Jimmy Hoffa

Bunun için belirli bir platform / bağlam var mı? (ör. DLL'ler, bir REST API'sı vb.)
GrandmasterB

.NET, MVC ve Webforms ui, dll sınıfları ile. Hem dinlenme hem de sabun API'miz var.
Dava

Yanıtlar:


6

Üçüncü taraflar tarafından kullanılan bir API'yı tutarken değişiklik yapmanız kaçınılmazdır. Karmaşıklık seviyesi, meydana gelen değişikliğin türüne bağlı olacaktır. Bunlar ortaya çıkan ana senaryolar:

  1. Mevcut API'ya Yeni İşlevler Eklendi
  2. Eski İşlevler API'dan Kullanımdan Kaldırıldı
  3. Bir Şekilde API Değiştirmede Mevcut İşlevler

Mevcut API'ya Yeni İşlevler Ekleniyor

Bu, desteklenmesi en kolay senaryodur. Bir API'ya yeni yöntemler eklemek için mevcut istemcilerde herhangi bir değişiklik yapılması gerekmez. Bu, yeni bir işlevselliğe ihtiyaç duyan istemciler için varolan herhangi bir istemci için güncelleme bulunmadığından güvenli bir şekilde kullanılabilir.

Eski İşlevler API'dan Kullanımdan Kaldırıldı

Bu senaryoda, API'nızın mevcut tüketicileriyle işlevselliğin uzun vadede desteklenmeyeceğini bildirmeniz gerekir. Eski işlevsellik desteğini bırakana kadar (veya tüm istemciler yeni işlevselliğe yükseltilinceye kadar) eski ve yeni API işlevlerini aynı anda tutmalısınız. Bir kitaplık varsa, çoğu dilde eski yöntemleri eski / kullanımdan kaldırılmış olarak işaretleme yolu vardır. Bir tür üçüncü taraf hizmetiyse, eski / yeni işlevsellik için farklı uç noktalara sahip olmak genellikle en iyisidir.

Bir Şekilde API Değiştirmede Mevcut İşlevler

Bu senaryo, değişikliğin türüne bağlı olacaktır. Giriş parametrelerinin artık kullanılması gerekmiyorsa, şimdi ekstra verileri yok saymak için hizmeti / kütüphaneyi güncelleyebilirsiniz. Bir kitaplıkta, aşırı yüklenmiş yöntemin dahili olarak daha az parametre gerektiren yeni yöntemi çağırması gerekir. Barındırılan bir hizmette uç noktanın fazladan veri yoksaymasını sağlar ve her iki istemciye de hizmet verebilir ve aynı mantığı çalıştırabilir.

Mevcut işlevlerin yeni gerekli öğeler eklemesi gerekiyorsa, hizmetiniz / kitaplığınız için iki uç noktanız / yönteminiz olmalıdır. İstemciler güncellenene kadar her iki sürümü de desteklemeniz gerekir.

diğer düşünceler

Rather, the API is likely to extend the private objects we are using for our base API, but then we run into the same problem because added properties would also be available in the public API when they are not supposed to be.

Dahili özel nesneleri kitaplığınız / hizmetiniz aracılığıyla göstermeyin. Kendi türlerinizi oluşturun ve dahili uygulamayı eşleyin. Bu, dahili değişiklikler yapmanıza ve harici istemcilerin yapması gereken güncelleme miktarını en aza indirmenize olanak tanır.

The problem is more that it seems like many or most changes require breaking the public API if the objects aren't more separated, but I don't see a good way to do that without duplicating code.

Bir hizmet veya kütüphane olup olmadığı API'sı, istemcilerle tümleştirme noktasında kararlı olmalıdır. Girdilerin ve çıktıların ne olması gerektiğini belirlemek ve bunları ayrı varlıklar olarak tutmak için ne kadar çok zaman harcarsanız, yolunuzda çok fazla baş ağrısı kurtaracaksınız. API sözleşmesini kendi ayrı varlığı haline getirin ve gerçek işi sağlayan sınıflarla eşleyin. Dahili uygulamalar değiştiğinde harcanan zaman, fazladan arayüzü tanımlamak için gereken ekstra süreyi telafi etmelidir.

Bu adımı "yinelenen kod" olarak görmeyin. Benzer olsalar da, yaratılması için zaman ayırmaya değer ayrı varlıklar. Harici API değişiklikleri neredeyse her zaman dahili uygulamaya karşılık gelen bir değişiklik gerektirse de, dahili uygulama değişiklikleri her zaman harici API'yi değiştirmemelidir.

Misal

Bir ödeme işleme çözümü sağladığınızı varsayalım. Kredi kartı işlemleri yapmak için PaymentProviderA kullanıyorsunuz. Daha sonra PaymentProviderB'nin ödeme işlemcisiyle daha iyi bir fiyat elde edersiniz. API'nız, PaymentProviderA'nın temsili yerine türünüzdeki Kredi Kartı / Fatura Adresi alanlarına maruz kaldıysa, arayüz aynı kaldığından API değişikliği 0 olur (umarım yine de, PaymentProviderB, PaymentProviderA tarafından gerekli olmayan veriler gerektiriyorsa, her ikisini de destekleyin veya PaymentProviderA ile en kötü oranı koruyun).


Bu çok ayrıntılı cevap için teşekkürler. Mevcut projelerin bunu nasıl yaptığını öğrenmek için kullanabileceğim açık kaynaklı projelere dair herhangi bir örnek biliyor musunuz? Paylaşılan yöntemleri çağırırsanız, bölmeniz gerekeceğinden, çeşitli POCO yapım kodlarını çeşitli sürüm nesnelerine kopyalamadan bunu yapmalarına izin veren kodları nasıl düzenlediklerine dair bazı somut örnekler görmek istiyorum. bu nesneyi sürümlenmiş nesne için düzenleyebilmek için
Dava

1
Kafamın üstündeki iyi örneklerin farkında değilim. Bu hafta sonu biraz zamanım varsa, bunlardan bazılarının nasıl uygulanabileceğini göstermek için GitHub'a atmak için bir test uygulaması oluşturabilirim.
Phil Patterson

1
Zor kısmı, yüksek seviyeden istemciler ve sunucular arasındaki bağlantıyı en aza indirmeye çalışmanın birçok farklı yolu olmasıdır. WCF, istemciden sözleşmede olmayan verileri iletmenizi ve kablo üzerinden sunucuya göndermenizi sağlayan IExtensibleDataObject adında bir arabirime sahiptir. Google, sistemler arasında iletişim için Protobuf'u oluşturdu (.NET, Java vb. İçin açık kaynak uygulamaları vardır). Ayrıca, çalışabilecek birçok mesaj tabanlı sistem vardır (işleminizin senkronize olmayan bir şekilde gerçekleştirilebileceği varsayılarak).
Phil Patterson

Kaldırmaya çalıştığınız kod çoğaltmasının belirli bir örneğini (yeni bir yığın taşması sorusu olarak) göstermek ve topluluğun hangi çözümleri bulduğunu görmek kötü bir fikir olmayabilir. Soruyu genel olarak cevaplamak zor; bu nedenle belirli bir senaryo daha iyi olabilir.
Phil Patterson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.