Ders 16 / 19
Katkı Süreci
Öneriden yayına uzanan akışın durum makinesi olarak tanımlanması, kabul kapılarının onaylara bağlanması, geçersiz geçişlerin saptanması ve aşama sürelerinin ölçülerek darboğazın bulunması.
İçindekiler
Önceki dersin ürettiği sürüm ve göç kılavuzu, değişikliklerin nereden geldiğini sormadı;
arayüz tanımı iki kez okundu ve arada bir şey değişmişti. dugme bileşenine genislik
özelliğinin eklenmesi kimin kararıydı, kim inceledi ve bu karar kaç günde verildi?
Katkı süreci bu soruların yanıtını verir. Bir tasarım sistemi, kullanan ekiplerin değiştiremediği bir şeye dönüştüğünde iki sonuçtan biri doğar: ya sistem ihtiyaçların gerisinde kalır ya da ekipler sistemi atlayıp kendi kopyalarını yazar. Katkı süreci bu ikisini önlemek için vardır, ama kendisi de bir maliyet taşır ve maliyeti ölçülmelidir.
Akışın Durumları
Bir katkı, öneri anından yayına kadar birkaç ayrı durumdan geçer ve her durumun bir sorusu vardır:
- Öneri. Ne isteniyor? Bu aşamada çözüm değil, ihtiyaç yazılır: hangi ekranda, hangi sorun, mevcut bileşenlerle neden çözülemiyor.
- Keşif. Bu gerçekten sistemin işi mi? İlk derste tanımlanan kapsam ölçütü burada işletilir; ihtiyaç tek ekibe özgüyse katkı ürüne yönlendirilir.
- Taslak. Nasıl çözülecek? Arayüz tasarlanır, belge bölümleri yazılır, göç etkisi varsa hesaplanır.
- İnceleme. Çözüm sistemin ölçütlerini karşılıyor mu? Üç ayrı inceleme yürür: tasarım, kod ve erişilebilirlik.
- Kabul. Karar verildi. Yayın notunun yazılması bekleniyor.
- Yayın. Katkı bir sürümle çıktı.
Bunlara üç son durum eklenir: reddedildi, ertelendi ve incelemeden taslağa dönüş. Reddedilme bir başarısızlık değil, kapsam ölçütünün çalıştığının kanıtıdır; hiç reddedilmeyen bir katkı süreci, ölçütün işletilmediğini gösterir.
Durum Makinesinin Kurulması
Akışı yazılı bir belge olarak tanımlamak yetmez; hangi geçişin geçerli olduğu ve bir geçişin hangi onayları gerektirdiği makineyle denetlenebilir olmalıdır. Aşağıdaki program yedi katkının geçmişini alır, geçişleri ve kapıları denetler, aşama sürelerini hesaplar ve darboğazı bulur.
// katki.mjs — katki akisinin durum makinesi, kapi denetimi ve asama sureleri // Gecerli gecisler. Listede olmayan her gecis gecersizdir. const GECIS = { oneri: ["kesif", "reddedildi", "ertelendi"], kesif: ["taslak", "reddedildi", "ertelendi"], taslak: ["inceleme", "ertelendi"], inceleme: ["kabul", "taslak", "reddedildi"], kabul: ["yayin"], yayin: [], reddedildi: [], ertelendi: ["kesif"], }; // Kapilar: bir gecisin yapilabilmesi icin toplanmis olmasi gereken onaylar. const KAPI = { "inceleme->kabul": ["tasarim", "kod", "erisim"], "kabul->yayin": ["surum-notu"], }; // Katki gecmisleri: [gun, durum] cifti ve gecis anina kadar toplanmis onaylar. const KATKILAR = [ { ad: "dugme.genislik", onay: ["tasarim", "kod", "erisim", "surum-notu"], gecmis: [[0, "oneri"], [2, "kesif"], [5, "taslak"], [9, "inceleme"], [12, "kabul"], [14, "yayin"]] }, { ad: "acilir-liste.aramali", onay: ["tasarim", "kod", "erisim", "surum-notu"], gecmis: [[0, "oneri"], [6, "kesif"], [11, "taslak"], [18, "inceleme"], [47, "kabul"], [52, "yayin"]] }, { ad: "sayi-alani", onay: ["tasarim", "kod", "erisim", "surum-notu"], gecmis: [[0, "oneri"], [3, "kesif"], [10, "taslak"], [21, "inceleme"], [29, "taslak"], [36, "inceleme"], [44, "kabul"], [46, "yayin"]] }, { ad: "arac-ipucu.belge", onay: ["tasarim", "kod", "erisim", "surum-notu"], gecmis: [[0, "oneri"], [4, "ertelendi"], [61, "kesif"], [66, "taslak"], [70, "inceleme"], [78, "kabul"], [80, "yayin"]] }, { ad: "kart.tiklanabilir", onay: ["tasarim", "kod", "erisim", "surum-notu"], gecmis: [[0, "oneri"], [3, "inceleme"], [8, "kabul"], [10, "yayin"]] }, { ad: "tablo.yogunluk", onay: ["tasarim", "kod", "surum-notu"], gecmis: [[0, "oneri"], [5, "kesif"], [9, "taslak"], [16, "inceleme"], [23, "kabul"], [25, "yayin"]] }, { ad: "rozet.ikonlu-kaldirma", onay: ["tasarim"], gecmis: [[0, "oneri"], [7, "kesif"], [19, "reddedildi"]] }, ]; // 1. Gecis ve kapi denetimi. console.log("geçersiz geçişler ve kapı ihlalleri"); let kusurlu = 0; for (const k of KATKILAR) { const kusur = []; for (let i = 1; i < k.gecmis.length; i++) { const onceki = k.gecmis[i - 1][1]; const simdi = k.gecmis[i][1]; if (!GECIS[onceki].includes(simdi)) kusur.push(`geçersiz geçiş: ${onceki} → ${simdi}`); const kapi = KAPI[`${onceki}->${simdi}`]; if (kapi) { const eksik = kapi.filter((o) => !k.onay.includes(o)); if (eksik.length) kusur.push(`${onceki} → ${simdi} için eksik onay: ${eksik.join(", ")}`); } } if (kusur.length) { kusurlu++; console.log(`${k.ad.padEnd(23)} ${kusur.join(" | ")}`); } } console.log(`kusurlu katkı: ${kusurlu}/${KATKILAR.length}`); // 2. Asamada gecirilen sureler. const sureler = {}; for (const k of KATKILAR) { for (let i = 1; i < k.gecmis.length; i++) { const durum = k.gecmis[i - 1][1]; const sure = k.gecmis[i][0] - k.gecmis[i - 1][0]; (sureler[durum] ??= []).push(sure); } } const ortanca = (dizi) => { const s = [...dizi].sort((a, b) => a - b); const o = Math.floor(s.length / 2); return s.length % 2 ? s[o] : (s[o - 1] + s[o]) / 2; }; console.log("\naşama geçiş sayısı ortanca gün en uzun gün toplam gün"); for (const durum of ["oneri", "kesif", "taslak", "inceleme", "kabul", "ertelendi"]) { const d = sureler[durum] ?? []; if (d.length === 0) continue; console.log( `${durum.padEnd(11)} ${String(d.length).padStart(12)} ${String(ortanca(d)).padStart(13)} ` + `${String(Math.max(...d)).padStart(13)} ${String(d.reduce((t, x) => t + x, 0)).padStart(12)}` ); } // 3. Uctan uca sure: yayina ulasan katkilarda oneri -> yayin. const yayinlanan = KATKILAR.filter((k) => k.gecmis.at(-1)[1] === "yayin"); const uctanUca = yayinlanan.map((k) => k.gecmis.at(-1)[0] - k.gecmis[0][0]); console.log("\nkatkı uçtan uca gün"); for (const k of yayinlanan) console.log(`${k.ad.padEnd(23)} ${String(k.gecmis.at(-1)[0]).padStart(14)}`); console.log(`ortanca uçtan uca süre: ${ortanca(uctanUca)} gün`); console.log(`en uzun: ${Math.max(...uctanUca)} gün en kısa: ${Math.min(...uctanUca)} gün`); // 4. Darbogaz: uctan uca surenin hangi asamaya dustugunu pay olarak ver. const toplamSure = Object.values(sureler).flat().reduce((t, x) => t + x, 0); console.log("\naşamanın toplam süredeki payı"); const paylar = Object.entries(sureler) .map(([durum, d]) => [durum, d.reduce((t, x) => t + x, 0)]) .sort((a, b) => b[1] - a[1]); for (const [durum, t] of paylar) { console.log(`${durum.padEnd(11)} ${String(t).padStart(5)} gün %${((t / toplamSure) * 100).toFixed(1)}`); }
geçersiz geçişler ve kapı ihlalleri kart.tiklanabilir geçersiz geçiş: oneri → inceleme tablo.yogunluk inceleme → kabul için eksik onay: erisim kusurlu katkı: 2/7 aşama geçiş sayısı ortanca gün en uzun gün toplam gün oneri 7 4 7 30 kesif 6 5 12 36 taslak 6 7 11 40 inceleme 7 8 29 68 kabul 6 2 5 15 ertelendi 1 57 57 57 katkı uçtan uca gün dugme.genislik 14 acilir-liste.aramali 52 sayi-alani 46 arac-ipucu.belge 80 kart.tiklanabilir 10 tablo.yogunluk 25 ortanca uçtan uca süre: 35.5 gün en uzun: 80 gün en kısa: 10 gün aşamanın toplam süredeki payı inceleme 68 gün %27.6 ertelendi 57 gün %23.2 taslak 40 gün %16.3 kesif 36 gün %14.6 oneri 30 gün %12.2 kabul 15 gün %6.1
İki Kusurun Okunması
Yedi katkının ikisi kusurlu. İki kusur birbirinden farklıdır ve farklı şeyler bozar.
kart.tiklanabilir öneriden doğrudan incelemeye geçmiş; keşif ve taslak atlanmış.
Sonucu, listedeki en kısa uçtan uca süredir: on gün. Atlanan iki aşamanın işi de
yapılmamıştır: kapsam ölçütü işletilmediği için bu değişikliğin sistemin işi olup olmadığı
sorulmamış, taslak yazılmadığı için göç etkisi hesaplanmamıştır. Hızlı görünen bu yol,
maliyeti sonraya taşır.
tablo.yogunluk ise geçişleri doğru yapmış ama erişilebilirlik onayı olmadan kabul
edilmiş. Bu satır ilk dersteki katalog tablosunun bir satırıyla örtüşüyor: tablo
bileşeninin erişilebilirlik incelemesi geçmemiş görünüyordu. İki denetim aynı boşluğu iki
farklı yerden gösteriyor — biri kataloğun durumundan, diğeri katkının geçmişinden.
Kapıların değeri buradadır. Bir inceleme türünün “yapılması beklenen” bir şey olarak yazılması yeterli değildir; geçişin koşulu hâline getirilmedikçe, işler sıkıştığında ilk atlanan o olur.
Sürenin Nereye Gittiği
İkinci tablo aşamaların sürelerini veriyor. İnceleme, hem ortanca (8 gün) hem toplam süre
payı (yüzde 27,6) bakımından en pahalı aşama. Ancak toplam süre payı tek başına yanıltıcı
olabilir: ertelendi durumu yüzde 23,2 pay alıyor, oysa bu payın tamamı tek bir katkıdan
geliyor — arac-ipucu.belge katkısı 57 gün ertelenmiş durumda beklemiş.
Bu ayrım, ortanca ile toplamın neden birlikte okunduğunu gösterir. Toplam, kaynakların
nereye gittiğini söyler; ortanca, tipik bir katkının ne kadar beklediğini. ertelendi
durumunun ortancası da 57’dir, ama tek bir gözlem üzerinden hesaplandığı için bir eğilim
değil, tek bir olaydır.
İnceleme aşamasında da benzer bir yayılım var: ortanca 8 gün, en uzun 29 gün. Yirmi dokuz
günlük bekleme acilir-liste.aramali katkısına ait ve bu, üçüncü tablodaki 52 günlük
uçtan uca sürenin çoğunu tek başına açıklıyor. İnceleme aşamasının ortalaması değil,
kuyruğu sorundur; sürecin iyileştirilmesi ortancayı değil bu uzun kuyruğu hedef almalıdır.
sayi-alani katkısı incelemeden taslağa dönmüş, sonra yeniden incelemeye girmiş. Bu geri
dönüş geçerli bir geçiştir ve akışın çalıştığının işaretidir; incelemenin hiçbir katkıyı
geri döndürmemesi, incelemenin biçimsel hâle geldiğini gösterirdi.
Sürecin Maliyeti ve Katkının Sınıflandırılması
Ortanca uçtan uca süre 35,5 gün. Bu sayı tek başına iyi ya da kötü değildir; bir eşikle karşılaştırıldığında anlam kazanır. Eşik şudur: bir katkının sistemden geçme süresi, kendi kopyasını yazma süresini aştığında ekipler kendi kopyalarını yazar. İsteğe bağlı bir özellik eklemek bir ekibin kendi deposunda yarım gün sürüyorsa, otuz beş günlük bir akış o özelliği sisteme hiç getirmez; sistem, gerçek ihtiyaçları görmez hâle gelir.
Çözüm, kapıları kaldırmak değil, katkıları sınıflandırmaktır. Önceki derste kurulan sınıflandırma burada doğrudan işe yarar:
- Ekleme sınıfı katkılar — isteğe bağlı yeni özellik, değer kümesinin genişlemesi — hiçbir çağrıyı bozmaz. Bunlar için keşif aşaması kısaltılabilir ve tasarım incelemesi ile kod incelemesi birleştirilebilir.
- Kırıcı sınıfı katkılar tam akışı izler; göç maliyeti hesaplanmadan taslak tamamlanmış sayılmaz.
- Yeni bileşen önerileri en uzun akışı izler, çünkü kapsam ölçütü asıl burada işletilir.
Bu üç yolun süreleri ayrı ayrı ölçülürse, “sürecimiz yavaş” cümlesi ölçülebilir bir iddiaya dönüşür: hangi sınıfta, hangi aşamada, kaç gün.
Katkı Verenin Gördüğü
Sürecin bir de dışarıdan görünen yüzü vardır. Katkı veren kişi, katkısının hangi durumda olduğunu ve sıradaki adımın kimde beklediğini görebilmelidir. Durum makinesinin en somut faydası budur: her katkının tek bir durumu vardır ve o durumun sahibi bellidir.
İkinci gereklilik, tamamlanmışlık tanımının yazılı olmasıdır. Taslağın hangi koşullarda incelemeye geçebileceği — belge bölümlerinin yazılmış, göç etkisinin hesaplanmış, örneğin eklenmiş olması — katkı verene önceden söylenmezse, inceleme aşaması bir eksik listesi üretme yerine döner ve kuyruk uzar. İnceleme aşamasının 29 günlük en uzun beklemesi çoğu zaman incelemenin yavaşlığından değil, incelemeye eksik girmiş bir taslaktan doğar.
Özet
- Katkı akışı öneri, keşif, taslak, inceleme, kabul ve yayın durumlarından oluşur; her durumun ayrı bir sorusu ve ayrı bir sahibi vardır.
- Geçişlerin geçerliliği ve kabul kapılarının onayları makineyle denetlenebilir; denetlenmediğinde en çok atlanan aşama, koşula bağlanmamış incelemedir.
- Aşama atlayan bir katkı hızlı görünür ama atlanan aşamanın işi yapılmamıştır; maliyet sonraya taşınır.
- Toplam süre payı kaynakların nereye gittiğini, ortanca tipik bekleme süresini söyler; ikisi birlikte okunmadığında tek bir uzun bekleme eğilim gibi görünür.
- Katkının sistemden geçme süresi kendi kopyasını yazma süresini aştığında sistem gerçek ihtiyaçları görmez olur; çözüm kapıları kaldırmak değil, ekleme ve kırıcı katkılara ayrı yollar tanımlamaktır.
- Tamamlanmışlık tanımı önceden yazılmadığında inceleme aşaması eksik listesi üretme yerine döner ve kuyruk uzar.
Sonraki Adım
Bu dersin durum makinesi bir şeyi sormadı: incelemeyi kim yapar? Üç onayın da tek bir merkezî ekipten gelmesiyle, onayların katkı veren ekiplerin kendi içinden gelmesi farklı sistemler üretir; ikisinin de kuyruk süresi, tutarlılık düzeyi ve ölçekle davranışı farklıdır. Sonraki ders bu soruyu yönetişim modeli olarak ele alır: merkezî, federatif ve karma düzenleri talep ile kapasite üzerinden modelleyip her birinin kuyruk süresini ve ürettiği sapma sayısını iki farklı ölçekte hesaplar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.