API tasarımını sözleşme öncelikli (contract-first) yürütmek
Önce sözleşme, sonra kod yaklaşımının ekipler arası beklentiyi nasıl hizaladığı ve pratikte ne anlama geldiği.
API geliştirmenin iki farklı yaklaşımı var: önce kodu yazıp sonra belgelemek (code-first), ya da önce sözleşmeyi yazıp sonra kodu üretmek (contract-first). İkisi de çalışır; ama birden fazla ekip veya tüketici söz konusu olduğunda bu seçimin bedeli belirginleşiyor.
Contract-first (sözleşme öncelikli) yaklaşımın özü şu: API’nin nasıl davranacağını — hangi endpoint’lerin var olacağını, hangi veriyi alıp döndüreceğini, hangi hata kodlarını kullanacağını — kodu yazmadan önce bir belge olarak ortaya koymak. Bu belge hem geliştirici rehberi hem ekipler arası sözleşme hem de test referansı haline geliyor.
Code-first’in kaçınılmaz sorunu
Code-first yaklaşımla backend ekibi kodu yazar, bir süre sonra documentation üretir. Frontend veya mobil ekip bu süreçte havada kalır — ya backend tamamlanana kadar bekler, ya da tahminen ilerler. Tahmin çoğunlukla yanlış çıkar.
Sonuç: entegrasyon sırasında “siz şunu diyordunuz ama backend bunu döndürüyor” tartışmaları. Bu tartışmalar zaman kaybıdır ve erken aşamada sözleşme yazılmış olsaydı hiç yaşanmayacaktı.
Bir de beklenti hizalaması sorunu var. Backend ekibi user.name döndürürken frontend user.fullName bekliyordur. Ya da backend sayfalama (pagination) için page parametresi kullanırken frontend offset/limit bekliyordur. Bunlar küçük uyumsuzluklar ama biriktikçe entegrasyon maliyetini artırıyor.
OpenAPI ile sözleşme yazmak
Pratikte contract-first için en yaygın araç OpenAPI (eski adıyla Swagger) spesifikasyonu. YAML veya JSON olarak yazılıyor, araç desteği geniş.
Küçük bir örnek:
openapi: "3.0.3"
info:
title: Sipariş API
version: "1.0"
paths:
/orders:
get:
summary: Sipariş listesi
parameters:
- name: status
in: query
required: false
schema:
type: string
enum: [pending, completed, cancelled]
responses:
"200":
description: Başarılı
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Order"
components:
schemas:
Order:
type: object
required: [id, status, total]
properties:
id:
type: integer
status:
type: string
total:
type: number
Bu spesifikasyon kodu var olmadan önce yazılabiliyor. Ardından:
- Backend ekibi bu sözleşmeye göre implementasyon yapıyor.
- Frontend ekibi mock server kurarak UI geliştirmeye başlıyor.
- Test ekibi sözleşmeye göre beklentilerini tanımlıyor.
Hepsi paralel ilerleyebiliyor.
Mock server ile paralel geliştirme
Contract-first’in somut kazançlarından biri mock sunucu (mock server) kullanımı. Prism veya benzeri araçlar, OpenAPI spesifikasyonunu okuyup gerçekmiş gibi yanıt döndüren bir sunucu ayağa kaldırıyor.
Frontend ekibi backend’i beklemeden çalışabiliyor. Sözleşme değiştikçe mock sunucu da değişiyor; entegrasyon anında sürpriz çıkmıyor.
Bu yaklaşımın bir bedeli var: sözleşme yazmak zaman alıyor. Özellikle ilk sözleşme iterasyonlarında “bu alan gerekli mi, bu tip doğru mu” tartışmaları oluyor. Ama bu tartışmalar entegrasyon sırasında değil tasarım sırasında oluyor — maliyeti çok daha düşük.
Sözleşmeyi yaşatmak
Contract-first’in en sık başarısız olduğu nokta şurası: sözleşme bir kez yazılıyor, kod değiştikçe güncellenmeyecek. Sözleşme ve implementasyon zaman içinde birbirinden uzaklaşıyor. Birkaç ay sonra belge gerçeği yansıtmıyor.
Bunu engellemek için sözleşme doğrulaması (contract testing) devreye giriyor. Backend’in döndürdüğü yanıtları sözleşmeyle karşılaştıran testler. Uyumsuzluk tespit edildiğinde ya sözleşme güncelleniyor ya da implementasyon düzeltiliyor — ikisi arasında bilinçli bir karar veriliyor.
Sözleşmeyi kodla senkron tutmak, ekiplerin birbirine güvenle bağlanmasını sağlıyor. Tüketici “bu endpoint böyle çalışıyor” diyebiliyor ve haklı olabiliyor.
Hangi projelerde değer yaratıyor
Tek geliştirici, küçük proje: contract-first overkill olabilir. Sözleşme yazmak yerine direkt koda geçmek mantıklı.
Birden fazla ekip veya tüketici (web, mobil, üçüncü taraf): contract-first kesinlikle zaman kazandırıyor. Entegrasyon sürtünmesi düşüyor, beklenti yanlış anlamaları azalıyor.
Yıllarca yaşaması planlanan API: sözleşme bir karar kaydı işlevi görüyor. “Neden böyle tasarladık” sorusunun cevabı sözleşme versiyonlarında yaşıyor.
Ben artık birden fazla tüketicisi olacak herhangi bir API’ye sözleşme yazarak başlıyorum. Kod önce yazmak bir alışkanlıktı; değiştirmesi zaman aldı ama getirisi açık.