Ders 02 / 14
Tasarım Sistemi Uyarlaması
Tasarım sistemi uyarlaması, tek bir tasarım dilini iki platformun beklentisine göre ayarlar. Ders uyarlanmış bir bileşenin her iki platformda da tam çalıştığını, başka bir bileşenin ise sürüm koşulunda kısıtlı kaldığını ölçer.
Yayın Güncelleme
Bu derste
- Tasarım belirteci, bileşen ve tasarım sistemi arasındaki ilişkiyi açıklar
- Bir bileşenin platforma göre uyarlanmasının ne kazandırdığını ve neye mal olduğunu karşılaştırır
- Uyarlanmış bir bileşenin her iki platformda tam çalıştığını ölçer
- Belirteç değeri değişince işlerlik kaydının aynı kaldığını gösterir
İçindekiler
Önceki derste platforma göre değişen şey bir yetenekti: katman yeteneği karşılamayınca özellik kapandı. Bu derste platforma göre değişen şey görünümdür. Bir ürünün tek bir tasarım dili vardır; renkleri, aralıkları, köşe yuvarlaklıkları ve yazı ölçüleri ürünün iki platformda da tanınmasını sağlar. Ama iOS ve Android kullanıcıları kendi platformlarından farklı alışkanlıklar getirir ve iyi bir tasarım sistemi bu farkı bilerek uyarlar. Ders önce uyarlamanın nasıl kurulduğunu anlatır, sonra uyarlanmış bir bileşenin işlerliğini ölçer.
Tasarım Belirteçleri
Tasarım sistemi, bir ürünün görünümünü tutarlı kılan parçalar bütünüdür: belirteçler, bu belirteçlerden kurulan bileşenler ve bileşenlerin ne zaman nasıl kullanılacağını söyleyen yönergeler. Tasarım belirteci, bir tasarım kararının adı konmuş değeridir: accent bir renk, gap bir aralık, radius bir köşe yuvarlaklığıdır. Bileşen rengi ya da aralığı kendi içine yazmaz, belirteci adıyla okur. Kazancı tek yerde değişmektir: vurgu rengi belirteçte değişir ve onu okuyan her bileşen ona uyar.
Belirteçler üç katmanda düşünülür. Temel katman ürünün iki platformda da aynı tuttuğu değerleri taşır. Uyarlama katmanı bir platformda temelin üstüne yazılan değerleri taşır. Bileşen son değeri bu ikisinin birleşiminden okur: platformda tanımlı bir değer varsa o, yoksa temel değer. Böylece uyarlama bir istisna listesi olarak küçük kalır; ürünün çoğu değeri hâlâ tek yerde durur.
Aşağıdaki parça bu okumayı bir bileşen üzerinde gösterir. Tarih seçici biçimini ve genişliğini belirteçten alır; hangi platformda koştuğunu kendisi sormaz. Parça ölçülmez.
// Platform kodu: belirteci okuyan bilesen
function DatePicker({ tokens, value, onChange }) {
const Picker = tokens.picker === "tekerlek" ? WheelPicker : CalendarPicker;
return (
<Picker
value={value}
onChange={onChange}
width={tokens.width}
radius={tokens.radius}
/>
);
}
Bileşenin içinde bir platform denetimi yoktur. Hangi biçimin seçileceğine belirteç karar verir ve belirteci platformun uyarlama katmanı doldurur. Bu, önceki dersin katman sınırının görünüm tarafındaki karşılığıdır: bileşen ne istediğini söyler, platformun nasıl karşıladığını bilmez.
Platforma Göre Uyarlama
Uyarlamanın gerekçesi alışkanlıktır. Tarih seçmek iOS’ta bir tekerleği çevirmek ya da küçük bir takvim açmak olabilir; Android’de bir takvim penceresinde güne dokunmaktır. İki kullanıcı da kendi platformunda bunu bekler. Aynı bileşenin her yerde tek biçimde çıkması ürüne tutarlılık kazandırır ama kullanıcının platformdan getirdiği beklentiyi bozar. Uyarlamak beklentiyi korur, bedelini de ödetir: ekip artık iki biçimi tasarlamak, yapmak ve sınamak zorundadır.
Bu bedel küçümsenmemelidir. Uyarlanan her bileşen bir sınama çarpanıdır: iki platformda iki biçim, iki ayrı genişlik, iki ayrı köşe yuvarlaklığı demektir. Bu yüzden iyi bir tasarım sistemi neyin uyarlanacağını bilinçli seçer. Tarih seçici gibi platformun kendi alışkanlığı güçlü olan bileşenler uyarlanır; markanın kimliğini taşıyan renk ve yazı ölçüleri tek kalır.
Uyarlama yalnız görünüm değildir. Bazı bileşenler platformun sunduğu bir görsel yeteneğe dayanır; bulanık bir arka plan gibi. Bu yetenek her platformda ve her sürümde yoktur. Bileşen bu durumda iki yoldan birini seçer: yeteneği şart koşar ve yoksa çalışmaz, ya da yoksa sade bir arka plana düşer. İkinci yol bir yedektir ve ders bunu sınırlayıcı ölçümün ikinci yarısında ölçer.
Belirteçten Koşula
Model uyarlamayı iki adımda kurar. Önce belirteçleri bir yardımcı dosyada tutar. Sonra themeFor(platform) bir platformun belirteçlerinden koşul üretir: seçicinin biçimi tanımlıysa koşulun has listesinde picker vardır, bulanık arka plan destekleniyorsa blur vardır. Dersin çekirdeği her derste olduğu gibi aşağıda yeniden verilir.
// operability.mjs — bir ozelligin bir kosulda ne kadar calistigini siniflandirir export const LEVELS = ["tam", "kisitli", "ertelenen", "kapali"]; const FALLBACKS = ["kisitli", "ertelenen"]; export function feature(name, needs, fallback = {}) { return { name, needs, fallback }; } export function condition(name, has) { return { name, has }; } function judge(item, cond) { const missing = item.needs.filter((need) => !cond.has.includes(need)).sort(); let level = "tam"; for (const need of missing) { const given = FALLBACKS.includes(item.fallback[need]) ? item.fallback[need] : "kapali"; if (LEVELS.indexOf(given) > LEVELS.indexOf(level)) level = given; } return { level, feature: item.name, condition: cond.name, missing }; } export function assess(features, conditions) { const records = []; for (const cond of conditions) { for (const item of features) records.push(judge(item, cond)); } return records; } export function printLevels(records) { for (const r of records) { const missing = r.missing.length === 0 ? "-" : r.missing.join(","); console.log(`${r.level}: ${r.feature} @ ${r.condition} eksik=${missing}`); } } export function countLevels(records) { for (const name of LEVELS) { console.log(`${name}: ${records.filter((r) => r.level === name).length}`); } console.log(`etkilenen: ${records.filter((r) => r.level !== "tam").length}`); }
Dokuz kayıtlık açılış ölçümünün sayısı ilk derste verildi; bu ders onu değiştirmez, yalnız kendi kesitini ölçer. Belirteçler ve themeFor ders-yerel bir yardımcı dosyada durur. Üç uyarlama vardır: iOS, Android ve sürüm koşulunu temsil eden eski bir Android.
// tokens.mjs — tek tasarim dilinin platforma gore uyarlanan degerleri import { condition } from "./operability.mjs"; const BASE = { accent: "mavi", gap: 8, radius: 4, blur: true }; const ADAPT = { ios: { picker: "tekerlek", radius: 10, width: 280 }, android: { picker: "takvim", width: 320 }, "android-legacy": { picker: "takvim", width: 320, blur: false }, }; export function tokensFor(platform) { return { ...BASE, ...ADAPT[platform] }; } export function themeFor(platform, tokens = tokensFor(platform)) { const has = []; if (tokens.picker) has.push("picker"); if (tokens.blur) has.push("blur"); return condition(platform, has); }
İlk ölçüm işlerliği değil belirteçleri basar. İki platformun son değerleri sıralı anahtarlarla yazılır.
// main.mjs import { tokensFor } from "./tokens.mjs"; for (const platform of ["ios", "android"]) { const tokens = tokensFor(platform); const keys = Object.keys(tokens).sort(); console.log(`${platform}: ${keys.map((k) => `${k}=${tokens[k]}`).join(" ")}`); }
ios: accent=mavi blur=true gap=8 picker=tekerlek radius=10 width=280 android: accent=mavi blur=true gap=8 picker=takvim radius=4 width=320
Uyarlama katmanı yalnız farkı taşır. accent ve gap iki platformda temelden gelir, radius yalnız iOS’ta ezilir, picker ve width iki platformda da kendi değerini taşır. Değerlerin hepsi dersin kurgusudur ve birim taşımaz.
PM3. Belirteç değerleri (gap, radius, width) dersin kurgusudur; gerçek bir tasarım sisteminin ölçüleri değildir. Model belirteçten yalnız iki sonuç çıkarır: seçicinin biçimi tanımlı mı, bulanık arka plan destekleniyor mu. Bileşenin gerçekte nasıl çizildiği, iki biçimin kullanıcıya nasıl hissettirdiği modelde yoktur. Model, bu işlerliğin kuralını kurar; model çerçevenin kendisi değildir.
Sınırlayıcı Ölçüm
Dersin odak kaydı DatePicker @ android‘dir. DatePicker yalnız picker yeteneğine ihtiyaç duyar. Belirteçler iki platformda farklıdır: iOS’ta tekerlek, Android’de takvim. Ama ikisinde de bir seçici biçimi vardır, bu yüzden yetenek iki koşulda da var olur.
// main.mjs import { feature, assess, printLevels } from "./operability.mjs"; import { themeFor } from "./tokens.mjs"; const features = [feature("DatePicker", ["picker"])]; const conditions = [themeFor("ios"), themeFor("android")]; printLevels(assess(features, conditions));
tam: DatePicker @ ios eksik=- tam: DatePicker @ android eksik=-
DatePicker @ android tamdır. Bu ölçüm M32/K03’ün sorusundan farklıdır. O ders düzen aşamasında bir bileşenin genişliğinin sahibini sordu. Tasarım sistemi bir bileşeni platforma göre uyarladığında genişliği değişebilir; işlerlik genişliği değil, bileşenin o koşulda işini görüp görmediğini sınıflar. İki platformda seçici iki farklı genişlikte, iki farklı biçimde çizilir ve ikisinde de işini görür.
Kuralın belirteç değerlerini görmediğini ikinci ölçüm doğrudan gösterir. Android uyarlamasında köşe yuvarlaklığı, genişlik ve seçicinin biçimi değiştirilir; önceki ve sonraki kayıtlar karşılaştırılır.
// main.mjs import { feature, assess } from "./operability.mjs"; import { tokensFor, themeFor } from "./tokens.mjs"; const features = [feature("DatePicker", ["picker"])]; const before = assess(features, [themeFor("android")]); const edited = { ...tokensFor("android"), radius: 16, width: 360, picker: "liste" }; const after = assess(features, [themeFor("android", edited)]); console.log(JSON.stringify(before) === JSON.stringify(after) ? "kayit ayni" : "kayit degisti");
kayit ayni
Üç belirteç değişti, kayıt aynı kaldı. Kural yalnız needs, fallback ve has’e girenleri görür; yetenek kümesine yansımayan bir değişiklik kaydı bozmaz. Bu bir çelişki değil, ölçünün kendisidir: genişliğin dar ya da geniş olması kullanıcıyı etkileyebilir, ama model yalnız seçicinin işini görüp görmediğini söyler.
İkinci karşılaştırma yedek taşıyan bir bileşendir. FrostedCard bulanık bir arka plan ister; bulanıklık yoksa sade arka plana düşer. Bulanıklığı karşılamayan eski bir Android sürümü koşulu eklenir.
// main.mjs import { feature, assess, printLevels } from "./operability.mjs"; import { themeFor } from "./tokens.mjs"; const features = [ feature("DatePicker", ["picker"]), feature("FrostedCard", ["blur"], { blur: "kisitli" }), ]; const conditions = [themeFor("ios"), themeFor("android"), themeFor("android-legacy")]; printLevels(assess(features, conditions));
tam: DatePicker @ ios eksik=- tam: FrostedCard @ ios eksik=- tam: DatePicker @ android eksik=- tam: FrostedCard @ android eksik=- tam: DatePicker @ android-legacy eksik=- kisitli: FrostedCard @ android-legacy eksik=blur
Eski sürüm koşulunda DatePicker hâlâ tamdır, FrostedCard ise kısıtlıdır: bulanıklık eksiktir, özellik sade arka planla hemen çalışır. Altı kaydın beşi tamdır. Bu sayı açılıştaki 5/1/2/1 ölçümünün sayısı değildir; iki ölçüm farklı kümeleri sayar.
PM4. Eski sürüm koşulunun bulanıklığı karşılamadığı dersin kurgusudur. Hangi gerçek sürümün bu yeteneği taşıdığını model söylemez; bu yüzden metinde sürüm numarası yazılmaz. Sade arka planın kullanıcıya ne kadar kötü ya da iyi göründüğü de modelde yoktur.
Yedek, kapalıyı kısıtlıya çeviren tasarım kararıdır. FrostedCard’ın fallback eşlemi boş olsaydı aynı eksik kapalı sonuç verirdi. Tasarım sistemi bu kararı bileşenin içine yazar: bileşen yeteneği bulamadığında ne yapacağını önceden bilir.
Özet
- Bu dersin işlerliği: tam.
DatePicker @ androidkaydında seçici iOS’ta tekerlek, Android’de takvim olsa dapickeryeteneği iki koşulda vardır ve eksik yoktur. - Tasarım belirteci bir tasarım kararının adı konmuş değeridir; uyarlama katmanı temelin üstüne yalnız platform farkını yazar.
- Genişlik, köşe yuvarlaklığı ve seçici biçimi değişse de kayıt aynı kaldı; kural yetenek kümesine yansımayan değişikliği görmez.
- Bulanıklığı karşılamayan eski sürüm koşulunda
FrostedCardkısıtlı çıktı,DatePickertam kaldı. - Uyarlama beklentiyi korur ve sınama çarpanı doğurur; yedek ise kapalıyı kısıtlıya çeviren tasarım kararıdır.
Sonraki Adım
Bu derste yeteneği belirtecin içeriği belirledi. Sıradaki ders, Yapılandırma ve Ortam Yönetimi, yeteneğin yapılandırmadan geldiği durumu ele alır: geliştirme, hazırlık ve üretim ortamları, gizli değerler ve uzaktan yapılandırmaya ulaşılamayan ilk açılışta bir bayrağın değeri.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.