İçeriğe geç
academia.sh

Ders 22 / 25

Hata Mesajı Yazımı

Hata iletisinin kaynağa göre sınıflandırılması, her sınıfın zorunlu parçaları, parçaları tam ama içeriksiz iletilerin dil denetimiyle yakalanması ve iletinin yeri ile ömrünün sınıftan türetilmesi.

İçindekiler

Önceki dersin denetimi en ağır bulguyu bir hata iletisinde bulmuştu: “ISBN yanlış girdiniz!” Karşı örneği aynı katalogda duruyordu ve aradaki fark üslup değil yapıydı. Birincisi neyin yanlış olduğunu söylüyor, ikincisi neyin doğru olduğunu ve kullanıcının ne yapacağını söylüyordu.

Bu ders hata iletisini bir metin sorunu olarak değil, parçaları belli bir yapı olarak ele alır. Yapının parçaları iletinin kaynağına göre değişir; kaynak sınıflandırılmadan hangi parçanın zorunlu olduğu bilinemez.

Hata Kaynağa Göre Sınıflandırılır

Beş sınıf, katalog arayüzündeki bütün hataları karşılar. Girdi hatası kullanıcının yazdığı değerin biçim ya da aralık kuralını karşılamamasıdır; kullanıcı düzeltebilir. Yetki hatası eylemin kullanıcının hakları dışında olmasıdır; kullanıcı düzeltemez ama bir yol izleyebilir. Çatışma eylemin başka bir durum yüzünden yapılamamasıdır — cilt başkasında. Geçici hata sistemin o an yanıt verememesidir. Kurtarılamaz hata ise kullanıcının hiçbir adımının sonucu değiştirmediği durumdur.

Sınıf üç şeyi belirler: hangi parçaların zorunlu olduğunu, iletinin nereye konacağını ve ne kadar kalacağını. Aşağıdaki hesap bu kuralları katalogdan toplanmış altı ileti üzerinde çalıştırır.

// hata.mjs — hata iletilerinin kaynagina gore siniflandirilmasi ve parca denetimi

// Her sinif icin zorunlu parcalar. "cozum" kullanicinin atabilecegi adimdir.
const SINIF = {
  girdi:        { parcalar: ["neden", "cozum"],            alanaBagli: true,  kalici: false },
  yetki:        { parcalar: ["neden", "cozum"],            alanaBagli: false, kalici: true  },
  catisma:      { parcalar: ["neden", "cozum", "durum"],   alanaBagli: false, kalici: true  },
  gecici:       { parcalar: ["neden", "cozum"],            alanaBagli: false, kalici: false },
  kurtarilamaz: { parcalar: ["neden", "kimlik"],           alanaBagli: false, kalici: true  },
};

// Katalog arayuzunden toplanan iletiler.
const ILETILER = [
  { kimlik: "H1", sinif: "girdi", alan: "isbn", metin: "ISBN yanlış girdiniz!",
    parcalar: ["neden"] },
  { kimlik: "H2", sinif: "girdi", alan: "isbn",
    metin: "ISBN 13 hane olmalı; kitabın arka kapağındaki çizgi kodun altında yazar.",
    parcalar: ["neden", "cozum"] },
  { kimlik: "H3", sinif: "yetki", alan: null,
    metin: "Bu kaydı ödünç alma yetkiniz yok. Ödünç hakkı öğrenci kartıyla açılır; kütüphane girişindeki bankoya başvurun.",
    parcalar: ["neden", "cozum"] },
  { kimlik: "H4", sinif: "catisma", alan: null,
    metin: "Bu cilt sizden önce ödünç alındı. Şu an rafta değil; iade tarihi 12 Ağustos, ayırtma listesine eklenebilirsiniz.",
    parcalar: ["neden", "cozum", "durum"] },
  { kimlik: "H5", sinif: "gecici", alan: null, metin: "Bir hata oluştu. Lütfen tekrar deneyin.",
    parcalar: ["neden", "cozum"] },
  { kimlik: "H6", sinif: "kurtarilamaz", alan: null,
    metin: "Ödünç kaydı oluşturulamadı. Kayıt numarası KYT-4471 ile bankoya başvurabilirsiniz.",
    parcalar: ["neden", "kimlik"] },
];

// 1. Parca denetimi: her ileti sinifinin zorunlu parcalarini tasiyor mu?
console.log("ileti  sinif          zorunlu parcalar        eksik");
let eksikToplam = 0;
for (const i of ILETILER) {
  const zorunlu = SINIF[i.sinif].parcalar;
  const eksik = zorunlu.filter((p) => !i.parcalar.includes(p));
  eksikToplam += eksik.length;
  console.log(
    `${i.kimlik.padEnd(6)} ${i.sinif.padEnd(14)} ${zorunlu.join(", ").padEnd(23)} ${eksik.length ? eksik.join(", ") : "-"}`
  );
}
console.log(`eksik parca toplami: ${eksikToplam}`);

// 2. Dil denetimi: suclayan kalip, unlem, ozur ve teknik siziinti.
const KURALLAR = [
  { ad: "suclayan kalip", sina: (m) => /\b(girdiniz|yaptiniz|yanlış girdiniz|hatalı girdiniz)\b/i.test(m) },
  { ad: "unlem", sina: (m) => m.includes("!") },
  { ad: "ozur kalibi", sina: (m) => /(özür|üzgünüz|maalesef)/i.test(m) },
  { ad: "bos nezaket", sina: (m) => /(lütfen tekrar deneyin|bir hata oluştu)/i.test(m) },
  { ad: "teknik sizinti", sina: (m) => /(null|undefined|exception|error code \d|HTTP \d{3})/i.test(m) },
];
console.log("\nileti  bulgular");
let bulguToplam = 0;
for (const i of ILETILER) {
  const bulgular = KURALLAR.filter((k) => k.sina(i.metin)).map((k) => k.ad);
  bulguToplam += bulgular.length;
  console.log(`${i.kimlik.padEnd(6)} ${bulgular.length ? bulgular.join(", ") : "-"}`);
}
console.log(`dil bulgusu toplami: ${bulguToplam}`);

// 3. Sunum karari: ileti nereye ve ne kadar kalir?
console.log("\nileti  sunum yeri                 kalicilik");
for (const i of ILETILER) {
  const s = SINIF[i.sinif];
  console.log(
    `${i.kimlik.padEnd(6)} ${(s.alanaBagli ? "alanin yaninda" : "eylemin yaninda / sayfa ustu").padEnd(26)} ` +
      (s.kalici ? "kullanici kapatana kadar" : "sonraki denemeye kadar")
  );
}

// 4. Ileti uzunlugu: okunabilirlik siniri.
const SINIR = 120;
console.log("\nileti  karakter  sinir asimi");
for (const i of ILETILER) {
  console.log(`${i.kimlik.padEnd(6)} ${String(i.metin.length).padStart(8)}  ${i.metin.length > SINIR ? "evet" : "hayir"}`);
}

// 5. Toplu denetim ozeti: hangi iletiler yeniden yazilmali?
const yenidenYaz = ILETILER.filter((i) => {
  const eksik = SINIF[i.sinif].parcalar.filter((p) => !i.parcalar.includes(p)).length;
  const bulgu = KURALLAR.filter((k) => k.sina(i.metin)).length;
  return eksik > 0 || bulgu > 0;
});
console.log(`\nyeniden yazilmasi gereken ileti: ${yenidenYaz.length} / ${ILETILER.length}`);
for (const i of yenidenYaz) console.log(`  ${i.kimlik}: ${JSON.stringify(i.metin)}`);
ileti  sinif          zorunlu parcalar        eksik
H1     girdi          neden, cozum            cozum
H2     girdi          neden, cozum            -
H3     yetki          neden, cozum            -
H4     catisma        neden, cozum, durum     -
H5     gecici         neden, cozum            -
H6     kurtarilamaz   neden, kimlik           -
eksik parca toplami: 1

ileti  bulgular
H1     suclayan kalip, unlem
H2     -
H3     -
H4     -
H5     bos nezaket
H6     -
dil bulgusu toplami: 3

ileti  sunum yeri                 kalicilik
H1     alanin yaninda             sonraki denemeye kadar
H2     alanin yaninda             sonraki denemeye kadar
H3     eylemin yaninda / sayfa ustu kullanici kapatana kadar
H4     eylemin yaninda / sayfa ustu kullanici kapatana kadar
H5     eylemin yaninda / sayfa ustu sonraki denemeye kadar
H6     eylemin yaninda / sayfa ustu kullanici kapatana kadar

ileti  karakter  sinir asimi
H1           21  hayir
H2           72  hayir
H3          110  hayir
H4          112  hayir
H5           39  hayir
H6           82  hayir

yeniden yazilmasi gereken ileti: 2 / 6
  H1: "ISBN yanlış girdiniz!"
  H5: "Bir hata oluştu. Lütfen tekrar deneyin."

Zorunlu Parçalar

Çıktının ilk bölümü parça denetimidir. Her sınıf için neden zorunludur: kullanıcı neyin olduğunu bilmelidir. Girdi, yetki, çatışma ve geçici hatalarda ayrıca çözüm zorunludur — kullanıcının atabileceği bir adım. Çatışmada bir de durum bilgisi gerekir: cildin ne zaman döneceği, alternatifin ne olduğu.

Kurtarılamaz hata bu kalıbın istisnasıdır. Çözüm önermek yanıltıcı olur; onun yerine kimlik zorunludur: kullanıcı bir yetkiliyle konuşacaksa elinde bir kayıt numarası olmalıdır. Bu ayrım Hata ve Uyarı Durumları dersinde kurulmuştu; burada iletinin metnine uygulanıyor.

Modelde yalnız bir ileti parça denetiminden kalıyor: “ISBN yanlış girdiniz!” nedeni söylüyor, çözümü söylemiyor. Karşı örneği hem kuralı hem de kuralın nerede yazdığını veriyor — hane sayısı ve çizgi kodun altındaki yer.

Parçalar Tam, İleti Boş

İkinci bölüm dil denetimidir ve daha ince bir kusuru yakalıyor. Geçici hata iletisi parça denetiminden geçiyor: bir nedeni var, bir çözümü var. Ama ikisi de içeriksiz. “Bir hata oluştu” bir neden değildir, “tekrar deneyin” ise koşulsuz bir öneridir — kullanıcı ne kadar bekleyeceğini ve tekrar denemenin niçin işe yarayacağını bilmez.

Denetim bunu boş nezaket kalıbı olarak işaretliyor. Aynı bölüm suçlayan kalıbı ve ünlemi de yakalıyor: “girdiniz” eki hatayı kullanıcıya bağlar, ünlem ise onu yükseltir. Teknik sızıntı kuralı da buradadır; sistemin iç hata kodunu kullanıcıya göstermek bilgi vermez, yalnız güveni sarsar. Kayıt numarası ise sızıntı değildir: kullanıcının bir yetkiliye verebileceği, o iş için üretilmiş bir kimliktir.

İletinin Yeri ve Ömrü

Üçüncü bölüm sunum kararını sınıftan türetiyor. Girdi hatası alanın yanında durur — hangi alanın sorunlu olduğu ancak konumla anlaşılır ve bu bağ Erişilebilir Hata Sunumu dersindeki gibi işaretlemede de kurulur. Diğer sınıflar eyleme ya da sayfaya bağlıdır.

Ömür de sınıftan gelir. Girdi ve geçici hata bir sonraki denemeye kadar durur; kullanıcı yeniden denediğinde ileti anlamını yitirir. Yetki, çatışma ve kurtarılamaz hata ise kullanıcı kapatana kadar kalır: bunlar tekrar denemekle çözülmez ve kullanıcı bilgiyi okumak, not almak ya da başka birine iletmek isteyebilir.

Dördüncü bölüm uzunluğu ölçüyor. Sınır katı bir kural değil, bir uyarı eşiğidir: bir hata iletisi bir paragraf uzunluğuna geldiyse çoğu zaman iki ayrı bilgi taşıyordur ve ikincisi yardım metnine aittir.

Denetimin Çıktısı

Son bölüm iki iletiyi yeniden yazılmak üzere işaretliyor. Denetimin değeri sayının kendisi değil, hangi kuralın düştüğünü söylemesidir: biri eksik parça, öteki içeriksiz parça. İki kusur farklı düzeltme gerektirir — birincisine bilgi eklenir, ikincisinde var olan bilginin yerine gerçek bilgi konur.

Bu denetim rehber dosyasının bir parçasıdır ve sürüm kontrolünde çalışır: yeni bir ileti eklendiğinde sınıfı yazılır, parçaları denetlenir ve dil kuralları taranır. Kural kümesi büyüdükçe yanlış alarm da üretir; her yanlış alarm kuralın daraltılması için bir kayıttır.

Özet

  • Hata iletisi bir üslup sorunu değil, parçaları kaynağa göre belirlenen bir yapıdır: neden her sınıfta zorunludur, çözüm dört sınıfta zorunludur, kurtarılamaz hatada yerini kimlik bilgisi alır.
  • Parça denetimi eksik bilgiyi yakalar, dil denetimi içeriksiz bilgiyi: “bir hata oluştu, tekrar deneyin” iletisi parça denetiminden geçer ama boş nezaket kalıbına takılır.
  • Suçlayan ek, ünlem, özür kalıbı ve teknik sızıntı taranabilir kurallardır; kayıt numarası sızıntı değil, kullanıcının kullanabileceği bir kimliktir.
  • İletinin yeri ve ömrü sınıftan türetilir: girdi hatası alanın yanında ve bir sonraki denemeye kadar, yetki ve çatışma kullanıcı kapatana kadar durur.
  • Denetim hangi kuralın düştüğünü söyler; eksik parça ile içeriksiz parça farklı düzeltme gerektirir.

Sonraki Adım

Bu iki ders arayüz metnini tek bir dilde ele aldı. Katalog başka bir dile açıldığında metnin kendisi kadar çevresi de değişir: aynı ileti bazı dillerde yüzde otuz uzar ve kutusuna sığmaz, tarih ve sayı biçimleri değişir, çoğul kuralları ikiden fazla biçim gerektirir. Sonraki ders yerelleştirme gereksinimlerini ele alır ve bunların hepsini hesapla ölçer: metin uzamasının düzene etkisi, biçimlemenin yerel ayardan türetilmesi ve dizgi birleştirmenin neden çeviriyi bozduğu.

İ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