Sertaç Yıldırım saha notları

Ana sayfa → Bölüm 14

Definition of Done: Kontrol Listesi Değil, Kalite Sözleşmesi

Çarşamba 26 Kasım, 09:30. Çağrı merkezinden mesaj: “Dünden beri müşteriler ‘IBAN size ait değil’ hatası alıyor, IBAN’lar kendilerine ait.” Hatayı veren story altı gün önce “bitti” sütununa geçmişti. DoD’nin altı maddesinin altısı da işaretliydi.

Özet
  • Bizim “bitti”miz test ortamında bitiyordu. Story 26 saat boyunca 1.460 para çekme talebinin 212’sini (%14,5) yanlışlıkla reddetti. Alarm yoktu; çağrı merkezi fark etti.
  • DoD bir kontrol listesi değil, bir sözleşmedir. Liste işi yapanın hafızası içindir; sözleşme o işe güvenen PO, çağrı merkezi ve müşteri içindir.
  • Üç katman var: story, sprint, canlı. Her katman farklı bir “bitti”yi söyler. Bizde yalnızca ilki vardı.
  • DoD’yi ekip değiştirir, retroda, bir sonraki sprint için. PO bir tarihe yetişmek için gevşetemez; her yeni madde kapasiteden bir bedel alır.
  • Kırılınca işi açık say. Yeni bug kaydı değil, aynı story yeniden açılır ve bitti sayısından düşülür.

Sahadan: altı kutusu işaretli story

Story şuydu: “Para çekme talebinde, IBAN sahibinin adı hesap sahibinin adıyla eşleşmiyorsa talep reddedilsin.” Müşteri parasını yalnızca kendi adına olan hesaba çekebilir; bu bir regülasyon kuralı. Eşleşmeyi bankanın ad sorgulama servisi yapıyordu.

Sprint 12’deydi, 10–21 Kasım. 20 Kasım Perşembe “bitti”ye geçti. O gün DoD’miz altı maddeydi:

DoD v1 — Kasım 2025
1. Kod incelendi (en az bir onay)
2. Birim ve entegrasyon testleri CI'da yesil
3. Kod kapsami %80 ustu
4. Test ortamina deploy edildi
5. Kabul kriterleri test ortaminda dogrulandi
6. PO onayladi

Altısı da doğruydu. Kod kapsamı %91’di. Test ortamında bankanın sandbox servisiyle on iki senaryo denenmişti. 21 Kasım’daki review’da gösterildi, PO onayladı. Haftalık sürümle 25 Kasım Salı 10:00’da canlıya çıktı.

Sandbox, ona ne gönderirsek adı aynen geri döndürüyordu. Canlıdaki servis ise yalnızca ilk adı ve soyadı döndürüyordu. “Fatma Nur Kaya” bizim kayıtta üç kelimeydi, bankanın cevabında “FATMA KAYA” idi. Bizim karşılaştırmamız büyük-küçük harfi yok sayıyordu, ama adın tamamının eşleşmesini bekliyordu. İki adı olan her müşteri reddedildi. Test senaryolarının on ikisinde de tek adlı müşteriler vardı.

26 saat sürdü. Salı 10:00’dan Çarşamba 12:00’a kadar gelen 1.460 para çekme talebinin 212’si yanlışlıkla reddedildi, yani %14,5. Red oranını gösteren bir metrik yoktu, bu yüzden alarm da yoktu. Kapatma anahtarı da yoktu; kontrolü devre dışı bırakmak için geri alma sürümü çıkarmamız gerekti, o da 12:00’yi buldu. Asıl düzeltme Sprint 13’te bir buçuk gün sürdü.

DoD’yi ben yazmıştım. Daily yazısında özetini de vermiştim: testler geçti, CI/CD ilgili ortama deploy etti, özellik orada doğrulandı. “İlgili ortam” ifadesini ben seçmiştim ve kafamda test ortamıydı. Tanımımız bir story’nin bittiğini söylüyordu. Müşterinin gördüğü yerde bittiğini söylemiyordu.

Bitti, müşterinin gördüğü yerde biter.

DoD ne işe yarıyor: bir sözleşme

Scrum Kılavuzu DoD’yi artımın taahhüdü olarak tanımlar. Bir madde DoD’yi karşıladığı anda bir artım doğar. Karşılamayan madde canlıya çıkamaz, review’da bile gösterilemez; product backlog’a geri döner. Bu, bir kontrol listesinden çok daha güçlü bir cümle.

Farkı şöyle koyuyorum. Kontrol listesi işi yapanın hafızası içindir: bir şeyi unutmasın diye. Sözleşme ise o işe güvenen için yazılır. Bizim “bitti” dediğimiz anda başkaları bir şeylere güvenmeye başlıyor:

  • PO bir sonraki sprinti o işin çalıştığını varsayarak planlıyor.
  • Çağrı merkezi müşteriye verilecek cevabı o işe göre veriyor.
  • Başka ekipler o işin üstüne kendi işlerini kuruyor.
  • Hız grafiği o işi “yapıldı” diye sayıyor ve gelecek tahminleri ona dayanıyor.

26 Kasım’da dördü de yanlış bir şeye güvenmişti. Çağrı merkezi yeni red mesajından haberdar bile değildi; müşteriye ne diyeceğini bilmiyordu. Liste yanlış değildi. Kimsenin güvendiği şeyi söylemiyordu.

Kontrol listesi işi yapanın hafızası içindir. Sözleşme, o işe güvenen içindir.

Nasıl olmalı: üç katman

Sprint 13 retrosunda, 5 Aralık’ta, DoD’yi üç katmana böldük. Her katman farklı bir “bitti”yi söylüyor ve farklı bir zamanda kontrol ediliyor:

KatmanSöylediği şeyMaddelerNe zaman
StoryBu madde tek başına çalışıyorİnceleme, CI’da testler, canlıya benzer veriyle en az bir örnek, log ve metrik eklendiKart “bitti”ye geçmeden
SprintMaddeler birlikte çalışıyor ve etkilenenler biliyorRegresyon seti yeşil, sürüm notu yazıldı, müşteriye görünen değişiklikte çağrı merkezi bilgilendirildiReview’dan önce
CanlıMüşterinin gördüğü yerde çalışıyorCanlıda doğrulandı, pano ve alarm var, kapatma yolu denendi, 24 saat izlendiSürümden 24 saat sonra

Tahtaya da bir sütun ekledik: “Canlıda, izleniyor.” Kart “bitti”ye ancak oradan geçiyor. IBAN story’si bu düzende “bitti”ye hiç ulaşamazdı; ilk gün red oranı alarmı çalardı.

DoD v2 — Aralık 2025 (repoda: docs/bitti-tanimi.md)
STORY
  - Kod incelendi (en az bir onay)
  - Birim ve entegrasyon testleri CI'da yesil
  - Canliya benzer veriyle en az bir ornek
    (iki adli musteri, Turkce karakter, buyuk harf, bosluk)
  - Yeni davranis icin log satiri ve metrik var

SPRINT
  - Regresyon seti yesil
  - Surum notu yazildi
  - Musteriye gorunen degisiklikse cagri merkezi
    bilgilendirildi (ne degisti, musteriye ne denir)

CANLI
  - Canlida en az bir gercek islemle dogrulandi
  - Panoda gorunuyor, esik asilirsa alarm caliyor
  - Kapatma yolu var ve denendi (flag ya da geri alma)
  - 24 saat izlendi, sonra "bitti"

Cikarilan: "kod kapsami %80 ustu" (IBAN story'si %91'di)

Her katmana kim bakar?

Katmanları yazmak kolaydı; her birine kimin bakacağını yazmak bir hafta sürdü. Sonunda şöyle bağladık:

  • Story katmanı: işi yapan ve kodu inceleyen. İnceleyen yalnızca kodu değil, “canlıya benzer veri” örneğini de soruyor.
  • Sprint katmanı: her sprint dönüşümlü bir geliştirici, review’dan bir gün önce. Sürüm notunu ve çağrı merkezine gidecek iki satırlık açıklamayı o yazıyor.
  • Canlı katmanı: sürümü çıkaran kişi. 24 saat sonra panoya bakıyor, red oranı ya da hata oranı eşiğin altındaysa kartı “bitti”ye kendisi çekiyor.

Bir kural daha ekledik: kartı “bitti”ye çeken kişi, katmanın maddelerini karta tek satırla yazıyor. “Canlıda 3 gerçek talep denendi, red oranı %0,8, alarm eşiği %3.” İşaretli kutu değil, cümle. Altı ay sonra o karta bakan kişi neye güvenildiğini okuyabiliyor.

Test tarafına ayrıca girmiyorum. Epic, Story, Task yazısında testi ayrı karta koymak yerine DoD’ye gömmeyi anlatmıştım; o kural aynen duruyor. Buradaki soru testin nerede durduğu değil, “bitti”nin nerede bittiği.

Kapsam maddesini neden çıkardık? Çünkü bize hiçbir şey söylemiyordu. %91 kapsamlı bir story para çekme taleplerinin yedide birini reddetti. Madde bir güven hissi veriyordu, güvenilecek bir şey değil. Sözleşmeye yalnızca birinin gerçekten güvendiği maddeler girer.

DoD’yi kim değiştirir

Kılavuz net: kurumun bir standardı varsa ekip onu en az seviye olarak uygular; yoksa DoD’yi Scrum ekibi oluşturur. Bizde kurum standardı yok, o yüzden kurallarımızı kendimiz koyduk:

  • Değişiklik retroda önerilir. Retrospective yazısındaki aksiyon kuralı burada da geçerli: tanım, sorumlu, termin.
  • Ekip karar verir, PO dinler. PO bir maddenin eklenmesini isteyebilir. Bir tarihe yetişmek için maddeyi gevşetemez.
  • Sprint ortasında değişmez. Bir sonraki sprintten geçerli olur. Sprint ortasında değişen DoD, o sprintin taahhüdünü de sessizce değiştirir.
  • Her ekleme bir bedeldir ve bu bedel yazılır. Yeni maddeler story başına ortalama yarım adam-gün getirdi. Sprint 14’te dokuz yerine yedi madde planladık.

Son madde en çok itiraz alan oldu. “Daha az iş mi yapacağız?” Hayır, daha az işi bitmiş sayacağız. Aradaki fark, Sprint 12’de “biten” yazan ama canlıda bir buçuk gün daha iş çıkaran bir maddeydi.

Kırılınca: işi açık saymak

26 Kasım’da ilk refleksimiz yeni bir bug kaydı açmaktı. Bunu yapsaydık story “bitti” olarak kalacaktı, Sprint 12’nin sayısı yedi olarak kalacaktı ve hata “başka bir iş” olarak Sprint 13’ün kapasitesinden yiyecekti. Kâğıt üstünde hiçbir şey bozulmamış olacaktı.

Onun yerine şu kuralı koyduk:

  1. Canlıya çıktıktan sonraki 7 gün içinde kabul kriterini bozan bir hata çıkarsa aynı story yeniden açılır. 7 günden sonrası normal bir bug kaydıdır.
  2. Açılan story, bittiği sprintin sayısından düşülür. Definition of Ready yazısındaki tabloda Sprint 12 için “7 / 8” yazıyor. Bugünkü kurala göre o sayı 6 / 8. Yazıyı düzeltmiyorum; bu yazı düzeltmenin kendisi.
  3. Esnetme kayda geçer. Bir iş DoD’nin bir maddesini karşılamadan canlıya çıkmak zorundaysa çıkabilir. Ama “bitti” sayılmaz. Hangi madde eksik, kararı kim verdi, eksik ne zaman tamamlanacak; üçü kartın üstüne yazılır. Madde tamamlanana kadar kart açık kalır.

Kuralın beklemediğim bir yan etkisi oldu. Ekip sürümden sonraki günlerde panoya kendiliğinden bakmaya başladı, çünkü canlıda geri dönen iş artık kendi sprintinin sayısından düşüyordu. Kimse bunu istemedi. Sayı istetti.

DoD’yi esnetmek işi hızlandırmaz. Bitmemiş işi bitmiş saymayı hızlandırır.

Nasıl bozuluyor

Yapılacaklar
  • DoD’yi story, sprint ve canlı diye katmanla
  • “Bitti”den önce bir “canlıda, izleniyor” sütunu koy
  • Canlıya benzer veriyle en az bir örnek iste
  • Canlıda geri dönen işi aynı story olarak yeniden aç
  • Her yeni maddenin kapasite bedelini yaz
Yapılmayacaklar
  • “İlgili ortam” gibi belirsiz ifadeler kullanmak
  • Kimsenin güvenmediği maddeleri (kapsam yüzdesi) tutmak
  • Tarihe yetişmek için DoD’yi sessizce gevşetmek
  • Canlıdaki hatayı yeni bug kaydıyla saklamak
  • DoD’yi sprint ortasında değiştirmek

Ne izlemeli?

Sprint 9–12
DoD v1
Sprint 14
DoD v2
Planlanan madde (sprint başına)8–97
Biten madde29 (dört sprintte)6
7 gün içinde canlıdan geri dönen4 / 29 (%14)0 / 6
Canlıdaki hatayı ilk fark eden4’ünde de müşteri ya da çağrı merkezi

Sprint 14 tek bir sprint. Sıfır bir sonuç değil, bir başlangıç. Canlı katmanının rahatsız edici bir bedeli de çıktı: haftalık sürümle çalıştığımız için 16 Aralık Salı sürümüne yetişmeyen iş, sprint içinde “bitti” olamıyor. Yedinci madde kod olarak bitti, 23 Aralık’ta çıktı ve Sprint 15’te sayılacak. Bunu bilerek kabul ettik.

Asıl izlediğim satır sonuncusu: bir sonraki hatayı ilk kimin gördüğü. Alarm görüyorsa DoD’nin canlı katmanı çalışıyor. Müşteri görüyorsa çalışmıyor.

Kontrol listesi

Kartı “bitti”ye çekmeden önce
  • DoD’mizde “bitti”nin hangi ortamda bittiği açıkça yazıyor mu?
  • Canlıya benzer veriyle en az bir örnek denendi mi?
  • Bu iş canlıda bozulursa bunu ilk kim görecek: alarm mı, müşteri mi?
  • Kapatma yolu var mı ve biri onu gerçekten denedi mi?
  • Müşteriye görünen bir değişiklikse çağrı merkezi ne diyeceğini biliyor mu?
  • DoD’de kimsenin güvenmediği bir madde var mı?
  • Son sprintte canlıdan geri dönen story’ler bitti sayısından düşüldü mü?

Sonuç

26 Kasım sabahı çağrı merkezinden gelen mesaj bir test hatası değildi, bir sözleşme ihlaliydi. Altı kutu işaretliydi ve altısı da doğruydu. Ama hiçbiri, o işe güvenen insanların güvendiği şeyi söylemiyordu.

Şimdi kart “bitti”ye geçmeden 24 saat bekliyor. Bu bir yavaşlık değil. Bu, “bitti” kelimesini bir daha çağrı merkezinden öğrenmemenin bedeli.

Kaynak

DoD’nin artımın taahhüdü olması, karşılanmayan maddenin review’da gösterilememesi ve kurum standardı ile ekip DoD’si ilişkisi Scrum Kılavuzu’ndan (2020). Üç katman, 7 gün kuralı ve işi açık sayma kendi ekibimizde bu olaydan sonra koyduğumuz kurallar.