Kural
Genel API sözleşmelerini ihlal etmekten kaçının.
Mevcut istemci isteklerini bozacak genel API uç noktası değişiklikleri
uyumsuzluk yaratan değişikliklerdir.
API sözleşmesini bir söz olarak düşünün;
— istemciler
ona bağımlı hale geldikten sonra bunu değiştirmek kodlarını bozar.
Desteklenen diller: PHP, Java, C#, Python, JavaScript, TypeScriptGiriş
Genel (public) API'ler, servisiniz ile bunu kullananlar arasındaki sözleşmelerdir. İstemciler bir uç noktanın (endpoint) istek formatına, yanıt yapısına veya davranışına bağımlı hale geldiğinde, bu yapıyı değiştirmek onların kodunu bozar. Uyumsuzluk yaratan (breaking) değişiklikler, tüm istemcilerin aynı anda güncelleme yapmasını zorunlu kılar; ancak istemcileri kontrol etmediğiniz durumlarda bu genellikle imkansızdır. Mobil uygulamalar zorunlu olarak güncellenemez, üçüncü taraf entegrasyonların migrasyon süresine ihtiyacı vardır ve eski (legacy) sistemler asla güncellenmeyebilir.
Neden önemli?
İstemci kesintileri ve güven kaybı: Uyumsuz API değişiklikleri, prodüksiyon ortamındaki istemci uygulamalarında ani hatalara neden olur. Kullanıcılar hatalar, veri kayıpları veya tam servis kesintileri yaşar. Bu durum, API sağlayıcıları ile tüketicileri arasındaki güvene zarar verir ve kararlı API'lerin kararlı kalacağına dair zımni sözleşmeyi ihlal eder.
Koordinasyon maliyetleri: Uyumsuz değişiklikleri birden fazla istemci ekibi arasında koordine etmek masraflı ve yavaştır. Her ekibin kodu güncellemek, değişiklikleri test etmek ve devreye almak için zamana ihtiyacı vardır. Bilinmeyen istemcilere (mobil uygulamalar, üçüncü taraf entegrasyonlar) sahip genel API'ler için koordinasyon imkansızdır.
Sürüm çoğalması: Kötü yönetilen uyumsuz değişiklikler, aynı anda birden fazla API sürümünün bakımının yapılmasına yol açar. Her sürüm ayrı kod yolları, testler, dokümantasyon ve hata düzeltmeleri gerektirerek bakım yükünü katlanarak artırır.
Kod örnekleri
❌ Kural dışı:
// Version 1: Original API
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
res.json({ id: user.id, name: user.name });
});
// Version 2: Breaking change - renamed field
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
res.json({
id: user.id,
fullName: user.name // Breaking: 'name' renamed to 'fullName'
});
});
Neden yanlış: name alanını fullName olarak yeniden adlandırmak, name alanını bekleyen tüm mevcut istemcileri bozar. response.name değerine erişen istemci kodu undefined alarak hatalara yol açar. Bu değişiklik, tüm istemcilerin aynı anda güncelleme yapmasını ya da hata almasını zorunlu kılar.
✅ Kurallara uygun:
// Version 2: Additive change - keeps old field, adds new
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
res.json({
id: user.id,
name: user.name, // Keep for backward compatibility
fullName: user.name // Add new field (deprecated 'name')
});
});
// Or use API versioning
app.get('/api/v2/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
res.json({ id: user.id, fullName: user.name });
});
Neden önemli: Eski olanı tutmak name alanı, geri dönüştürülebilirliği korurken ekleme yapar fullName yeni istemciler için. Alternatif olarak, yeni sürümlendirilmiş bir uç nokta (endpoint) oluşturmak (/api/v2/) mevcut istemcileri etkilemeden kırıcı değişiklikler (breaking changes) yapılmasına olanak tanır ve hâlâ şunu kullanan /api/v1/.
Sonuç
API'leri eklemeli değişikliklerle geliştirin: yeni alanlar, yeni uç noktalar (endpoints) ve isteğe bağlı parametreler ekleyin. Kırıcı değişiklikler kaçınılmaz olduğunda, eski ve yeni sürümleri aynı anda çalıştırmak için API sürümlendirmesini kullanın. Kaldırmadan önce eski alanları net zaman çizelgeleri ve geçiş kılavuzlarıyla kullanımdan kaldırın (deprecate edin).

