İçeriğe geç
academia.sh

Ders 05 / 10

Mühendislik Pratikleri

Hata bulma gecikmesinin ölçülmesi: kusurun doğduğu adım ile bulunduğu adım arası kaç adım ve kaç saat, tümleştirme sıklığı iki saatten kırk saate ve eşli çalışma oranı sıfırdan bire tarandığında bu gecikme, yeniden iş ve eşli çalışmanın iki kişilik maliyeti dahil toplam iş gücü nasıl değişir.

İçindekiler

Önceki dört ders bir sayıyı hep varsayım olarak aldı: kusur bulunduğunda geri dönülür. Kaç kalemin geri döndüğü ve kaça mal olduğu sayıldı, ama kusurun ne zaman bulunduğu her seferinde sürecin biçiminden okundu. Bu ders konuyu kapatırken o sayıyı doğrudan ölçer: hata bulma gecikmesi, yani kusurun doğduğu adım ile bulunduğu adım arasındaki mesafe.

Mesafe iki ayrı birimde ölçülür ve ikisi aynı şeyi söylemez. Adım cinsinden gecikme kusurun kaç aşama sonra göründüğünü, saat cinsinden gecikme o aşamaların ne kadar sürdüğünü verir. İki pratik bu iki birime ayrı ayrı dokunur: tümleştirme sıklığı saati kısaltır, eşli çalışma adımı. Teslimat hattının mekaniği bu müfredatta başka yerde koşturulduğu için burada hat bir periyottan ibarettir. Through-line bölgesel kütüphane ağıdır ve kurgudur.

Kusur Nerede Bulunuyor

Aşağıdaki blok bir modeldir, ölçüm değil.

SM25 — kırk sekiz iş kalemi bir üreteçle türetilir, üreteç kendi yazılır ve tohum görünürdür. Her kalemin bir boyutu (3–12 saat) ve dokunduğu bir modül vardır; aynı küme bütün ayarlarda kullanılır. Sekiz geliştirici çalışır.

SM26 — kusurun en erken görülebileceği adım bir sınıf olarak girdidir. Yol beş adımdır: yazım, yerel, tümleşim, sürüm, işletim. Yazım sınıfı kusur, ikinci bir çift göz varsa yazılırken görünür; yoksa tümleşime kadar gizli kalır. Tümleşim sınıfı ancak başkalarının işiyle birleşince, sürüm sınıfı sürüm sınamasında, işletim sınıfı yalnız işletimde görünür. Sürüm sınaması kırk saatte bir, işletim penceresi seksen saatte bir açılır.

SM27 — eşli çalışılan kalemde yazım sınıfı kusur yerinde düzeltilir ve ayrı bir iş kalemi olmaz. Bu, eşli çalışmanın modeldeki tek kazancıdır.

SM28 — her tümleştirme olayı sabit 0,5 saat tutar, üstüne aynı partide tümleşen her kalem çifti için 0,06 saat çakışma bedeli eklenir. Seyrek tümleştirmenin bedeli buradan gelir: parti büyüdükçe çift sayısı karesel artar.

Yeniden iş, kalemin üçte biri artı kusurun doğuşu ile bulunuşu arasında aynı modülde tamamlanmış her kalem için bir saattir.

// pratik.mjs — hata bulma gecikmesi (model); tumlestirme sikligi ve esli calisma orani taranir
import { writeFileSync } from "node:fs";

const KISI = 8;            // gelistirici sayisi
const SURUM = 40;          // surum sinamasi bu saatte bir kosar
const ISLETIM = 80;        // isletim penceresi
const SABIT = 0.5;         // her tumlestirme olayinin sabit maliyeti (saat)
const CAKISMA = 0.06;      // ayni partide tumlesen her kalem cifti icin cakisma maliyeti (saat)
const ADIM = ["yazim", "yerel", "tumlesim", "surum", "isletim"];

// SM25: uretec kendi yazilir, tohum gorunur; ayni kalem kumesi butun ayarlarda kullanilir.
let tohum = 20260127;
const rast = () => (tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648;
const MODUL = ["odunc", "ucret", "uyelik", "katalog", "sube", "kimlik"];
const KALEM = [...Array(48)].map((no) => {
  const boyut = 3 + Math.floor(rast() * 10);              // 3-12 saat
  const m = MODUL[Math.floor(rast() * MODUL.length)];
  const r = rast();
  // SM26: kusurun en erken gorulebilecegi adim sinifi girdidir
  const sinif = r < 0.55 ? null : r < 0.76 ? "yazim" : r < 0.90 ? "tumlesim" : r < 0.96 ? "surum" : "isletim";
  return { no, boyut, modul: m, sinif };
});

const sonraki = (t, p) => Math.ceil((t + 1e-9) / p) * p;   // bir sonraki periyodik olay

function kostur(T, oran) {
  const bos = Array(KISI).fill(0);
  const kalem = KALEM.map((k, i) => ({ ...k, esli: i % 4 < Math.round(oran * 4) }));
  let isGucu = 0;
  for (const k of kalem) {
    const kac = k.esli ? 2 : 1;
    const sec = bos.map((t, i) => [t, i]).sort((a, b) => a[0] - b[0]).slice(0, kac);
    const bas = Math.max(...sec.map(([t]) => t));
    for (const [, i] of sec) bos[i] = bas + k.boyut;
    k.bit = bas + k.boyut;
    isGucu += k.boyut * kac;
  }
  // SM27: esli calisilan kalemde yazim sinifi kusur ayni anda gorulur; digerleri periyodu bekler
  const bulgu = [];
  for (const k of kalem) {
    if (!k.sinif) continue;
    const [adim, an] =
      k.sinif === "yazim" && k.esli ? [0, k.bit]
      : k.sinif === "surum" ? [3, sonraki(k.bit, SURUM)]
      : k.sinif === "isletim" ? [4, sonraki(k.bit, ISLETIM)]
      : [2, sonraki(k.bit, T)];
    const ustune = kalem.filter((x) => x.modul === k.modul && x.bit > k.bit && x.bit <= an).length;
    // yazarken yakalanan kusur yerinde duzeltilir, ayri bir is kalemi olmaz
    bulgu.push({ no: k.no, sinif: k.sinif, adim, gecikmeSaat: an - k.bit,
                 yeniden: adim === 0 ? 0 : Math.ceil(k.boyut / 3) + ustune });
  }
  const yeniden = bulgu.reduce((a, b) => a + b.yeniden, 0);
  // SM28: her tumlestirme olayi sabit bir bedel, ustune partideki kalem cifti kadar cakisma odetir
  const son = Math.max(...kalem.map((k) => k.bit));
  let olay = 0, cakisma = 0;
  for (let t = T; t <= sonraki(son, T); t += T) {
    const parti = kalem.filter((k) => k.bit > t - T && k.bit <= t).length;
    if (parti === 0) continue;
    olay += 1; cakisma += (CAKISMA * parti * (parti - 1)) / 2;
  }
  const tumlesimBedeli = +(olay * SABIT + cakisma).toFixed(1);
  const ort = (f) => bulgu.reduce((a, b) => a + f(b), 0) / bulgu.length;
  return { T, oran, sure: son, bulgular: bulgu, bulgu: bulgu.length, olay, cakisma: +cakisma.toFixed(1),
    gecikmeAdim: ort((b) => b.adim), gecikmeSaat: ort((b) => b.gecikmeSaat),
    esliBulunan: bulgu.filter((b) => b.adim === 0).length,
    yeniden, tumlesimBedeli, isGucu,
    toplam: +(isGucu + yeniden + tumlesimBedeli).toFixed(1) };
}

const cikar = ({ bulgular, ...r }) => r;
const SIKLIK = [2, 4, 8, 16, 40].map((T) => kostur(T, 0));
const ORAN = [0, 0.25, 0.5, 0.75, 1].map((o) => kostur(4, o));
writeFileSync("pratik.json", JSON.stringify({ SIKLIK: SIKLIK.map(cikar), ORAN: ORAN.map(cikar) }));

console.log(`is kalemi: ${KALEM.length}, temel is: ${KALEM.reduce((a, k) => a + k.boyut, 0)} saat, ` +
  `gelistirici: ${KISI} (tohum ${20260127})`);
console.log(`kusur sinifi: ${["yazim", "tumlesim", "surum", "isletim"]
  .map((s) => `${s} ${KALEM.filter((k) => k.sinif === s).length}`).join(", ")}; ` +
  `kusursuz ${KALEM.filter((k) => !k.sinif).length}`);
console.log(`adimlar: ${ADIM.map((a, i) => `${i} ${a}`).join(", ")}`);

const temel = SIKLIK[1];
console.log(`\ntumlestirme 4 saatte bir, esli calisma yok: kusur nerede bulunuyor`);
console.log(`${"kusur sinifi".padEnd(14)}${"adet".padStart(6)}${"bulundugu adim".padStart(16)}` +
  `${"gecikme (adim)".padStart(16)}${"gecikme (saat)".padStart(16)}${"yeniden is".padStart(12)}`);
for (const s of ["yazim", "tumlesim", "surum", "isletim"]) {
  const g = temel.bulgular.filter((b) => b.sinif === s);
  const o = (f) => (g.reduce((a, b) => a + f(b), 0) / g.length).toFixed(1);
  console.log(`${s.padEnd(14)}${String(g.length).padStart(6)}${ADIM[g[0].adim].padStart(16)}` +
    `${o((b) => b.adim).padStart(16)}${o((b) => b.gecikmeSaat).padStart(16)}` +
    `${String(g.reduce((a, b) => a + b.yeniden, 0)).padStart(12)}`);
}
is kalemi: 48, temel is: 354 saat, gelistirici: 8 (tohum 20260127)
kusur sinifi: yazim 14, tumlesim 5, surum 2, isletim 2; kusursuz 25
adimlar: 0 yazim, 1 yerel, 2 tumlesim, 3 surum, 4 isletim

tumlestirme 4 saatte bir, esli calisma yok: kusur nerede bulunuyor
kusur sinifi    adet  bulundugu adim  gecikme (adim)  gecikme (saat)  yeniden is
yazim             14        tumlesim             2.0             2.1          45
tumlesim           5        tumlesim             2.0             3.4          16
surum              2           surum             3.0            20.5          15
isletim            2         isletim             4.0            56.5          13

Tablo hata bulma gecikmesinin neden iki birimde ölçülmesi gerektiğini gösterir. Yazım sınıfı on dört kusur, eşli çalışma olmadığında iki adım sonra ve ortalama 2,1 saat sonra bulunur; bunlar yerinde düzeltilebilecekken tümleşimi beklerler. Karşı uçta yalnız iki işletim kusuru vardır ama gecikmeleri 56,5 saattir ve on üç saatlik yeniden iş üretirler — kusur başına 6,5 saat, yazım sınıfının iki katı. Az sayıda ama geç bulunan kusur, çok sayıda ve erken bulunan kusurdan pahalıdır.

İki Ayarın Taranması

// gecikme-taramasi.mjs — pratik.mjs'in yazdigi sonuclari okur; iki ayar ayri ayri taranir
import { readFileSync } from "node:fs";

const { SIKLIK, ORAN } = JSON.parse(readFileSync("pratik.json", "utf8"));
const SABIT = 0.5;
const tablo = (baslik, satir, ust) => {
  const yaz = (h) => console.log(h.map((c, i) => String(c).padStart(baslik[i][1])).join(""));
  if (ust) { console.log(); console.log(ust); }
  yaz(baslik.map((b) => b[0])); satir.forEach(yaz);
};

tablo([["tumlestirme", 13], ["olay", 6], ["gecikme (adim)", 16], ["gecikme (saat)", 16],
       ["yeniden is", 12], ["tumlesim bedeli", 17], ["toplam", 9]],
  SIKLIK.map((r) => [`${r.T} saat`, r.olay, r.gecikmeAdim.toFixed(2), r.gecikmeSaat.toFixed(1),
                     r.yeniden, r.tumlesimBedeli, r.toplam]),
  "tumlestirme sikligi (esli calisma yok):");

// SM29: siklastirmanin tek bedeli olay basina sabit maliyettir; basa bas noktasi asagida.
const a = SIKLIK[0], b = SIKLIK[1];
const basaBas = (b.yeniden + b.cakisma - a.yeniden - a.cakisma) / (a.olay - b.olay);
console.log(`\niki saatlik ritim ${a.olay} olay, dort saatlik ${b.olay} olay uretir; ` +
  `olay basina sabit maliyet ${SABIT} saatken iki saatlik ritim ${(b.toplam - a.toplam).toFixed(1)} saat one gecer.`);
console.log(`bu ustunluk olay basina sabit maliyet ${basaBas.toFixed(2)} saati asinca kaybolur.`);

tablo([["esli oran", 11], ["sure (saat)", 13], ["yazarken bulunan", 18], ["gecikme (adim)", 16],
       ["gecikme (saat)", 16], ["yeniden is", 12], ["is gucu", 9], ["toplam", 9]],
  ORAN.map((r) => [`%${(100 * r.oran).toFixed(0)}`, r.sure, `${r.esliBulunan}/${r.bulgu}`,
                   r.gecikmeAdim.toFixed(2), r.gecikmeSaat.toFixed(1), r.yeniden, r.isGucu, r.toplam]),
  "esli calisma orani (tumlestirme 4 saatte bir):");

// SM30: esli calismanin iki kisilik maliyeti kazanci asiyorsa, hangi carpanda basa bas gelir
const y = ORAN[0], z = ORAN[ORAN.length - 1];
const carpan = (z.isGucu - y.isGucu) / (y.yeniden - z.yeniden);
console.log(`\nesli calisma %100'de gecikmeyi ${y.gecikmeSaat.toFixed(1)} saatten ` +
  `${z.gecikmeSaat.toFixed(1)} saate, yeniden isi ${y.yeniden} saatten ${z.yeniden} saate indirir; ` +
  `karsiliginda is gucu ${y.isGucu} saatten ${z.isGucu} saate cikar ve is ${z.sure - y.sure} saat uzar.`);
console.log(`kusur basina yeniden is ${(y.yeniden / y.bulgu).toFixed(1)} saattir; ` +
  `esli calismanin karsiligini vermesi icin bu sayinin ${carpan.toFixed(1)} katina cikmasi gerekir.`);
tumlestirme sikligi (esli calisma yok):
  tumlestirme  olay  gecikme (adim)  gecikme (saat)  yeniden is  tumlesim bedeli   toplam
       2 saat    21            2.26             8.0          82             13.3    449.3
       4 saat    13            2.26             8.7          89             12.3    455.3
       8 saat     7            2.26            10.0          94             13.6    461.6
      16 saat     4            2.26            13.4         103             22.9    479.9
      40 saat     2            2.26            21.4         132             53.6    539.6

iki saatlik ritim 21 olay, dort saatlik 13 olay uretir; olay basina sabit maliyet 0.5 saatken iki saatlik ritim 6.0 saat one gecer.
bu ustunluk olay basina sabit maliyet 1.25 saati asinca kaybolur.

esli calisma orani (tumlestirme 4 saatte bir):
  esli oran  sure (saat)  yazarken bulunan  gecikme (adim)  gecikme (saat)  yeniden is  is gucu   toplam
         %0           50              0/23            2.26             8.7          89      354    455.3
        %25           62              4/23            1.91             7.8          69      443    523.8
        %50           73              7/23            1.65             6.3          59      530    601.9
        %75           85              9/23            1.48             5.3          50      615    677.5
       %100           90             14/23            1.04             4.7          35      708    755.8

esli calisma %100'de gecikmeyi 8.7 saatten 4.7 saate, yeniden isi 89 saatten 35 saate indirir; karsiliginda is gucu 354 saatten 708 saate cikar ve is 40 saat uzar.
kusur basina yeniden is 3.9 saattir; esli calismanin karsiligini vermesi icin bu sayinin 6.6 katina cikmasi gerekir.

İki Pratik, İki Ayrı Bileşen

İlk tablonun en dikkat çekici sütunu değişmeyendir. Tümleştirme iki saatten kırk saate seyrekleşse de adım cinsinden gecikme 2,26’da sabit kalır: kusur yine aynı adımda bulunur, yalnız o adıma varmak uzar. Saat cinsinden gecikme 8,0’dan 21,4’e, yeniden iş 82’den 132 saate çıkar. Kırk saatlik ritimde tümleşim bedeli de 13,3’ten 53,6 saate fırlar, çünkü tek partide tümleşen kalem sayısı arttıkça çakışma çifti karesel büyür. Tümleştirmeyi sıklaştırmak bu modelde hiçbir yerde kaybettirmez; iki saatlik ritim dört saatliğe göre 6,0 saat öndedir ve bu üstünlük ancak olay başına sabit maliyet 1,25 saati aşarsa kaybolur. Ölçülmesi gereken sayı budur: bir tümleştirme olayı ne kadar sürüyor.

İkinci tablo tam tersini yapar. Eşli çalışma adım cinsinden gecikmeye dokunur — 2,26’dan 1,04’e iner, çünkü on dört yazım kusurunun on dördü sıfırıncı adımda yakalanır ve hiç yeniden iş üretmez. Yeniden iş 89 saatten 35 saate düşer. Bedeli ise başka hiçbir ayarda görülmeyen büyüklüktedir: iş gücü 354 saatten 708 saate çıkar, çünkü aynı işi iki kişi yapar, ve iş kırk saat uzar, çünkü sekiz kişi yarısı kadar kalemi aynı anda yürütür.

Aritmetik açıktır. 354 saatlik ek iş gücü 54 saatlik yeniden iş tasarrufu satın alır. Eşli çalışmanın bu modelde karşılığını vermesi için kusur başına yeniden işin 3,9 saatten 6,6 katına çıkması gerekir. Bu çarpan hayalî değildir: işletim sınıfı kusurlar zaten kusur başına 6,5 saatte seyreder ve bir kusurun işletime kaçması hâlinde yeniden iş bu modeldekinin çok üstüne çıkar. Yani eşli çalışma, kusurun ucuz olduğu yerde pahalı bir alışkanlık, kusurun pahalı olduğu yerde ucuz bir sigortadır — ve hangisinin geçerli olduğu ölçülebilir bir sorudur.

Özet

  • Hata bulma gecikmesi iki birimde ölçüldü: adım cinsinden gecikme kusurun kaç aşama sonra göründüğünü, saat cinsinden gecikme o aşamaların ne kadar sürdüğünü verir.
  • Dört saatlik tümleştirmede 14 yazım kusuru 2 adım ve 2,1 saat sonra bulunur; 2 işletim kusuru 4 adım ve 56,5 saat sonra bulunur ve kusur başına 6,5 saatle en pahalı yeniden işi üretir.
  • Tümleştirme sıklığı adım sayısını hiç değiştirmez (2,26’da sabit), saati değiştirir: 2 saatten 40 saate çıkınca gecikme 8,0’dan 21,4 saate, yeniden iş 82’den 132 saate, tümleşim bedeli 13,3’ten 53,6 saate çıkar.
  • Sıklaştırmanın tek bedeli olay başına sabit maliyettir; 2 saatlik ritmin üstünlüğü ancak bu maliyet 1,25 saati aşarsa kaybolur.
  • Eşli çalışma adım cinsinden gecikmeyi 2,26’dan 1,04’e, yeniden işi 89’dan 35 saate indirir, ama iş gücünü 354’ten 708 saate çıkarır ve işi 40 saat uzatır; başa baş için kusur başına yeniden işin 6,6 katına çıkması gerekir.

Sonraki Adım

Beş ders sürecin biçimini seçti, akışı sınırladı, eşgüdüm bedelini saydı ve hata bulma gecikmesini kısalttı. Hepsinin ortak bir kör noktası var. Bütün bu ölçümler işin kimden kime geçtiğini veri olarak aldı: yaşam döngüsü modelinde adım sınırı, yinelemede biriktirme listesinin sahibi, akış modelinde iş sınırının kapsadığı ekip, ölçekli düzende modüllerin hangi ekibe düştüğü. Her seferinde o sınır girdiydi ve hiç sorgulanmadı. Oysa o sınır bir yerden geliyor: ekipler bir biçimde bölünmüş, modüller bir biçimde paylaştırılmış ve iş kaleminin geçtiği her sınır aslında bir ekip sınırıdır. Sonraki konu bu soruyu sorar — ekiplerin nasıl bölündüğü mimariyi ne kadar belirliyor ve iletişim yapısı ile modül yapısı örtüşmediğinde bu beş derste sayılan bekleme, yeniden iş ve eşgüdüm turu ne kadar büyüyor.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat