Mert Özen Her Satırda Daha İleri
Proje Yönetimi Kanban — #06

Kanban'da Aktif Yönetim ve İyileştirme: Blocker, Aging ve Flow Review

Mert Özen 8 Kas 2026 12 dk 2 görüntülenme
Kanban'da Aktif Yönetim ve İyileştirme: Blocker, Aging ve Flow Review

Flow'u aktif yönetmek; board'u her gün sağdan sola ve en yaşlı item'dan başlayarak okumak, blocked işi eskale etmek, expedite'i sınırlamak ve bottleneck'i veriyle bulmaktır. Bookstore verisinden CFD bantlarını C# ile hesaplıyor, Code Review'ın Temmuz'da nasıl darboğaz olduğunu, Theory of Constraints adımlarıyla nasıl çözüldüğünü (p85 16 günden 11 güne) ve sıradaki constraint'in deploy ritmi olduğunu görüyoruz.

Sürüm notu: Bu yazı The Kanban Guide'ın 2025.5 sürümünü esas alır; Kanban Method cadence'leri için Kanban University kaynaklarına bakılmıştır. Analiz kodu .NET 10 ile 04. yazıdaki Bookstore board verisi üzerinde çalıştırılmıştır.

Önce Tahmin Et

Temmuz 2026, Bookstore ekibi. Code Review kolonunda ortalama altı PR (pull request) bekliyor, bazıları bir haftadır. Geliştiriciler şikâyetçi: "Review bekliyorum, o yüzden yeni bir iş aldım." Tester şikâyetçi: "Bana iş gelmiyor, sonra perşembe bir anda beş iş geliyor." Ürün sahibi şikâyetçi: "Küçük bir bug bile iki hafta sürüyor."

Ekibin önünde üç seçenek var. Birincisi, review'ları hızlandırmak için ekibe bir senior geliştirici daha almak. İkincisi, "her geliştirici günde en az iki PR review eder" diye bir kural koymak. Üçüncüsü, In Dev kolonuna sıkı bir WIP (Work in Progress) limit'i koyup Code Review kolonuna da bir limit eklemek, yani geliştiricilerin yeni iş başlatmasını yavaşlatmak. Hangisi cycle time'ı en çok kısaltır? Bir de şunu düşün: Code Review'ı çözdüğünde, bir sonraki bekleme nerede ortaya çıkacak?

Günlük Flow Toplantısı: Sağdan Sola, En Yaşlıdan Başla

The Kanban Guide belirli bir toplantı tanımlamaz; aktif item'ların düzenli olarak gözden geçirilmesini ister ve bunun sürekli, belirli aralıklarla ya da ikisi birden yapılabileceğini söyler. Çoğu ekip bunu her sabah 15 dakikalık bir board toplantısıyla yapar. Scrum ekibiysen bu senin Daily Scrum'ındır; Scrum serisinin Daily Scrum yazısında anlatıldığı gibi o toplantı zaten bir status raporu değil, bir plan toplantısıdır.

Flow odaklı bir günlük toplantının iki kuralı var. Birincisi board'u sağdan sola oku: önce Ready to Deploy, sonra Test, Code Review, en son In Dev. Sağdaki iş bitmeye en yakın olandır; onu bitirmek, soldaki yeni bir işi ilerletmekten daha çok value üretir. İkincisi en yaşlı item'dan başla: 04. yazıdaki aging chart'ta en üstteki nokta, gündemin ilk maddesidir.

Bu toplantıda sorulacak sorular kişiye değil işe yönelik:

  • Bitmeye en yakın item hangisi ve onu bugün bitirmek için ne gerekiyor?
  • Yaşı SLE'ye (Service Level Expectation) yaklaşan ya da onu geçmiş item var mı? Onu ilerletmek için kim yardım edebilir?
  • Blocked item var mı? Engeli kim, ne zamana kadar kaldıracak?
  • Bir kolonun WIP limit'i dolu mu? Doluysa, yeni iş çekmek yerine o kolona kim yardım edecek?
  • Board'da görünmeyen bir iş yapan var mı?

"Dün ne yaptın, bugün ne yapacaksın?" sorusu her kişiyi meşgul gösterir ama hiçbir item'ı ilerletmez. "En yaşlı item'ımızı bugün nasıl ilerletiriz?" sorusu ise ekibi işin etrafında toplar.

Blocked Item'lar: Etiket, Sebep, Süre

Kanban Guide aktif yönetim pratiğinin içinde tıkanan işi açmayı da sayar. 02. yazıdaki Bookstore policy'si basitti: blocked item kolonundan çıkmaz, etiket ve sebep alır, WIP'e sayılmaya devam eder. Bunun üzerine iki alışkanlık ekle.

Birincisi blocked süresini ölç. Bookstore'un CSV'sinde (Comma-Separated Values) BlockedDays kolonu bu yüzden var. Altı ayda hangi sebeplerin kaç gün blokaj ürettiğini toplamak, ekibin en sık hangi dış bağımlılığa takıldığını gösterir. Bookstore'da bunun en tanıdık örneği ödeme sağlayıcısının test ortamı.

İkincisi bir eskalasyon eşiği koy. BS-1205, ödeme sağlayıcısının test ortamını beklediği için 12 gün blocked kaldı ve 19 günlük yaşıyla SLE'yi çoktan geçti. Ekip bu item için iki şey yapabilirdi: blocked etiketinin üçüncü gününde konuyu takım liderine ve sağlayıcıyla ilişkiyi yöneten kişiye taşımak, ya da item'ı bölüp sağlayıcıya bağımlı olmayan kısmını (fallback ekranı, log'lama) ayrı bir item olarak production'a çıkarmak. Blocked item'ı beklerken yapılacak en kötü şey, onun yerine sessizce yeni bir iş başlatmaktır.

Expedite Policy'si ve Bedeli

Destek ağırlıklı bir ekipte bazı işler sırayı beklemez: "checkout'ta kartla ödeme çalışmıyor" gibi. Kanban Method bu tür işler için class of service fikrini kullanır; en bilinen sınıflar expedite, fixed date, standard ve intangible'dır. Expedite, işin diğer her şeyin önüne geçtiği sınıftır.

Expedite'in bir bedeli var: o işe ayrılan her saat, board'daki diğer işlerin beklemesi demek. Bu yüzden Bookstore policy'si expedite şeridini aynı anda tek item'la sınırladı ve toplam WIP'e dahil etti. Ama veriye bakınca ilginç bir şey çıktı. Aşağıdaki kodun son bölümü, başlığı "Urgent" ile başlayan item'ların cycle time'ını listeliyor: 10 item, 6 ile 14 gün arası. Yani expedite yalnız Ready'de sıranın başına geçmek anlamına geliyordu; item sonra herkes gibi Code Review kuyruğunda, ardından salı ya da perşembe deploy'unda bekliyordu. Ekip bunu görünce expedite policy'sini değiştirdi: expedite item review'a aynı gün alınır, gerekiyorsa deploy günü beklenmeden hotfix olarak çıkar. Policy'nin yazılı olması, onun ölçülüp düzeltilebilmesini sağladı.

Bottleneck'i Bulmak: CFD'yi Hesaplamak

04. yazıda CFD'nin (Cumulative Flow Diagram) bantlarının her state'teki item sayısını gösterdiğini söyledik. Grafiği çizmeden de aynı bilgiyi hesaplayabiliriz: her gün için her state'te kaç item durduğunu sayıp ay bazında ortalamasını almak, CFD'deki bant kalınlıklarının sayısal hâlidir. 04. yazıdaki WorkItem tiplerini kullanan FlowReview projesi:

using System.Globalization;
using Bookstore.Flow;

CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;

List<WorkItem> items = BoardCsv.Load("board-history.csv");
string[] active = ["InDev", "CodeReview", "Test", "ReadyToDeploy"];

// CFD'nin bir günlük kesiti: o gün her state'te kaç item duruyor?
int InState(string state, DateOnly day) => items.Count(i =>
{
    if (!i.Entered.TryGetValue(state, out DateOnly entered) || entered > day)
        return false;
    int next = BoardCsv.States.IndexOf(state) + 1;
    return !i.Entered.TryGetValue(BoardCsv.States[next], out DateOnly left) || left > day;
});

Console.WriteLine("Month    | avg items per state (CFD band width)              | median days in CodeReview");
Console.WriteLine("         | InDev  CodeReview  Test  ReadyToDeploy  total WIP |");
for (int month = 5; month <= 10; month++)
{
    DateOnly first = new(2026, month, 1);
    DateOnly[] days = [.. Enumerable.Range(0, DateTime.DaysInMonth(2026, month)).Select(d => first.AddDays(d))];
    double[] bands = [.. active.Select(s => days.Average(d => InState(s, d)))];

    List<int> reviewDays = [.. items
        .Where(i => i.Entered.TryGetValue("Test", out DateOnly t) && t.Month == month)
        .Select(i => i.Entered["Test"].DayNumber - i.Entered["CodeReview"].DayNumber)
        .Order()];

    Console.WriteLine($"{first:yyyy-MM}  | {bands[0],5:F1}  {bands[1],10:F1}  {bands[2],4:F1}  {bands[3],13:F1}  {bands.Sum(),9:F1} | " +
        $"{reviewDays[reviewDays.Count / 2],3} d (n = {reviewDays.Count})");
}

// Değişikliğin etkisi: başlangıç tarihine göre iki dönem
Console.WriteLine();
Console.WriteLine("Started            | finished n | cycle time p50 / p85 | median days in CodeReview / ReadyToDeploy");
PrintPeriod("Jun 1 - Aug 31", new(2026, 6, 1), new(2026, 8, 31));
PrintPeriod("Sep 7 - Oct 30", new(2026, 9, 7), new(2026, 10, 30));

// Expedite edilen işler gerçekten hızlı mı geçti?
List<int> urgent = [.. items.Where(i => i.Title.StartsWith("Urgent") && i.Finished is not null)
    .Select(i => i.CycleTimeDays!.Value).Order()];
Console.WriteLine();
Console.WriteLine($"Urgent items: n = {urgent.Count}, cycle times = [{string.Join(", ", urgent)}] d");

void PrintPeriod(string label, DateOnly from, DateOnly to)
{
    List<WorkItem> done = [.. items.Where(i => i.Started >= from && i.Started <= to && i.Finished is not null)];
    List<int> ct = [.. done.Select(i => i.CycleTimeDays!.Value).Order()];
    int Median(string state, string next) => done
        .Select(i => i.Entered[next].DayNumber - i.Entered[state].DayNumber)
        .Order().ElementAt(done.Count / 2);

    Console.WriteLine($"{label,-18} | {done.Count,10} | {Stats.Percentile(ct, 50),8} / {Stats.Percentile(ct, 85),2} d    | " +
        $"{Median("CodeReview", "Test"),5} d / {Median("ReadyToDeploy", "Done")} d");
}

Gerçek çıktı:

Month    | avg items per state (CFD band width)              | median days in CodeReview
         | InDev  CodeReview  Test  ReadyToDeploy  total WIP |
2026-05  |   3.0         2.6   1.3            1.5        8.4 |   3 d (n = 23)
2026-06  |   4.5         4.2   1.6            3.3       13.6 |   4 d (n = 35)
2026-07  |   2.9         5.8   1.8            2.8       13.4 |   5 d (n = 39)
2026-08  |   3.1         4.8   1.4            3.2       12.5 |   5 d (n = 30)
2026-09  |   3.4         2.4   1.8            2.9       10.6 |   1 d (n = 37)
2026-10  |   3.8         1.6   1.8            2.4        9.5 |   1 d (n = 34)

Started            | finished n | cycle time p50 / p85 | median days in CodeReview / ReadyToDeploy
Jun 1 - Aug 31     |        105 |       12 / 16 d    |     5 d / 2 d
Sep 7 - Oct 30     |         51 |        8 / 11 d    |     1 d / 2 d

Urgent items: n = 10, cycle times = [6, 6, 7, 8, 8, 9, 9, 9, 13, 14] d

Tablonun ilk kısmı hikâyeyi anlatıyor. Code Review bandı Mayıs'ta ortalama 2,6 item'dan Temmuz'da 5,8 item'a kalınlaşıyor ve bir PR'ın Code Review'da geçirdiği medyan süre 3 günden 5 güne çıkıyor. Aynı dönemde In Dev bandı incelmiyor; geliştiriciler review beklerken yeni iş başlatıyor, toplam WIP 8,4'ten 13,6'ya çıkıyor. Bu, 03. yazıdaki simülasyonun gerçek hayattaki karşılığı: throughput aynı kalırken WIP büyüyor ve Little's Law cycle time'ı büyümeye zorluyor.

Theory of Constraints'e Kısa Giriş

Eliyahu Goldratt'ın 1984 tarihli "The Goal" romanıyla yaygınlaşan Theory of Constraints'in temel fikri şudur: bir sistemin çıktısını, sistemdeki tek bir darboğaz, yani constraint belirler. Constraint dışındaki bir adımı hızlandırmak sistemi hızlandırmaz; yalnız constraint'in önündeki kuyruğu büyütür. Goldratt bunun için beş adımlık bir süreç önerir: constraint'i bul, onu sonuna kadar kullan, diğer her şeyi ona tabi kıl, gerekirse kapasitesini artır ve constraint yer değiştirdiğinde baştan başla.

Bookstore ekibi Eylül'de bu adımları neredeyse kelimesi kelimesine uyguladı. Constraint'i buldu: CFD'de kalınlaşan bant Code Review'dı. Onu sonuna kadar kullandı: "yeni iş başlatmadan önce bekleyen bir PR'ı review et" policy'si, Code Review'ı geliştiricilerin boş zaman işi olmaktan çıkardı. Diğer her şeyi ona tabi kıldı: In Dev'e 5, Code Review'a 3 WIP limit'i koydu; Code Review doluysa kimse yeni iş başlatmıyor. Kapasitesini artırdı: büyük feature'larda pairing'e geçti, yani iki kişinin birlikte yazdığı kod review kuyruğuna hiç girmeden ilk göz incelemesinden geçmiş oluyor. Yeni bir senior geliştirici almadı.

Baştaki üç seçeneğe dönersek: yeni bir kişi almak constraint'e kapasite eklerdi ama aylar sürerdi ve WIP'i sınırlamazsan yeni kişi de yeni iş başlatırdı. "Günde iki review" kuralı bir hedef koyar ama review'u yeni iş başlatmaktan önceye koymaz. Üçüncü seçenek, WIP limit'leri, constraint'i doğrudan besler: In Dev'e limit koymak, geliştiricinin boşta kalan zamanını Code Review'a yönlendirir.

Tablonun ikinci kısmı sonucu gösteriyor. Haziran–Ağustos arasında başlayan 105 item'ın p50 cycle time'ı 12 gün, p85'i 16 gün; Eylül 7 sonrası başlayan 51 item'da 8 ve 11 gün. Code Review'da geçen medyan süre 5 günden 1 güne indi. Burada bir dikkat notu: ikinci dönem daha kısa ve Ekim sonunda başlamış ama henüz bitmemiş item'lar hesapta yok, bu da sayıyı biraz iyimser gösterir. Yine de fark, bu yanlılığın açıklayamayacağı kadar büyük.

Beşinci adım, baştan başlamak. Code Review çözülünce sıradaki constraint görünür hâle geldi: Ready to Deploy bandı Eylül–Ekim'de hâlâ 2,4–2,9 item ve bir item orada medyan 2 gün bekliyor. Bu bekleme haftada iki deploy kararının doğrudan sonucu. Ekibin bir sonraki iyileştirmesi bir board kuralı değil, bir mühendislik yatırımı: deploy'u her gün yapılabilir hâle getirmek. Bunun nasıl yapılacağı, CI (Continuous Integration) ve CD (Continuous Delivery) pratiklerini anlatan CI/CD Temelleri serisinin ve Deployment Stratejileri serisinin konusu.

02. yazıda Code Review kolonunu "Waiting for Review" ve "In Review" diye ikiye bölmenin ne zaman mantıklı olduğunu sormuştuk. Cevap bu analizde: bekleme ile işin ayrı ayrı ölçülmesi gerektiğinde. Haziran'da kolonu bölseydin bandın kalınlaşmasının review'ın uzun sürmesinden değil, review'un başlamamasından geldiğini doğrudan görürdün. Eylül'den sonra medyan 1 güne inince bölmenin getirisi azaldı; ekip kolonu tek bıraktı.

Replenishment ve Kanban Method Cadence'leri

Aktif yönetimin board dışındaki ritimleri de var. Replenishment, Ready kolonunun ne zaman ve neyle doldurulacağının kararıdır. Bookstore ekibi bunu her pazartesi ürün sahibiyle 20 dakikalık bir toplantıda yapıyor ve Ready'yi en fazla 8 item'la sınırlıyor; Ready'nin kendisi de bir queue olduğu için sınırsız bırakılırsa orada bekleyen işler eskir ve öncelikler bayatlar.

Kanban Method bu ritimleri cadence adıyla daha ayrıntılı tarif eder. Anderson'ın çevresinde yaygınlaşan set yedi cadence'tan oluşur: günlük Kanban meeting, Replenishment meeting, Delivery Planning meeting, Service Delivery Review, Operations Review, Risk Review ve Strategy Review. Bunlardan Service Delivery Review ekibe özellikle uygun: birkaç haftada bir müşteri tarafıyla birlikte, ekibin SLE'yi ne kadar tuttuğunu, flow metric'lerini ve bekleyen talepleri konuşmak.

Kanban Guide bu toplantıların hiçbirini zorunlu tutmaz. 2025.5 sürümü DoW'un (Definition of Workflow) zaman zaman gözden geçirilmesini ister ve bunun için resmî, tekrar eden bir toplantıyı beklemek gerekmediğini söyler. Yani Guide'a göre iyileştirme bir toplantının değil, sürekli bir pratiğin işidir; cadence'ler ise o pratiği organizasyona yerleştirmenin bir yoludur.

Üretimde Dikkat

Değişikliği tarihle kaydet. Bookstore ekibi WIP limit'lerini 7 Eylül'de değiştirdi ve bu tarihi biliyor; analizdeki iki dönemi bu tarihe göre ayırabildi. Board'a, DoW'a ya da ekibe yapılan her değişikliği bir satırla not etmek, birkaç ay sonra "neden iyileşti?" sorusuna cevap vermeni sağlar.

Tek değişken değiştir. Eylül'de ekip WIP limit'lerini, review önceliğini ve pairing'i aynı anda değiştirdi; sonuç iyi ama hangisinin ne kadar katkı verdiğini bu veriden ayıramayız. İyileştirmeler küçük ve ardışık olduğunda etkileri ayrı ayrı okunabilir.

Bottleneck'i çözünce kutlamayı kısa tut. Constraint yer değiştirir; Bookstore'da Code Review'dan deploy ritmine geçti. Bir sonraki darboğazı aramayı bırakmak, sistemin yeniden yavaşlamasının en kısa yoludur.

Sık Düşülen Tuzaklar

İlk tuzak iyileştirmeyi yalnız retro'ya bırakmak. İki haftada bir yapılan bir retro, Code Review'da biriken altı PR'ı fark etmek için çok geç kalır. Guide'ın iyileştirme pratiği resmî bir toplantıyı beklememeyi söyler; günlük toplantıda "bu kolon üç gündür dolu, policy'mizi değiştirelim mi?" sorusunu sormak da iyileştirmedir.

İkinci tuzak metric'i kişi değerlendirmesinde kullanmak. "En çok item bitiren geliştirici" ya da "en düşük cycle time'lı geliştirici" sıralaması, insanları başkasının PR'ını review etmek yerine kendi işini bitirmeye iter; bu yazıda çözdüğümüz bottleneck'i tam olarak yeniden yaratır. Flow metric'leri sistemin sağlığını ölçer.

Üçüncüsü expedite'i yaygınlaştırmak. Her hafta yarım düzine "acil" iş geliyorsa, bunların çoğu acil değil, yalnız yüksek sesle istenmiştir. Expedite sınırı dolduğunda yeni gelen acil işin kimin onayıyla girebileceğini policy'ye yaz.

Dördüncüsü yanlış yeri hızlandırmak. Haziran'da ekibe bir geliştirici daha eklenseydi daha çok iş başlayacak, Code Review kuyruğu daha da büyüyecekti. Constraint dışındaki kapasite artışı, constraint'in önündeki kuyruğu besler.

Küçük Bir Deneme

★☆☆ Kendi board'unda yarın sabahki toplantıyı sağdan sola ve en yaşlı item'dan başlayarak yönet. Toplantının süresi ve konuşulan konular ne kadar değişti?

★★☆ Veri Code Review'u bekleme ve iş diye ayırmıyor. FlowReview programına, Code Review'da 1 iş gününden uzun kalan item'ların ay bazında oranını ekle. Ekip 02. yazıdaki "en fazla 1 iş günü" policy'sini Eylül'den sonra ne kadar tuttu?

★★★ Expedite item'larını ayrı bir DoW gibi düşün: kendi started/finished noktaları ve kendi SLE'si olsun. Bookstore verisindeki "Urgent" item'larından bir SLE hesapla ve "expedite item'ların %85'i 2 gün içinde production'da" hedefine ulaşmak için hangi policy'lerin değişmesi gerektiğini yaz.

Seri boyunca Kanban'ı Scrum'dan ayrı bir ekip üzerinden anlattık. Son yazıda ikisini birleştiriyoruz: Corey Ladas'ın Scrumban'ını, Kanban Guide for Scrum Teams'in Sprint event'lerine flow metric'lerini nasıl eklediğini ve hangi ekip için hangi seçimin mantıklı olduğunu konuşacağız.