Ders 05 / 12
Kendi Kendine Hizmet
Talep kuyruğunun ortadan kaldırılmasının ölçülmesi: aynı istek kümesi bir talep kuyruğunda ve kendi kendine hizmet düzeninde koşturulur, bekleme süresi ile platform ekibinin kesintisi sayılır, arayüz yazma işi, yanlış kullanım ve geri alınamayan işlem bedelleri çıkarılır ve otomatikleştirmenin karşılığını vermediği istek türü adıyla yazılır.
İçindekiler
Dört derste platform bir maliyet hesabı, bir işletme biçimi, bir kapsam ve bir kip seçimi olarak ölçüldü. Dördünde de ortak bir varsayım vardı: bir ekip bir şey istediğinde platform ekibinden biri onu yapıyor. Öntanımlı bir seçeneği değiştirmek, yola girmek, bir yeteneği almak — hepsi bir insanın elinden geçiyordu. O insan bir kuyruğun arkasındadır.
Bu ders kuyruğu ölçer ve kaldırmayı dener. Kendi kendine hizmet, isteği platform ekibinin elinden alıp isteği açan ekibin eline verir. Bunun kazancı bekleme süresi ve kesintidir; bedeli ise arayüzü yazma işi, arayüzün bakımı, yanlış kullanım ve geri alınamayan işlemdir. Sayılar otomatikleştirmenin nerede karşılığını vermediğini de gösterir. Through-line bölgesel ölçüm ağı ve onun beş ekibidir; ağ da ekipler de kurgudur.
Talep Kuyruğu
PY25 — on iki istek türü vardır; her tür yılda kaç kez geldiğiyle, elle yapılışının kaç saat sürdüğüyle ve değişkenliğiyle yazılır. Değişkenlik sıfırsa istek her seferinde birebir aynıdır, bire yakınsa her seferinde farklıdır. Gerekçe: bir isteğin otomatikleştirilebilirliği sıklığından değil, seferden sefere ne kadar değiştiğinden gelir; iki sayı ayrılmadan eşik çıkmaz.
PY26 — talep kuyruğunda istek platform ekibine gider; ekip günde 4 saatini isteklere ayırır ve sırayla işler. Her istek elle işinin üstüne 0,25 saat kesinti getirir. Gerekçe: elle yapılan işin bedeli yalnız o işin süresi değildir; ekip başka bir işten çıkıp isteğe döner ve geri döndüğü işi yeniden kurar. Pencere üç yıl, yıl 250 iş günü, gün 8 saattir.
// kuyruk.mjs — ayni istek kumesi bir talep kuyrugunda kosturulur (model) import { writeFileSync } from "node:fs"; // PY25 — on iki istek turu: ad, yilda kac kez geldigi, elle yapilisinin isi (saat) ve // degiskenlik (0 = her seferinde birebir ayni, 1 = her seferinde farkli). Sayilar kurgudur. const TUR = [ ["hat degiskeni degistirme", 150, 0.3, 0.05], ["yetki verme", 120, 0.4, 0.05], ["gizli deger ekleme", 90, 0.5, 0.05], ["yeni ortam acma", 40, 3, 0.10], ["gosterge panosu ekleme", 30, 2, 0.30], ["veri tabani kopyasi", 24, 4, 0.20], ["alan adi baglama", 20, 1.5, 0.15], ["yeni servis iskeleti", 18, 6, 0.25], ["denetim kaydi cikarma", 12, 2.5, 0.40], ["yedekten geri donme", 6, 8, 0.60], ["kume surum yukseltme", 4, 20, 0.50], ["bolge tasima", 3, 40, 0.90], ].map(([ad, yilda, saat, degisken]) => ({ ad, yilda, saat, degisken })); // PY26 — talep kuyrugu: istek platform ekibine gider, ekip gunde 4 saatini isteklere ayirir // ve sirayla isler. Her istek elle isinin ustune 0.25 saat kesinti getirir: ekip baska bir // isten cikip istege doner. Pencere uc yil, yil 250 is gunu, gun 8 saattir. const GUNLUK = 4, YIL = 250, PENCERE = 3, KESINTI = 0.25, SAAT = 8; function kuyruk(pay) { const gelis = TUR.flatMap((t, i) => { const n = t.yilda * PENCERE, is = t.saat * (pay ? pay(t) : 1); return Array.from({ length: n }, (_, j) => ({ tur: i, gun: (j + 0.5) * YIL * PENCERE / n, is: is + KESINTI })); }).sort((a, b) => a.gun - b.gun); let bos = 0, toplam = 0; for (const g of gelis) { bos = Math.max(bos, g.gun * GUNLUK) + g.is; g.bekleme = bos / GUNLUK - g.gun; toplam += g.is; } const b = gelis.map((g) => g.bekleme).sort((x, y) => x - y); return { gelis, sayi: gelis.length, toplam, ort: b.reduce((x, y) => x + y, 0) / b.length, ortanca: b[b.length >> 1], enUzun: b.at(-1), doluluk: toplam / (YIL * PENCERE * GUNLUK) }; } const K = kuyruk(null); writeFileSync("kuyruk.json", JSON.stringify({ TUR, temel: { ort: K.ort, ortanca: K.ortanca, enUzun: K.enUzun, toplam: K.toplam, sayi: K.sayi } })); console.log("tur".padEnd(26) + "yilda".padStart(6) + "saat".padStart(6) + "degisken".padStart(10) + "3 yilda istek".padStart(14) + "elle is (gun)".padStart(14) + "ort. bekleme (gun)".padStart(20)); for (let i = 0; i < TUR.length; i++) { const g = K.gelis.filter((x) => x.tur === i); console.log(TUR[i].ad.padEnd(26) + `${TUR[i].yilda}`.padStart(6) + `${TUR[i].saat}`.padStart(6) + `${TUR[i].degisken.toFixed(2)}`.padStart(10) + `${g.length}`.padStart(14) + `${(g.length * TUR[i].saat / SAAT).toFixed(1)}`.padStart(14) + `${(g.reduce((t, x) => t + x.bekleme, 0) / g.length).toFixed(1)}`.padStart(20)); } const kesinti = K.sayi * KESINTI / SAAT; console.log(`\nuc yilda ${K.sayi} istek, ${(K.toplam / SAAT).toFixed(1)} is gunu ` + `(bunun ${kesinti.toFixed(1)} is gunu yalniz kesinti), doluluk %` + `${(100 * K.doluluk).toFixed(1)}`); console.log(`bekleme: ortalama ${K.ort.toFixed(1)} gun, ortanca ${K.ortanca.toFixed(1)} gun, ` + `en uzun ${K.enUzun.toFixed(1)} gun`);
tur yilda saat degisken 3 yilda istek elle is (gun) ort. bekleme (gun) hat degiskeni degistirme 150 0.3 0.05 450 16.9 4.8 yetki verme 120 0.4 0.05 360 18.0 4.7 gizli deger ekleme 90 0.5 0.05 270 16.9 4.7 yeni ortam acma 40 3 0.10 120 45.0 5.3 gosterge panosu ekleme 30 2 0.30 90 22.5 5.0 veri tabani kopyasi 24 4 0.20 72 36.0 5.6 alan adi baglama 20 1.5 0.15 60 11.3 4.5 yeni servis iskeleti 18 6 0.25 54 40.5 5.7 denetim kaydi cikarma 12 2.5 0.40 36 11.3 4.4 yedekten geri donme 6 8 0.60 18 18.0 7.4 kume surum yukseltme 4 20 0.50 12 30.0 8.4 bolge tasima 3 40 0.90 9 45.0 11.1 uc yilda 1551 istek, 359.7 is gunu (bunun 48.5 is gunu yalniz kesinti), doluluk %95.9 bekleme: ortalama 5.0 gun, ortanca 4.5 gun, en uzun 13.0 gun
Kuyruk üç yılda 1551 istek görür ve 359,7 iş günü harcar. Bunun 48,5 iş günü hiçbir isteği ilerletmez: yalnız bağlam değiştirme bedeli, harcanan işin %13,5’i. Doluluk %95,9’dur ve bu oran beklemenin neden bu kadar uzun olduğunu açıklar: ortalama bekleme 5 gün, en uzunu 13 gün.
Bekleme türlere eşit dağılmaz. Bir hat değişkeni değişikliği ortalama 4,8 gün, kırk saatlik bir bölge taşıma 11,1 gün bekler; küçük işler büyük olanların arkasında bekler. Ortancanın (4,5) ortalamanın (5,0) altında kalması bunu gösterir — birkaç uzun iş dağılımı yukarı çeker.
Kendi Kendine Hizmetin Bedeli
PY27 — bir tür için arayüz yazma işi 4 + 20 × değişkenlik iş günüdür, yıllık bakımı bu işin beşte biridir ve arayüz isteklerin ancak (1 − değişkenlik) kadarını karşılar; kalanı yine elle yapılır. Gerekçe: her seferinde farklı olan bir isteği bir arayüzün arkasına almak, o isteğin ancak değişmeyen kısmını alır.
PY28 — kendi kendine hizmette isteklerin 0,02 + 0,10 × değişkenlik kadarı yanlış kullanılır; bunların %85’i geri alınabilir (0,5 iş günü düzeltme), %15’i geri alınamaz (6 iş günü kurtarma). Gerekçe: arayüzün arkasındaki işlemi yapan kişi o işi ilk kez yapıyordur ve kimse omzunun üstünden bakmamaktadır. PY29 — bir tür için arayüz, üç yıllık penceredeki toplamı elle düzenin toplamını aşmazsa kendini öder. PY30 — karma düzen yalnız kendini ödeyen türler için arayüz yazar; geri kalanlar ve otomatikleştirilenin elle kalan payı kuyrukta durur.
// hizmet.mjs — kendi kendine hizmetin bedeli, tur basina esik ve karma duzende kuyruk import { readFileSync } from "node:fs"; const { TUR, temel } = JSON.parse(readFileSync("kuyruk.json", "utf8")); // PY27 — bir tur icin arayuz yazma isi 4 + 20 x degiskenlik is gunudur, yillik bakim bu isin // beste biridir ve arayuz isteklerin ancak (1 - degiskenlik) kadarini karsilar; kalani yine // elle yapilir. PY28 — kendi kendine hizmette isteklerin 0.02 + 0.10 x degiskenlik kadari // yanlis kullanilir; bunlarin %85'i geri alinabilir (0.5 is gunu duzeltme), %15'i geri // alinamaz (6 is gunu kurtarma). PY29 — bir tur icin arayuz, uc yillik penceredeki toplami // elle duzenin toplamini asmazsa kendini oder. const GUNLUK = 4, YIL = 250, PENCERE = 3, KESINTI = 0.25, SAAT = 8; const GERI_ALINABILIR = 0.5, GERI_ALINAMAZ = 6; const hesap = TUR.map((t) => { const n = t.yilda * PENCERE, elle = n * (t.saat + KESINTI) / SAAT; const arayuz = 4 + 20 * t.degisken, bakim = PENCERE * arayuz / 5; const yanlis = n * (0.02 + 0.10 * t.degisken); const zarar = yanlis * 0.85 * GERI_ALINABILIR + yanlis * 0.15 * GERI_ALINAMAZ; const kendi = arayuz + bakim + t.degisken * elle + zarar; return { ...t, n, elle, arayuz, bakim, yanlis, zarar, kendi, fark: elle - kendi }; }); console.log("tur".padEnd(26) + "elle".padStart(7) + "arayuz".padStart(8) + "bakim".padStart(7) + "kalan elle".padStart(12) + "yanlis".padStart(8) + "geri alinamaz".padStart(15) + "zarar".padStart(7) + "kendi".padStart(7) + "fark".padStart(7)); for (const h of hesap) console.log(h.ad.padEnd(26) + h.elle.toFixed(1).padStart(7) + h.arayuz.toFixed(1).padStart(8) + h.bakim.toFixed(1).padStart(7) + (h.degisken * h.elle).toFixed(1).padStart(12) + h.yanlis.toFixed(1).padStart(8) + (h.yanlis * 0.15).toFixed(2).padStart(15) + h.zarar.toFixed(1).padStart(7) + h.kendi.toFixed(1).padStart(7) + ((h.fark >= 0 ? "+" : "") + h.fark.toFixed(1)).padStart(7)); const oden = hesap.filter((h) => h.fark > 0), odemez = hesap.filter((h) => h.fark <= 0); console.log(`\nkendini odeyen tur: ${oden.length} / ${TUR.length}, ` + `toplam kazanc ${oden.reduce((t, h) => t + h.fark, 0).toFixed(1)} is gunu`); console.log("odemeyenler — " + odemez.map((h) => `${h.ad} (${h.fark.toFixed(1)})`).join(", ")); // PY30 — karma duzen: yalniz kendini odeyen turler icin arayuz yazilir, geri kalanlar ve // otomatiklestirilenin elle kalan payi kuyrukta durur. Kuyruk yeniden kosturulur. const kuyruk = (pay) => { const gelis = TUR.flatMap((t, i) => { const n = Math.round(t.yilda * PENCERE * pay(hesap[i])); return Array.from({ length: n }, (_, j) => ({ gun: (j + 0.5) * YIL * PENCERE / n, is: t.saat + KESINTI })); }).sort((a, b) => a.gun - b.gun); let bos = 0, toplam = 0; for (const g of gelis) { bos = Math.max(bos, g.gun * GUNLUK) + g.is; g.bekleme = bos / GUNLUK - g.gun; toplam += g.is; } const b = gelis.map((g) => g.bekleme).sort((x, y) => x - y); return { sayi: gelis.length, gun: toplam / SAAT, ort: b.reduce((x, y) => x + y, 0) / b.length, enUzun: b.at(-1), doluluk: toplam / (YIL * PENCERE * GUNLUK) }; }; const K2 = kuyruk((h) => (h.fark > 0 ? h.degisken : 1)); const K3 = kuyruk((h) => h.degisken); console.log("\n" + "duzen".padEnd(30) + "kuyruga giren".padStart(14) + "elle is".padStart(9) + "doluluk".padStart(9) + "ort. bekleme".padStart(14) + "en uzun".padStart(9)); console.log("talep kuyrugu (hepsi elle)".padEnd(30) + `${temel.sayi}`.padStart(14) + (temel.toplam / SAAT).toFixed(1).padStart(9) + `%${(100 * temel.toplam / (YIL * PENCERE * GUNLUK)).toFixed(1)}`.padStart(9) + temel.ort.toFixed(1).padStart(14) + temel.enUzun.toFixed(1).padStart(9)); for (const [ad, K] of [["karma (6 turde arayuz)", K2], ["hepsinde arayuz", K3]]) console.log(ad.padEnd(30) + `${K.sayi}`.padStart(14) + K.gun.toFixed(1).padStart(9) + `%${(100 * K.doluluk).toFixed(1)}`.padStart(9) + K.ort.toFixed(1).padStart(14) + K.enUzun.toFixed(1).padStart(9)); const arayuzIsi = (H) => H.reduce((t, h) => t + h.arayuz + h.bakim + h.zarar, 0); console.log(`\narayuz + bakim + zarar: karma duzende ${arayuzIsi(oden).toFixed(1)}, ` + `hepsinde ${arayuzIsi(hesap).toFixed(1)} is gunu`);
tur elle arayuz bakim kalan elle yanlis geri alinamaz zarar kendi fark hat degiskeni degistirme 30.9 5.0 3.0 1.5 11.3 1.69 14.9 24.5 +6.5 yetki verme 29.3 5.0 3.0 1.5 9.0 1.35 11.9 21.4 +7.9 gizli deger ekleme 25.3 5.0 3.0 1.3 6.8 1.01 8.9 18.2 +7.1 yeni ortam acma 48.8 6.0 3.6 4.9 3.6 0.54 4.8 19.2 +29.5 gosterge panosu ekleme 25.3 10.0 6.0 7.6 4.5 0.67 6.0 29.6 -4.2 veri tabani kopyasi 38.3 8.0 4.8 7.7 2.9 0.43 3.8 24.3 +14.0 alan adi baglama 13.1 7.0 4.2 2.0 2.1 0.32 2.8 16.0 -2.8 yeni servis iskeleti 42.2 9.0 5.4 10.5 2.4 0.36 3.2 28.2 +14.0 denetim kaydi cikarma 12.4 12.0 7.2 5.0 2.2 0.32 2.9 27.0 -14.6 yedekten geri donme 18.6 16.0 9.6 11.1 1.4 0.22 1.9 38.6 -20.1 kume surum yukseltme 30.4 14.0 8.4 15.2 0.8 0.13 1.1 38.7 -8.3 bolge tasima 45.3 22.0 13.2 40.8 1.0 0.15 1.3 77.3 -32.0 kendini odeyen tur: 6 / 12, toplam kazanc 79.0 is gunu odemeyenler — gosterge panosu ekleme (-4.2), alan adi baglama (-2.8), denetim kaydi cikarma (-14.6), yedekten geri donme (-20.1), kume surum yukseltme (-8.3), bolge tasima (-32.0) duzen kuyruga giren elle is doluluk ort. bekleme en uzun talep kuyrugu (hepsi elle) 1551 359.7 %95.9 5.0 13.0 karma (6 turde arayuz) 320 172.6 %46.0 2.1 10.3 hepsinde arayuz 170 108.8 %29.0 2.3 10.1 arayuz + bakim + zarar: karma duzende 108.4, hepsinde 253.9 is gunu
Otomatikleştirmenin Karşılığını Vermediği Yer
On iki türün altısı kendini öder ve toplam kazanç 79 iş günüdür. Altısı ödemez ve listenin
sonu dersin adını koyduğu durumdur: bolge tasima — yılda üç kez gelen, her seferinde farklı
olan istek. Elle yapılması üç yılda 45,3 iş günü tutar; arayüzün arkasına alınması 77,3 iş
günü, yani 32 iş günü daha fazla. Hesap üç kalemden çıkar: arayüz 22 iş günü, üç yıllık bakım
13,2 iş günü ve — asıl olan — arayüz işin ancak onda birini karşıladığı için 40,8 iş günü elle iş
yerinde kalır. Aynı biçim yedekten geri donme ve kume surum yukseltme türlerinde tekrarlanır.
İkinci bir bedel tablonun ortasındadır. hat degiskeni degistirme türünde arayüz kendini öder ama
kazancı yalnız 6,5 iş günüdür; oysa üç yılda 11,3 yanlış kullanım doğar ve bunların 1,69’u
geri alınamaz — toplam 14,9 iş günlük zarar, arayüz ve bakım işinin toplamından (8 iş günü) daha
büyüktür. En sık gelen istek, arayüzün en çok yanlış kullanıldığı istektir, çünkü yanlış
kullanım sayısı sıklıkla çarpılır. Elle düzende bu kalem hiç yoktu: bir insan işlemi yapmadan önce
bakıyordu.
Son tablo kuyruğun ne olduğunu gösterir. Karma düzende kuyruğa giren istek 1551’den 320’ye, elle iş 359,7’den 172,6 iş gününe, doluluk %95,9’dan %46’ya iner; ortalama bekleme 5,0 günden 2,1 güne düşer. Altı türü otomatikleştirmek, kuyrukta kalan altı türün beklemesini de kısaltır — kuyruk boşaldığı için.
Hepsini otomatikleştirmek buradan öteye gitmez. Kuyruğa giren istek 170’e, elle iş 108,8 iş gününe iner ama ortalama bekleme 2,3 güne çıkar: kuyrukta kalan artık yalnız uzun ve değişken iştir ve tek bir bölge taşıma sırayı günlerce kapatır. Bunun için ödenen arayüz, bakım ve zarar toplamı 253,9 iş günü, karma düzenin 108,4 iş gününün iki katından fazladır. Kuyruğun tamamını kaldırmak, kuyruğu kısaltmaktan 145 iş günü pahalı ve beklemede karşılıksızdır.
Özet
- On iki istek türü üç yıllık pencerede kuyruğa girdi: 1551 istek, 359,7 iş günü elle iş, bunun 48,5 iş günü (%13,5) yalnız kesinti; doluluk %95,9, ortalama bekleme 5,0 gün, en uzun 13,0 gün.
- Bekleme türlere eşit dağılmaz: hat değişkeni değiştirme 4,8 gün, bölge taşıma 11,1 gün bekler; ortanca (4,5) ortalamanın (5,0) altındadır.
- On iki türün altısı kendini öder ve 79 iş günü kazandırır; altısı ödemez.
- Otomatikleştirmenin karşılığını vermediği tür
bolge tasimadır: yılda üç kez, her seferinde farklı. Elle 45,3 iş günü, arayüzle 77,3 iş günü — 32 iş günü kayıp, çünkü 40,8 iş günü elle iş yerinde kalır. - Kendi kendine hizmetin ikinci bedeli yanlış kullanımdır:
hat degiskeni degistirmetüründe üç yılda 11,3 yanlış kullanım, 1,69’u geri alınamaz, toplam 14,9 iş günü — arayüz ve bakımın toplamından büyük. - Karma düzende kuyruğa giren istek 1551’den 320’ye, doluluk %95,9’dan %46’ya, ortalama bekleme 5,0’dan 2,1 güne iner. Hepsini otomatikleştirmek beklemeyi 2,3 güne çıkarır ve 145 iş günü daha pahalıdır.
Sonraki Adım
Bu beş derste platform bir yaklaşım olarak tanımlandı ve sınırları çizildi: hangi ekip sayısından sonra kendini ödediği, iki işletme biçiminin benimseme ve ölü yetenek sayıları, yolun kapsamı ve dışında kalanın kaybı, zorunluluğun üç kipi, kuyruğun bedeli ve kendi kendine hizmetin nerede karşılığını vermediği. Hepsi platformun nasıl işletileceğine dair sayılardı.
Söylenmemiş olan şey ne sunduğudur. Beş derste “yetenek”, “kalem”, “istek türü” adları geçti ama hiçbiri açılmadı: ortamın istek üzerine nasıl geldiği, iskeletin neyi üretip neyi üretmediği, kataloğun sahipliği nasıl tuttuğu, politikanın hatta nasıl gömüldüğü, maliyetin nasıl bölüştürüldüğü, göçün nasıl yürüdüğü ve platformun etkisinin hangi ölçütle sayıldığı. Sonraki konu bu yetenekleri tek tek açar ve her birini aynı ölçüyle — gizlenen katman, geri sızan kısım, dışına çıkanlar — sayar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.