Bir pull request düşünün: 40 dosya değişmiş, ödeme akışı yeniden düzenlenmiş, veritabanına yeni alanlar eklenmiş ve birkaç “hazır buradayken” düzeltmesi yapılmış. Testler geçiyor. Kod geliştiricinin ortamında çalışıyor. Ancak inceleyen kişinin cevaplaması gereken soru zor: Bu değişikliği güvenle canlıya alabilir miyiz?
Pull request boyutu neden önemlidir? Çünkü bir değişikliği anlamak, doğrulamak ve gerektiğinde geri almak için gereken çabayı etkiler. PR büyüdükçe yalnızca okunacak kod artmaz; bileşenler arasındaki ilişkileri ve olası hata yollarını takip etmek de zorlaşır.
Bununla birlikte, küçük PR yazmak bir satır sınırına uymaktan ibaret değildir. Asıl hedef, tek bir amacı olan, bağımsız değerlendirilebilen ve güvenle birleştirilebilen değişiklikler üretmektir.
Bu yazıda, ödeme sistemine idempotency desteği eklenen örnek bir uygulama üzerinden bu yaklaşımı inceleyeceğiz.
Vaka notu: Aşağıdaki senaryo, tasarım kararlarını açıklamak için oluşturulmuş örnek bir vakadır. Gerçek bir projeden ölçülmüş performans veya verimlilik sonuçları içermez.
PR Boyutu Satır Sayısından Daha Fazlasıdır
Satır sayısı yararlı bir ilk işarettir; ancak inceleme maliyetini tek başına açıklamaz.
Otomatik üretilmiş bir dosyadaki 1.000 satırlık değişiklik, ödeme yetkilendirmesini değiştiren 20 satırlık bir düzenlemeden daha kolay değerlendirilebilir. Küçük görünen bir koşul değişikliği ise çok sayıda kullanıcıyı etkileyebilir.
Bir PR’ın gerçek boyutunu değerlendirirken şu boyutları birlikte düşünmek gerekir:
| Boyut | İnceleme sırasında sorulacak soru |
|---|---|
| Kod hacmi | Ne kadar kod ve test okunacak? |
| Kavramsal kapsam | Kaç farklı davranış veya tasarım kararı değişiyor? |
| Bağımlılıklar | Değişiklik kaç bileşenin birlikte çalışmasına bağlı? |
| Operasyonel etki | Dağıtım, veri geçişi veya izleme gerekiyor mu? |
| Geri alınabilirlik | Önceki sürüme dönülürse veri ve sistem uyumlu kalır mı? |
Bu nedenle yararlı hedef, “Her PR 200 satırdan az olmalı” gibi katı bir kural değildir. Daha iyi bir ölçüt şudur:
İnceleyen kişi, değişikliğin amacını, doğruluk koşullarını ve hata durumlarını tek bir bütün olarak değerlendirebiliyor mu?
Örnek Vaka: Ödeme API’sine Idempotency Eklemek
Bir ödeme API’sinde istemci, yanıt alamadığı isteği yeniden gönderiyor. İlk istek aslında başarılı olmuşsa ikinci istek mükerrer ödeme oluşturabiliyor.
Hedefimiz, aynı işlem için aynı idempotency anahtarı kullanıldığında ikinci bir ödeme oluşturulmasını önlemek.
İlk bakışta çözüm küçük görünebilir:
- İstekten idempotency anahtarını oku.
- Anahtar daha önce kullanılmış mı kontrol et.
- Kullanılmışsa önceki sonucu döndür.
- Kullanılmamışsa ödemeyi gerçekleştir ve sonucu sakla.
Üretim ortamındaki zor sorular ise bu listenin arasında saklıdır:
- Aynı anahtarla iki istek eşzamanlı gelirse ne olur?
- Aynı anahtar farklı bir tutarla tekrar kullanılırsa ne yapılır?
- Ödeme sağlayıcısı işlemi tamamlar, ancak uygulama sonucu kaydedemeden kapanırsa ne olur?
- Yeni sürüm geri alınırsa eklenen kayıtlar nasıl ele alınır?
- Anahtarlar hangi müşteri veya hesap kapsamında benzersizdir?
Bu davranışları; şema değişikliği, servis düzenlemesi, API entegrasyonu ve canlıya geçişle birlikte tek PR’a koymak incelemeyi zorlaştırır. İnceleyen kişi aynı anda hem veri modelini hem eşzamanlılık tasarımını hem de dağıtım güvenliğini değerlendirmek zorunda kalır.
Büyük PR Yaklaşımının Sorunu
Tek bir büyük PR’da aşağıdaki değişikliklerin bulunduğunu varsayalım:
- Yeni idempotency tablosu.
- Ödeme servisinin yeniden düzenlenmesi.
- Anahtar doğrulama ve istek özeti oluşturma.
- Eşzamanlı isteklerin yönetimi.
- Ödeme sağlayıcısı entegrasyonu.
- API hata yanıtları.
- Metrikler ve etkinleştirme ayarı.
- İlgisiz isimlendirme ve biçimlendirme düzeltmeleri.
Buradaki temel sorun dosya sayısı değildir. Birbirinden farklı doğruluk sorularının aynı incelemede birleşmesidir.
Bir şema yorumu uygulama kodunu değiştirebilir. Sağlayıcının hata davranışı veri modelinin yeniden ele alınmasını gerektirebilir. İlgisiz biçimlendirme değişiklikleri ise asıl davranış değişikliğini görmeyi güçleştirebilir.
Değişikliği Güvenli PR’lara Bölmek
Bu vakada bölme sınırlarını dosya türlerine göre değil, doğrulanabilir davranışlara göre belirleyebiliriz. Her PR’ın ilgili kodu, testleri ve gerekli açıklamaları birlikte taşıması gerekir.
PR 1: Geriye Uyumlu Veri Modelini Eklemek
İlk PR yalnızca yeni veri yapısını hazırlar. Mevcut ödeme akışı henüz bu yapıyı kullanmaz.
Örnek alanlar:
- Müşteri veya hesap kimliği.
- Idempotency anahtarı.
- İstek içeriğinin özeti.
- İşlem durumu.
- Sağlayıcı işlem referansı.
- Saklanacak sonuç bilgileri.
- Oluşturulma ve sona erme zamanı.
Bu PR’ın temel inceleme sorusu şudur:
Yeni şema, çalışan eski uygulama sürümünü bozmadan dağıtılabilir mi?
Anahtarın hesap kapsamında benzersiz olması gerekiyorsa bu kural veritabanında uygun bir benzersizlik kısıtıyla korunmalıdır. Yalnızca uygulamada “kayıt var mı?” sorgusu yapmak, eşzamanlı isteklerde yeterli olmaz.
Doğrulama, şemanın uygulanabilmesini ve benzersizlik davranışını kapsar. Geri alma yaklaşımı da açıktır: Uygulama eski sürüme döndüğünde kullanılmayan yeni tablo yerinde kalabilir. Şemayı hemen silmek zorunlu değildir.
PR 2: İşlem Durumlarını ve Eşzamanlılık Davranışını Uygulamak
İkinci PR, idempotency kayıtlarının nasıl oluşturulacağını ve güncelleneceğini tanımlar. Üretimdeki ödeme uç noktası henüz bu davranışa geçirilmez.
Örnek durumlar:
| Durum | Anlamı | Tekrarlanan istekte davranış |
|---|---|---|
| İşleniyor | İşlem başlatılmış, kesin sonuç henüz yok | Sözleşmede tanımlanan bekleme veya yeniden deneme yanıtı |
| Tamamlandı | İşlem sonucu kaydedilmiş | Kayıtlı sonucu döndür |
| Sonuç belirsiz | Sağlayıcıda işlem gerçekleşmiş olabilir | Yeni ödeme başlatmadan sonucu uzlaştır |
Ayrıca aynı anahtar farklı istek içeriğiyle gönderildiğinde isteğin reddedilmesi gerekir. Anahtar eşleşmesi tek başına işlemlerin aynı olduğunu kanıtlamaz.
Bu PR’ın temel sorusu:
Sistem, eşzamanlı istekleri ve belirsiz sonuçları tutarlı biçimde yönetiyor mu?
Buradaki testlerin yalnızca başarılı akışı kapsaması yeterli değildir. Eşzamanlı kayıt oluşturma, farklı içerikle anahtarın tekrar kullanılması ve yarım kalan işlem durumları da doğrulanmalıdır.
PR 3: Ödeme Akışını Kontrollü Şekilde Bağlamak
Üçüncü PR, hazırlanan davranışı ödeme API’sine bağlar. Etkinleştirme ayarı varsayılan olarak kapalıdır.
Bu aşamada kritik sınır, veritabanı ile harici ödeme sağlayıcısı arasındadır. Yerel bir veritabanı işlemi, dış servisteki ödeme ile kendiliğinden atomik hâle gelmez.
Sağlayıcı idempotency desteği sunuyorsa entegrasyon, onun anahtar kapsamı ve geçerlilik kurallarına göre tasarlanmalıdır. Destek sunmuyorsa zaman aşımı sonrasında körlemesine yeniden ödeme denemek yerine sağlayıcı referansıyla sorgulama veya uzlaştırma mekanizması gerekir.
Bu PR’ın inceleme sorusu:
Yerel kayıt ile sağlayıcı sonucu ayrıştığında mükerrer ödeme riski nasıl kontrol ediliyor?
Doğrulama özellikle şu hata penceresini kapsamalıdır: Sağlayıcı ödemeyi tamamlar, uygulama sonucu kaydetmeden durur.
Etkinleştirme ayarının kapatılması da ayrıca tasarlanmalıdır. Yeni işlemler eski akışa dönebilir; ancak başlamış veya tamamlanmış idempotent işlemlerin tekrarları güvenli biçimde ele alınmaya devam etmelidir.
PR 4: Kademeli Etkinleştirme ve Operasyonel Doğrulama
Son aşamada özellik sınırlı bir kapsamda etkinleştirilir. Gerekli metrikler ve alarmlar, ilk canlı işlemden önce hazır olmalıdır.
İzlenebilecek göstergeler:
- Tekrarlanan istek sayısı.
- Aynı anahtarla farklı içerik gönderilme sayısı.
- Uzun süre “işleniyor” durumunda kalan kayıtlar.
- Sonucu belirsiz işlemler.
- Ödeme başarı oranı ve yanıt süresi.
Bu aşamanın sorusu şudur:
Özelliği daha geniş kullanıma açmak için yeterli operasyonel kanıt var mı?
Eski akışın veya geçici ayarların temizlenmesi, geçiş doğrulandıktan sonra ayrı bir PR olarak yapılabilir.
Küçük PR’lar Bu Vakada Ne Kazandırdı?
Bu bölme yaklaşımı ödeme problemini basitleştirmedi. Problemin farklı parçalarını ayrı ayrı değerlendirmeyi mümkün kıldı.
| Tek büyük PR | Odaklı PR dizisi |
|---|---|
| Şema, iş mantığı ve dağıtım birlikte değerlendirilir | Her aşamanın belirli bir inceleme sorusu vardır |
| Bir tasarım değişikliği geniş bir diff’i etkileyebilir | Geri bildirim daha dar bir kapsamda uygulanabilir |
| Hatanın hangi değişiklikten geldiğini ayırmak zorlaşabilir | Hata araştırması daha sınırlı bir değişiklikten başlayabilir |
| Geri alma birçok davranışı aynı anda etkileyebilir | Uyumlu ara durumlar önceden tasarlanabilir |
Beklenen fayda, inceleme ve hata ayıklama yükünün azalmasıdır. Bunun gerçekten gerçekleşip gerçekleşmediği ise ekip verileriyle ölçülmelidir.
Küçük PR ile Eksik PR Arasındaki Fark
Bir değişikliği küçük tutmak için testlerini sonraki PR’a bırakmak doğru bir bölme değildir. Aynı şekilde, derlenen ancak dağıtıldığında mevcut davranışı bozan bir ara sürüm de güvenli değildir.
Küçük PR, kapsamı dar ama kendi kapsamında tamamlanmış değişikliktir.
Her PR için şu koşullar aranmalıdır:
- Birleştirildiğinde ana dalı çalışır durumda bırakır.
- Getirdiği davranışın testlerini içerir.
- Önceki ve sonraki sürümlerle gereken uyumu korur.
- Bağımlı olduğu PR’ları açıkça belirtir.
- Dağıtım ve geri alma etkilerini anlaşılır kılar.
Özellikle kaçınılması gereken bölme biçimi, üretim kodunu bir PR’a, onun doğruluk testlerini başka PR’a ayırmaktır. Bölme, incelemeyi kolaylaştırmalı; doğruluk kanıtını parçalamamalıdır.
Bağımlı PR’ları Nasıl Yönetmeli?
Bazı değişiklikler doğal olarak bir zincir oluşturur. Veri modeli tamamlanmadan servis katmanı, servis katmanı olmadan API entegrasyonu anlamlı olmayabilir.
Böyle durumlarda birbirine bağımlı PR’lar kullanılabilir. Ancak her açıklama, zincirdeki konumunu ve incelenmesi gereken farkı açıkça belirtmelidir.
Örnek bir PR açıklaması:
Amaç: Idempotency anahtarlarının hesap kapsamında benzersiz olmasını sağlamak.
Kapsam: Yeni tablo, benzersizlik kısıtı ve ilgili veritabanı testleri.
Davranış etkisi: Mevcut ödeme akışı henüz yeni tabloyu kullanmıyor.
Bağımlılık: Sonraki PR, işlem durumlarının yönetimini ekleyecek.
Dağıtım: Şema mevcut uygulama sürümüyle uyumlu.
Geri alma: Uygulama geri alınırsa tablo korunabilir.
Bağımlı PR’larda alt katman değiştiğinde üst katmanların da yeniden doğrulanması gerekir. Bir PR’ın küçük olması, temel aldığı kod değiştikten sonra önceki incelemenin otomatik olarak geçerli kalacağı anlamına gelmez.
PR Boyutunun Etkisini Nasıl Ölçebilirsiniz?
“Daha küçük PR açıyoruz” ifadesi tek başına bir başarı ölçütü değildir. Amaç daha fazla PR üretmek değil, güvenli değişiklikleri daha az beklemeyle teslim etmektir.
Ekip içinde şu göstergeleri birlikte izleyebilirsiniz:
| Metrik | Gösterdiği şey |
|---|---|
| İlk anlamlı incelemeye kadar geçen süre | İnceleme kuyruğundaki bekleme |
| İncelemeye hazır oluş ile birleştirme arasındaki süre | İnceleme ve düzeltme döngüsü |
| İşin başlangıcından canlıya çıkışına kadar geçen süre | PR bölmenin toplam teslimata etkisi |
| Birleştirme sonrası düzeltme ihtiyacı | Kaçan sorunların işareti |
| Geri alma ve olay sayısı | Operasyonel sonuçlar |
Karşılaştırmalarda otomatik üretilen dosyaları, bağımlılık güncellemelerini ve davranış değiştiren kodu ayrı değerlendirmek yararlıdır. Benzer risk ve iş türlerini karşılaştırmadan yalnızca satır sayısından sonuç çıkarmak yanıltıcı olabilir.
Bir başka önemli nokta da PR başına süre ile işin toplam süresini birlikte izlemektir. Her PR daha hızlı birleşse bile uzun bir bağımlılık zinciri özelliğin teslimatını geciktirebilir.
Büyük PR Ne Zaman Makuldür?
Bazı değişiklikler doğal olarak geniştir: otomatik kod üretimi, depo genelinde mekanik bir dönüşüm veya bölünmesi uyumsuz ara durumlar oluşturacak bir güncelleme.
Bu durumlarda hedef, büyük PR’ı gerekçesiz biçimde parçalamak değildir. İncelemeyi kolaylaştırmak için:
- Mekanik düzenlemeleri davranış değişikliklerinden ayırın.
- Kullanılan dönüşüm aracını ve doğrulama yöntemini açıklayın.
- Elle değiştirilmiş kritik dosyaları belirtin.
- İnceleyene nereden başlaması gerektiğini söyleyin.
- Dağıtım ve geri alma koşullarını yazın.
Binlerce satırlık öngörülebilir bir dönüşüm, birkaç farklı iş kuralını değiştiren kısa bir PR’dan daha kolay incelenebilir. Boyut, her zaman değişikliğin anlamıyla birlikte değerlendirilmelidir.
Sık Sorulan Sorular
İdeal pull request boyutu kaç satırdır?
Her ekip ve değişiklik türü için geçerli bir sayı yoktur. Satır sayısını bir uyarı işareti olarak kullanabilirsiniz. Asıl ölçüt, PR’ın tek bir amacı olup olmadığı ve doğruluğunun makul bir incelemeyle değerlendirilebilmesidir.
Küçük PR’lar her zaman daha hızlı mı teslim edilir?
Hayır. Çok sayıda bağımlı PR; inceleme, CI ve birleştirme yükünü artırabilir. Bölme sınırları, bağımsız doğrulanabilir ve güvenli ara durumlar oluşturmalıdır.
Refactoring ile özellik geliştirme aynı PR’da yapılmalı mı?
Özelliği mümkün kılan hazırlık düzenlemesi bağımsız ve davranışı koruyan bir değişiklikse ayrı PR yararlı olabilir. Birbirinden ayrılması kodu anlaşılmaz veya geçici olarak hatalı hâle getiriyorsa birlikte tutulabilir.
Küçük PR daha az test gerektirir mi?
Test ihtiyacını satır sayısı değil, değişen davranış ve risk belirler. Ödeme veya yetkilendirme akışındaki birkaç satır kapsamlı doğrulama gerektirebilir.
Bir Sonraki PR İçin Tek Bir Soru
PR açmadan önce açıklamasına şu cümleyi eklemeyi deneyin:
“Bu değişikliğin doğru olduğunu kabul etmek için şu davranışın doğrulanması gerekir: …”
Cümleyi tamamlamak için birbirinden bağımsız birçok koşul sıralıyorsanız değişikliği bölmek yararlı olabilir.
Pull request boyutu neden önemlidir sorusunun pratik karşılığı burada ortaya çıkar: Kapsamı iyi belirlenmiş değişiklikler, inceleyenin neyi doğruladığını görmesini kolaylaştırır. Bu da geliştiriciye daha odaklı geri bildirim, ekibe daha anlaşılır bir değişiklik geçmişi ve üretim sorunlarında daha dar bir araştırma alanı sağlar.