İçeriğe geç
academia.sh

Ders 19 / 24

İlerleme ve Geri Bildirim

İlerleme göstergesinin kalan işi doğru bildirip bildirmediğinin hesaplanması, tamamlama oranını yükselten yanıltmanın ayırt edilmesi ve geri bildirim gecikmesinin gösterge sınıflarına bağlanması.

İçindekiler

Önceki ders arayüzün kullanıcıya başkaları hakkında verdiği bilgiyi ele aldı. Arayüzün verdiği bir bilgi türü daha var ve doğrudan kullanıcının kendisiyle ilgili: akışın neresinde olduğu, ne kadar yol aldığı, ne kadar kaldığı.

Bu bilgi kullanıcının tek bir kararını besler: devam etmek mi, çıkmak mı? Karar her adım sonunda yeniden verilir ve kullanıcının elindeki tek girdi, kalan işin ne kadar olduğuna dair tahminidir. Bu ders o tahmini ölçer, göstergenin tahmini nasıl değiştirdiğini hesaplar ve tamamlama oranını yükselten bir göstergenin ne zaman bilgi ne zaman yanıltma olduğunu ayırır.

Adım Sayısı Zamanı Ölçmez

Ödünç alma akışı altı adımdan oluşuyor ama adımlar eşit uzunlukta değil. Kayıt ayrıntısını açmak 0.8 saniye, nüsha seçimi 5.1 saniye sürüyor. Bir ilerleme çubuğu iki farklı biçimde doldurulabilir: adım sayısına göre (altı adımın üçü bitti, yüzde 50) ya da süreye göre (harcanan sürenin toplam süreye oranı).

Aşağıdaki hesap iki çubuğun kalan süre tahminini karşılaştırıyor, sonra üç bin kullanıcının devam etme kararını benzetiyor.

// ilerleme.mjs — ilerleme gostergesinin dogrulugu ve terk uzerindeki etkisi

function uretec(tohum) {
  let s = tohum >>> 0;
  return () => { s = (s * 1664525 + 1013904223) >>> 0; return s / 4294967296; };
}

// Odunc alma akisinin alti adimi ve gercek sureleri (sn).
const ADIMLAR = [
  ["arama", 1.2], ["sonuc listesi", 3.4], ["kayit ayrinti", 0.8],
  ["nusha secimi", 5.1], ["onay", 1.0], ["makbuz", 2.2],
];
const SURELER = ADIMLAR.map(([, d]) => d);
const TOPLAM = SURELER.reduce((a, b) => a + b, 0);
const gecen = SURELER.map((_, i) => SURELER.slice(0, i + 1).reduce((a, b) => a + b, 0));

// Iki gosterge: adim sayisina gore ilerleyen cubuk, sureye gore agirliklandirilmis cubuk.
const adimCubugu = (i) => (i + 1) / ADIMLAR.length;
const sureCubugu = (i) => gecen[i] / TOPLAM;

console.log("adim            sure  gecen  adim cubugu  sure cubugu  kalan (gercek)  adim cub. tahmini  sure cub. tahmini");
let adimHata = 0, sureHata = 0;
for (let i = 0; i < ADIMLAR.length - 1; i++) {
  const kalan = TOPLAM - gecen[i];
  const tA = gecen[i] * (1 - adimCubugu(i)) / adimCubugu(i);
  const tS = gecen[i] * (1 - sureCubugu(i)) / sureCubugu(i);
  adimHata += Math.abs(tA - kalan) / kalan;
  sureHata += Math.abs(tS - kalan) / kalan;
  console.log(
    `${ADIMLAR[i][0].padEnd(15)} ${SURELER[i].toFixed(1).padStart(4)} ${gecen[i].toFixed(1).padStart(6)}` +
    ` ${(adimCubugu(i) * 100).toFixed(0).padStart(10)} % ${(sureCubugu(i) * 100).toFixed(0).padStart(11)} %` +
    ` ${kalan.toFixed(1).padStart(15)} ${tA.toFixed(1).padStart(18)} ${tS.toFixed(1).padStart(18)}`
  );
}
const n = ADIMLAR.length - 1;
console.log(`ortalama bagil hata: adim cubugu ${(adimHata / n * 100).toFixed(1)} %, sure cubugu ${(sureHata / n * 100).toFixed(1)} %`);

// Terk karari: kullanici her adim sonunda kalan sureyi tahmin eder ve sabriyla karsilastirir.
// Dogru karar, GERCEK kalan sure sabri asmiyorsa devam etmektir.
const KISI = 3000;
const BELIRSIZLIK = 2.2;   // gosterge yokken kullanicinin kotumser carpani

function karar(gosterge) {
  const rnd = uretec(20260714);
  let tamamlayan = 0, gereksizTerk = 0, gereksizDevam = 0;
  for (let k = 0; k < KISI; k++) {
    const sabir = 5 + rnd() * 40;   // kabul edilen kalan sure (sn)
    let cikti = false;
    for (let i = 0; i < ADIMLAR.length - 1; i++) {
      const gercekKalan = TOPLAM - gecen[i];
      const dogruDevam = gercekKalan <= sabir;
      let tahmin;
      if (gosterge === "yok") tahmin = gecen[i] * BELIRSIZLIK;
      else if (gosterge === "adim cubugu") tahmin = gecen[i] * (1 - adimCubugu(i)) / adimCubugu(i);
      else tahmin = gecen[i] * (1 - sureCubugu(i)) / sureCubugu(i);
      const devam = tahmin <= sabir;
      if (devam && !dogruDevam) gereksizDevam++;
      if (!devam && dogruDevam) gereksizTerk++;
      if (!devam) { cikti = true; break; }
    }
    if (!cikti) tamamlayan++;
  }
  return { oran: (tamamlayan / KISI) * 100, gereksizTerk, gereksizDevam };
}

console.log("\ngosterge        tamamlama  gereksiz terk  gereksiz devam  yanlis karar");
for (const g of ["yok", "adim cubugu", "sure cubugu"]) {
  const t = karar(g);
  console.log(
    `${g.padEnd(15)} ${(t.oran.toFixed(1) + " %").padStart(9)} ${String(t.gereksizTerk).padStart(14)}` +
    ` ${String(t.gereksizDevam).padStart(15)} ${String(t.gereksizTerk + t.gereksizDevam).padStart(13)}`
  );
}
console.log(`(${KISI} kullanici, akisin gercek toplam suresi ${TOPLAM.toFixed(1)} sn)`);

// Geri bildirim gecikmesi siniflari ve her sinifin gerektirdigi gosterge
const ISLEMLER = [
  ["arama alanina yazma", 0.04], ["suzgec uygulama", 0.18], ["kayit acma", 0.7],
  ["nusha durumu sorgusu", 2.4], ["odunc kaydi olusturma", 6.5], ["makbuz uretimi", 14.0],
];
const sinif = (t) => t <= 0.1 ? "anlik" : t <= 1.0 ? "akis korunur" : t <= 10 ? "dikkat dagilir" : "dikkat kopar";
const gerekli = (t) => t <= 0.1 ? "gosterge gerekmez" : t <= 1.0 ? "durum degisimi yeter"
  : t <= 10 ? "belirsiz bekleme gostergesi" : "belirli ilerleme + kalan sure";
console.log("\nislem                     sure     sinif           gereken geri bildirim");
for (const [ad, t] of ISLEMLER) {
  console.log(`${ad.padEnd(25)} ${(t.toFixed(2) + " sn").padStart(8)}  ${sinif(t).padEnd(15)} ${gerekli(t)}`);
}

// Yapay gecikme: gosterilen ilerleme ile gercek is arasindaki bag
console.log("\ngosterilen ilerleme ile gercek is arasindaki iliski");
const gercekIs = [0.10, 0.25, 0.45, 0.70, 0.88, 1.00];
const durumlar = {
  "gercege bagli": gercekIs,
  "sabit hizli (yapay)": [0.17, 0.33, 0.50, 0.67, 0.83, 1.00],
  "sona takilan": [0.30, 0.60, 0.85, 0.93, 0.96, 1.00],
};
for (const [ad, g] of Object.entries(durumlar)) {
  let enBuyukSapma = 0, toplam = 0;
  for (let i = 0; i < g.length; i++) {
    const s = Math.abs(g[i] - gercekIs[i]);
    toplam += s;
    if (s > enBuyukSapma) enBuyukSapma = s;
  }
  console.log(`${ad.padEnd(22)} ortalama sapma ${(toplam / g.length * 100).toFixed(1)} puan, en buyuk sapma ${(enBuyukSapma * 100).toFixed(1)} puan`);
}
adim            sure  gecen  adim cubugu  sure cubugu  kalan (gercek)  adim cub. tahmini  sure cub. tahmini
arama            1.2    1.2         17 %           9 %            12.5                6.0               12.5
sonuc listesi    3.4    4.6         33 %          34 %             9.1                9.2                9.1
kayit ayrinti    0.8    5.4         50 %          39 %             8.3                5.4                8.3
nusha secimi     5.1   10.5         67 %          77 %             3.2                5.3                3.2
onay             1.0   11.5         83 %          84 %             2.2                2.3                2.2
ortalama bagil hata: adim cubugu 31.3 %, sure cubugu 0.0 %

gosterge        tamamlama  gereksiz terk  gereksiz devam  yanlis karar
yok                48.7 %           1226             558          1784
adim cubugu        89.2 %             11             476           487
sure cubugu        81.4 %              0               0             0
(3000 kullanici, akisin gercek toplam suresi 13.7 sn)

islem                     sure     sinif           gereken geri bildirim
arama alanina yazma        0.04 sn  anlik           gosterge gerekmez
suzgec uygulama            0.18 sn  akis korunur    durum degisimi yeter
kayit acma                 0.70 sn  akis korunur    durum degisimi yeter
nusha durumu sorgusu       2.40 sn  dikkat dagilir  belirsiz bekleme gostergesi
odunc kaydi olusturma      6.50 sn  dikkat dagilir  belirsiz bekleme gostergesi
makbuz uretimi            14.00 sn  dikkat kopar    belirli ilerleme + kalan sure

gosterilen ilerleme ile gercek is arasindaki iliski
gercege bagli          ortalama sapma 0.0 puan, en buyuk sapma 0.0 puan
sabit hizli (yapay)    ortalama sapma 4.7 puan, en buyuk sapma 8.0 puan
sona takilan           ortalama sapma 21.0 puan, en buyuk sapma 40.0 puan

Adım Çubuğunun Hatası Yönlüdür

İlk tabloda iki çubuk ilk adımda birbirinden ayrılıyor. Arama bittiğinde adım çubuğu yüzde 17, süre çubuğu yüzde 9 gösteriyor. Kalan gerçek süre 12.5 saniye. Adım çubuğuna bakan kullanıcı 6.0 saniye tahmin ediyor — gerçeğin yarısından az. Süre çubuğu 12.5 saniye veriyor.

Ortalama bağıl hata adım çubuğunda yüzde 31.3, süre çubuğunda yüzde 0. İkinci sayı bir başarı değil, tanım gereği doğrudur: süre çubuğu zaten harcanan sürenin oranını gösteriyor, dolayısıyla ondan türetilen tahmin gerçek kalan süreyi verir. Anlamlı olan birinci sayıdır.

Adım çubuğunun hatası rastgele de değil. Uzun adım henüz gelmemişken çubuk iyimser (6.0 yerine 12.5), uzun adım geçtikten sonra kötümser (5.3 yerine 3.2) tahmin ürettiriyor. Yani kullanıcı akışın başında kalan işi olduğundan az sanıyor.

Tamamlama Oranı Yanlış Ölçüttür

İkinci tablo bu dersin ağırlık merkezidir. Gösterge yokken tamamlama oranı yüzde 48.7; adım çubuğuyla yüzde 89.2; süre çubuğuyla yüzde 81.4.

Tamamlama oranına bakan biri adım çubuğunu seçer. Yanındaki üç sütun bu seçimin ne olduğunu söylüyor. Süre çubuğunda yanlış karar sayısı sıfır: hiçbir kullanıcı, devam etmeyi tercih edeceği bir akıştan çıkmıyor ve hiçbiri katlanmayacağı bir akışta kalmıyor. Adım çubuğunda 476 kullanıcı gereksiz devam ediyor — kalan işi olduğundan az sandıkları için, sabırlarının üzerinde bir akışı sürdürüyorlar.

Adım çubuğunun tamamlama oranını yüzde 81.4’ten 89.2’ye çıkarması, yedi buçuk puanlık bir kazanç gibi görünüyor. Kazancın kaynağı, kullanıcının kalan işi yanlış tahmin etmesidir. Bu, Varsayılanların Gücü dersindeki pişmanlık oranıyla aynı yapıdır: gösterge tablosundaki sayı yükseliyor, yükselişin tamamı yanılmadan geliyor.

Gösterge olmayan durum ise ayrı bir kayıp türü gösteriyor: 1226 gereksiz terk. Bunlar, kalan iş sabırlarının altında olmasına rağmen belirsizlik yüzünden çıkan kullanıcılar. Bu, ilerleme göstergesinin asıl gerekçesidir — gösterge, kullanıcıyı akışta tutmak için değil, kullanıcının kararını gerçeğe dayandırmak için konur. Doğru göstergenin tamamlama oranını yükseltmesi bu kararın bir sonucudur, amacı değil.

Geri Bildirim Gecikmesi Gösterge Sınıfını Belirler

Üçüncü tablo farklı bir soruyu ele alıyor: bir işlem sürerken kullanıcıya ne gösterilmeli? Yanıt, işlemin süresine bağlıdır ve yerleşik üç eşikle sınıflandırılır.

0.1 saniyeye kadar kullanıcı gecikmeyi algılamaz; sonuç anında gelmiş gibi görünür. Arama alanına yazma bu sınıftadır ve gösterge gerekmez. Bu sınıfta bir yükleme göstergesi eklemek zarar verir: göstergenin belirip kaybolması, olmayan bir gecikmeyi görünür kılar.

1 saniyeye kadar gecikme algılanır ama kullanıcının düşünce akışı kesilmez. Süzgeç uygulama ve kayıt açma bu sınıfta. Yeterli geri bildirim, sonucun kendisinin değişmesidir — liste yenilenir, sayfa gelir. Ayrı bir bekleme göstergesi gerekmez.

10 saniyeye kadar kullanıcının dikkati dağılır; başka bir şeye bakmaya başlar. Nüsha durumu sorgusu ve ödünç kaydı oluşturma bu sınıfta. Burada bir bekleme göstergesi gereklidir; işin ne kadar süreceği bilinmiyorsa belirsiz bir gösterge yeterlidir, çünkü kullanıcının verdiği tek karar “bekleyeyim mi” değil “arayüz çalışıyor mu” sorusudur.

10 saniyenin üstünde dikkat kopar. Makbuz üretimi bu sınıfta. Burada belirsiz gösterge yetmez; kullanıcının işi bırakıp geri dönme kararını verebilmesi için ilerlemenin ve kalan sürenin gösterilmesi gerekir. İkinci tablodaki hesabın uygulandığı yer burasıdır.

İlerleme Gerçek İşe Bağlanır

Son tablo bir denetim aracıdır: gösterilen ilerleme ile gerçekte tamamlanan işin oranı arasındaki sapmayı ölçer.

Gerçeğe bağlı gösterge sıfır sapma verir. Sabit hızlı gösterge — çubuğun eşit aralıklarla ilerlediği, işin gerçek dağılımını yansıtmadığı durum — ortalama 4.7, en fazla 8.0 puan sapıyor. Sona takılan gösterge — çubuğun hızla yüzde 85’e çıkıp orada beklediği durum — ortalama 21.0, en fazla 40.0 puan sapıyor.

Sapmanın işareti önemlidir. Sona takılan gösterge işi olduğundan fazla tamamlanmış gösteriyor; kullanıcı “neredeyse bitti” diye bekliyor ve beklemesi uzuyor. Bu, tamamlama oranını yükselten ama kullanıcının kararını yanlış bilgiye dayandıran bir tasarımdır. Aynı yapının bir başka biçimi, işin gerçekte bitmiş olmasına rağmen bir bekleme göstergesinin belirli bir süre tutulmasıdır; bu, yapılan işi olduğundan ağır göstermek için eklenen bir gecikmedir.

Ölçüt bu konunun her dersindeki ölçütle aynıdır. Kullanıcı, çubuğun gerçek işe değil sabit bir hıza bağlı olduğunu bilseydi ekranda beklemeye devam eder miydi? Sona takılan göstergede yanıt hayırdır: kullanıcı beklemeyi, “yüzde 85 bitti” bilgisine güvendiği için sürdürüyor. Gerçeğe bağlı göstergede yanıt evettir; kullanıcı zaten doğru bilgiyle karar veriyor.

Özet

  • İlerleme göstergesi kullanıcının tek bir kararını besler: devam etmek mi, çıkmak mı. Gösterge, kalan işi doğru bildirdiği ölçüde işe yarar.
  • Adım sayısına göre ilerleyen çubuk, adımlar eşit uzunlukta değilse hatalı tahmin ürettirir; hesapta ortalama bağıl hata yüzde 31.3 ve hata akışın başında iyimser yönde.
  • Tamamlama oranı yanlış ölçüttür: adım çubuğu tamamlamayı yüzde 81.4’ten 89.2’ye çıkarıyor ama bu kazanç 476 kullanıcının kalan işi az sanmasından geliyor.
  • Doğru ölçüt yanlış karar sayısıdır; gösterge yokken 1226 kullanıcı gereksiz yere terk ediyor, süre çubuğuyla yanlış karar sayısı sıfır.
  • Geri bildirim gecikmesi dört sınıfa ayrılır: 0.1 saniyeye kadar gösterge gerekmez, 1 saniyeye kadar durum değişimi yeter, 10 saniyeye kadar belirsiz bekleme göstergesi, üstünde belirli ilerleme ve kalan süre gerekir.
  • İlerleme çubuğu gerçek işe bağlanır; sabit hızlı ya da sona takılan gösterge kullanıcının bekleme kararını yanlış bilgiye dayandırır.

Sonraki Adım

Bu konunun yedi dersinde aynı ölçüt yedi kez ortaya çıktı: kullanıcı, tasarım kararının nasıl alındığını bilseydi de aynı seçimi yapar mıydı? Belirginlikte, varsayılanda, sosyal kanıtta, ilerleme çubuğunda her seferinde aynı ayrım belirdi — kararın gücü kullanıcının bilgisinden mi geliyor, bilgisizliğinden mi? Sonraki ders bu ölçütü sistemleştirir: acele ettirme, gizli maliyet, zorlaştırılmış iptal, onay tuzağı ve sahte kıtlık kalıplarını sayılabilir göstergelere bağlar ve bir arayüzü bu göstergelerle denetlemenin yolunu kurar.

İ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