Ders 13 / 19
Adlandırma Sözleşmeleri
Tasarım adlarıyla kod adları arasındaki türetim kuralı, adın dilbilgisi denetimi, eş anlamlı ad çakışmalarının saptanması ve değişke eksenleriyle girdi özellikleri arasındaki farkın raporlanması.
İçindekiler
Önceki dersin katalog tablosu bir varsayıma dayanıyordu: bir bileşenden söz edildiğinde
tasarımcının ve geliştiricinin aynı şeyi kastettiği varsayımına. Tablodaki arac-ipucu
satırının tasarım dosyasındaki karşılığının ne olduğu, ya da tasarımda duran bir parçanın
kodda hiç bulunmadığı o tablodan okunamaz.
Adlandırma sözleşmesi bu boşluğu kapatır. Amacı estetik değildir: iki ayrı kayıt kümesi arasında makineyle denetlenebilir bir eşleme kurmaktır. Eşleme kurulduğunda “tasarımda var, kodda yok” ve “kodda var, tasarımda yok” listeleri hesaplanabilir hâle gelir; bu iki liste, sistemin en sık ve en sessiz kusurunu görünür kılar.
İki Ad Kümesi, Tek Kavram
Bileşen iki yerde adlandırılır. Tasarım kitaplığında hiyerarşik bir ad taşır; bu ad insanlara gösterilir ve boşluk, büyük harf, Türkçe karakter içerebilir. Kodda ise bir modül adı taşır; bu ad dosya sisteminde ve içe aktarımlarda geçer, ASCII olmak zorundadır.
İki ad kümesinin bağımsız yönetilmesi, sistemin en yaygın çürüme biçimidir. Tasarımcı bir parçanın adını değiştirir, kod adı eskisi kalır; ya da geliştirici yeni bir bileşen ekler, tasarım kitaplığında karşılığı hiç oluşmaz. Hiçbiri hata vermez, çünkü iki küme arasında kimse bir denklik iddia etmemiştir.
Sözleşme tam olarak bu denklik iddiasıdır ve üç parçası vardır:
- Dilbilgisi. Tasarım adı hangi biçimde yazılır: kaç bölüm, hangi harf düzeni.
- Türetim. Tasarım adından kod adı nasıl hesaplanır. Bu kural bir işlev olmalıdır; iki adın “birbirine benzemesi” denetlenemez, birinden diğerinin hesaplanması denetlenir.
- Tekillik. Bir kavram için tek ad. Aynı şeyi anlatan iki ad, iki bileşen üretir.
Türetim Kuralının Yazılması
Türetim kuralı çevriyazımla başlar ve sırası önemlidir. Türkçe harfler önce ASCII
karşılıklarına çevrilmeli, sonra küçültme yapılmalıdır. Ters sırada, büyük noktalı İ
harfinin küçültülmesi noktası ayrı duran bir birleşik karakter üretir ve kod adı gözle
görülmeden bozulur.
Aşağıdaki program tasarım kitaplığındaki yirmi bir adı ve kod kataloğundaki yirmi bir adı alır; türetimi uygular, dilbilgisini denetler, eş anlamlı ad sözlüğünü işletir ve son olarak değişke eksenleriyle girdi özelliklerini karşılaştırır.
// adlandirma.mjs — tasarim adlari ile kod adlari arasindaki eslemenin denetimi // Tasarim kitapligindaki adlar: "Kategori/Bilesen" ve degiske eksenleri. const TASARIM = [ { ad: "Eylem/Düğme", eksen: ["tur", "boyut", "durum"] }, { ad: "Eylem/Bağlantı", eksen: ["tur", "durum"] }, { ad: "Form/Metin Alanı", eksen: ["boyut", "durum"] }, { ad: "Form/Onay Kutusu", eksen: ["durum", "secili"] }, { ad: "Form/Radyo Grubu", eksen: ["yon", "durum"] }, { ad: "Form/Açılır Liste", eksen: ["boyut", "durum"] }, { ad: "Form/Arama Alanı", eksen: ["boyut", "durum"] }, { ad: "Gösterim/Rozet", eksen: ["ton", "boyut"] }, { ad: "Kapsayıcı/Kart", eksen: ["yukselti", "tiklanabilir"] }, { ad: "Gezinme/Kırıntı Yolu", eksen: ["kisaltma"] }, { ad: "Gezinme/Sayfalama", eksen: ["boyut"] }, { ad: "Gezinme/Sekmeler", eksen: ["yon", "boyut"] }, { ad: "Geri Bildirim/Bildirim Şeridi", eksen: ["ton", "kapatilabilir"] }, { ad: "Geri Bildirim/Boş Durum", eksen: ["boyut"] }, { ad: "Geri Bildirim/İskelet", eksen: ["satir"] }, { ad: "Katman/Kip Pencere", eksen: ["boyut"] }, { ad: "Katman/İpucu Balonu", eksen: ["yon"] }, { ad: "Kapsayıcı/Akordeon", eksen: ["boyut"] }, { ad: "Gösterim/Tablo", eksen: ["yogunluk"] }, { ad: "Kart Bileşeni", eksen: ["yukselti"] }, { ad: "Form/Girdi/Sayı Alanı", eksen: ["boyut"] }, ]; // Kod katalogundaki adlar ve her bilesenin girdi ozellikleri. const KOD = [ { ad: "dugme", ozellik: ["tur", "boyut", "durum"] }, { ad: "baglanti", ozellik: ["tur", "durum"] }, { ad: "metin-alani", ozellik: ["boyut", "durum"] }, { ad: "onay-kutusu", ozellik: ["durum", "secili"] }, { ad: "radyo-grubu", ozellik: ["yon", "durum"] }, { ad: "acilir-liste", ozellik: ["boyut", "durum", "aramali"] }, { ad: "arama-alani", ozellik: ["boyut", "durum"] }, { ad: "rozet", ozellik: ["ton", "boyut"] }, { ad: "kart", ozellik: ["yukselti", "tiklanabilir"] }, { ad: "kirinti-yolu", ozellik: ["kisaltma"] }, { ad: "sayfalama", ozellik: ["boyut"] }, { ad: "sekmeler", ozellik: ["yon", "boyut"] }, { ad: "bildirim-seridi", ozellik: ["ton", "kapatilabilir"] }, { ad: "bos-durum", ozellik: ["boyut"] }, { ad: "iskelet", ozellik: ["satir"] }, { ad: "kip-pencere", ozellik: ["boyut", "kapatilabilir"] }, { ad: "arac-ipucu", ozellik: ["yon"] }, { ad: "akordeon", ozellik: ["boyut"] }, { ad: "tablo", ozellik: ["yogunluk"] }, { ad: "sayi-alani", ozellik: ["boyut"] }, { ad: "yardim-metni", ozellik: [] }, ]; // Turkce harfleri once cevir, sonra kucult. Ters sira yapilirsa "I" harfi noktali // "i" uretir ve kod adi sessizce bozulur. const CEVRIM = { "ı": "i", "İ": "i", "ş": "s", "Ş": "s", "ç": "c", "Ç": "c", "ğ": "g", "Ğ": "g", "ü": "u", "Ü": "u", "ö": "o", "Ö": "o", "â": "a", "î": "i", "û": "u" }; const cevir = (s) => [...s].map((h) => CEVRIM[h] ?? h).join(""); // Turetim kurali: son bolum -> cevriyazim -> kucult -> bosluk yerine tire. const koddanBeklenen = (tasarimAdi) => { const son = tasarimAdi.split("/").at(-1); return cevir(son).toLowerCase().replace(/\s+/g, "-"); }; // Dilbilgisi kurallari: ad iki bolumden olusur, her bolum Baslik Bicimi'ndedir. function dilbilgisi(tasarimAdi) { const kusur = []; const bolum = tasarimAdi.split("/"); if (bolum.length !== 2) kusur.push(`bölüm sayısı ${bolum.length}, 2 olmalı`); for (const b of bolum) { for (const sozcuk of b.split(/\s+/)) { if (sozcuk !== sozcuk.charAt(0).toLocaleUpperCase("tr") + sozcuk.slice(1)) { kusur.push(`"${sozcuk}" başlık biçiminde değil`); } } } return kusur; } // Es anlamli ad sozlugu: bir kavram icin kabul edilen tek ad ve reddedilen adlar. const ESANLAM = [ { kabul: "arac-ipucu", red: ["ipucu-balonu", "aciklama-balonu"] }, { kabul: "kip-pencere", red: ["diyalog", "acilir-pencere"] }, { kabul: "bildirim-seridi", red: ["uyari-kutusu"] }, ]; const kodAdlari = new Set(KOD.map((k) => k.ad)); console.log("tasarım adı beklenen kod adı durum"); let eslesen = 0; const eslesmeyenTasarim = []; for (const t of TASARIM) { const beklenen = koddanBeklenen(t.ad); const bulundu = kodAdlari.has(beklenen); if (bulundu) eslesen++; else eslesmeyenTasarim.push(beklenen); console.log(`${t.ad.padEnd(31)} ${beklenen.padEnd(19)} ${bulundu ? "eşleşti" : "KOD YOK"}`); } const beklenenler = new Set(TASARIM.map((t) => koddanBeklenen(t.ad))); const eslesmeyenKod = KOD.filter((k) => !beklenenler.has(k.ad)).map((k) => k.ad); console.log(`\ntasarımda karşılığı olmayan kod adları: ${JSON.stringify(eslesmeyenKod)}`); console.log("\ndilbilgisi kusurları"); for (const t of TASARIM) { const kusur = dilbilgisi(t.ad); if (kusur.length) console.log(`${t.ad.padEnd(31)} ${kusur.join("; ")}`); } console.log("\neş anlamlı ad çakışmaları"); const tumAdlar = [...kodAdlari, ...TASARIM.map((t) => koddanBeklenen(t.ad))]; for (const e of ESANLAM) { const gecen = e.red.filter((r) => tumAdlar.includes(r)); if (gecen.length) console.log(`${e.kabul.padEnd(19)} yerine kullanılan: ${JSON.stringify(gecen)}`); } console.log("\ndeğişke ekseni ile girdi özelliği farkları"); const kodHarita = new Map(KOD.map((k) => [k.ad, k.ozellik])); for (const t of TASARIM) { const ozellik = kodHarita.get(koddanBeklenen(t.ad)); if (!ozellik) continue; const yalnizTasarim = t.eksen.filter((e) => !ozellik.includes(e)); const yalnizKod = ozellik.filter((o) => !t.eksen.includes(o)); if (yalnizTasarim.length === 0 && yalnizKod.length === 0) continue; console.log(`${t.ad.padEnd(31)} yalnız tasarımda: ${JSON.stringify(yalnizTasarim)} yalnız kodda: ${JSON.stringify(yalnizKod)}`); } const oran = (eslesen / TASARIM.length) * 100; console.log(`\neşleşen ad sayısı : ${eslesen}/${TASARIM.length} (%${oran.toFixed(1)})`); console.log(`tasarımda karşılığı olmayan : ${eslesmeyenKod.length}`); console.log(`kodda karşılığı olmayan : ${eslesmeyenTasarim.length}`);
tasarım adı beklenen kod adı durum Eylem/Düğme dugme eşleşti Eylem/Bağlantı baglanti eşleşti Form/Metin Alanı metin-alani eşleşti Form/Onay Kutusu onay-kutusu eşleşti Form/Radyo Grubu radyo-grubu eşleşti Form/Açılır Liste acilir-liste eşleşti Form/Arama Alanı arama-alani eşleşti Gösterim/Rozet rozet eşleşti Kapsayıcı/Kart kart eşleşti Gezinme/Kırıntı Yolu kirinti-yolu eşleşti Gezinme/Sayfalama sayfalama eşleşti Gezinme/Sekmeler sekmeler eşleşti Geri Bildirim/Bildirim Şeridi bildirim-seridi eşleşti Geri Bildirim/Boş Durum bos-durum eşleşti Geri Bildirim/İskelet iskelet eşleşti Katman/Kip Pencere kip-pencere eşleşti Katman/İpucu Balonu ipucu-balonu KOD YOK Kapsayıcı/Akordeon akordeon eşleşti Gösterim/Tablo tablo eşleşti Kart Bileşeni kart-bileseni KOD YOK Form/Girdi/Sayı Alanı sayi-alani eşleşti tasarımda karşılığı olmayan kod adları: ["arac-ipucu","yardim-metni"] dilbilgisi kusurları Kart Bileşeni bölüm sayısı 1, 2 olmalı Form/Girdi/Sayı Alanı bölüm sayısı 3, 2 olmalı eş anlamlı ad çakışmaları arac-ipucu yerine kullanılan: ["ipucu-balonu"] değişke ekseni ile girdi özelliği farkları Form/Açılır Liste yalnız tasarımda: [] yalnız kodda: ["aramali"] Katman/Kip Pencere yalnız tasarımda: [] yalnız kodda: ["kapatilabilir"] eşleşen ad sayısı : 19/21 (%90.5) tasarımda karşılığı olmayan : 2 kodda karşılığı olmayan : 2
Raporun Okunması
Yirmi bir adın on dokuzu eşleşiyor. Kalan dört satır — iki eşleşmeyen tasarım adı ve iki eşleşmeyen kod adı — dört farklı kusur türünü temsil ediyor ve her biri farklı bir işle kapanır.
Katman/İpucu Balonu ile arac-ipucu aynı bileşendir, iki adı vardır. Bu, listenin
en zararlı satırıdır; çünkü ne tasarımda ne kodda bir eksik görünür. Her iki tarafta da
bileşen mevcuttur, yalnızca birbirine bağlanamaz. Eş anlamlı ad sözlüğü bu durumu
yakalayan tek denetimdir: kabul edilen adın yanına reddedilen adlar yazılmadıkça, bir
denetim programı iki adın aynı kavramı gösterdiğini kendiliğinden bilemez.
Kart Bileşeni iki kusur birden taşır. Kategorisiz yazılmıştır ve zaten var olan
Kapsayıcı/Kart kaydının kopyasıdır. “Bileşeni” sözcüğü de sözleşme dışıdır: kataloğun
her kaydı zaten bir bileşendir, adın bunu tekrar söylemesi hiçbir ayrım üretmez.
yardim-metni kodda var, tasarımda yok. Bu satır her zaman kusur anlamına gelmez.
Görsel karşılığı olmayan bir yardımcının kod tarafında bulunması olağandır. Sözleşmenin
istediği şey, bu satırın açıkça işaretlenmiş olmasıdır: kataloğa “tasarım karşılığı
yok” notu düşülmezse, denetim her çalıştığında aynı satırı kusur gibi raporlar ve rapor
okunmaz hâle gelir.
Form/Girdi/Sayı Alanı ilginç bir durumu gösteriyor: dilbilgisi denetiminden kalıyor ama
ad eşleşmesinden geçiyor. Türetim son bölümü aldığı için üç bölümlü ad da doğru kod adını
üretiyor. Bu, iki denetimin ayrı tutulmasının nedenidir. Türetim kuralı gevşek
olabilir; dilbilgisi kuralı gevşek olursa kategoriler dağılır ve kitaplıkta arama yapmak
zorlaşır.
Değişke Ekseni ile Girdi Özelliği
Adlandırma yalnızca bileşen adını kapsamaz. Tasarım kitaplığında bir bileşenin görünümlerini üreten eksenler vardır; kodda bunların karşılığı Bileşen Tabanlı Arayüz Geliştirme kursunda tanımlanan girdi özellikleridir. İkisinin adları da eşleşmelidir, çünkü tasarımcı ile geliştirici arasındaki konuşma bu eksenlerin adları üzerinden yürür.
Çıktının son bloğu iki sapma gösteriyor ve ikisi de aynı yönde: kodda olan bir eksen
tasarımda yok. acilir-liste bileşeninin aramali özelliği ve kip-pencere bileşeninin
kapatilabilir özelliği kod tarafında eklenmiş, tasarım kitaplığına yansımamış.
Bu yön, sapmanın nedeni hakkında bilgi verir. Kodda beliren yeni eksen genellikle bir ürün ihtiyacından doğar: bir ekibin uzun listeye ihtiyacı olmuş, arama özelliği eklenmiş. Tasarımda beliren ama kodda olmayan eksen ise gerçekleştirilmemiş bir tasarım kararıdır. İki durumun kapatma yolu farklıdır; ilki tasarım kitaplığının güncellenmesini, ikincisi katkı sürecine bir iş girmesini gerektirir.
Eksen değerlerinin de sözleşmeye girmesi gerekir. tur ekseninin tasarımda “birincil”
ve “ikincil”, kodda birincil ve ikincil değerlerini alması denetlenebilir; tasarımda
“ana eylem” yazılıp kodda birincil kullanılması, ad eşleşse bile konuşmayı bozar.
Sözleşmenin Sürdürülmesi
Denetim programı tek seferlik bir temizlik aracı değildir. Ad kümeleri sürekli değişir ve sapma her zaman yeniden birikir. İki uygulama kararı bunu belirler.
Birincisi, denetimin kırıcı olup olmadığıdır. Rapor üreten ama hiçbir şeyi durdurmayan bir denetim, birkaç ay içinde okunmayan bir çıktıya dönüşür. Eşleşme oranı için bir alt sınır belirlenip bu sınırın altına düşüldüğünde sürecin durdurulması, raporu karara bağlar.
İkincisi, istisnaların kayıt altına alınmasıdır. yardim-metni gibi meşru
eşleşmezlikler bir istisna listesine yazılır ve listeye her giriş bir gerekçe taşır.
İstisna listesi büyüdükçe sözleşmenin kendisinin gözden geçirilmesi gerektiği anlaşılır;
listenin uzunluğu da bir göstergedir.
Özet
- Bileşen iki ayrı kümede adlandırılır; iki küme bağımsız yönetildiğinde aralarındaki sapma hiçbir yerde hata üretmeden birikir.
- Sözleşmenin üç parçası vardır: adın dilbilgisi, tasarım adından kod adını hesaplayan türetim kuralı ve bir kavrama tek ad veren tekillik kuralı.
- Türetimde Türkçe harfler küçültmeden önce çevrilir; ters sıra noktalı
İharfinde bozuk kod adı üretir. - Eş anlamlı ad çakışması iki tarafta da eksik göstermediği için yalnızca bir eş anlam sözlüğüyle yakalanır; en zararlı kusur türü budur.
- Değişke eksenleri ile girdi özellikleri de eşleşmelidir; sapmanın yönü, işin tasarım kitaplığında mı yoksa katkı sürecinde mi olduğunu söyler.
- Denetim bir alt sınıra bağlanmadıkça ve istisnalar gerekçeleriyle kayıt altına alınmadıkça rapor okunmaz hâle gelir.
Sonraki Adım
Adlar eşleştiğinde bir bileşenden söz etmek mümkün olur, ama onu kullanmak için
yeterli değildir. acilir-liste bileşeninin hangi durumda arama-alani yerine
seçileceği, kip-pencere yerine ne zaman ayrı bir sayfa kullanılacağı ve rozet ile
bildirim-seridi arasındaki ayrım adlardan okunamaz. Sonraki ders bileşen belgesinin
zorunlu bölümlerini tanımlar, karşı örneğin neden örnek kadar gerekli olduğunu gösterir ve
belgelendirme kapsamını kullanımla ağırlıklandırarak hesaplar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.