İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat