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.