EduFlow

الوحدة 5 · التبنّي على نطاق واسع

قياس التبنّي وفنّ قول «لا»

18 دقراءة 4 دبيئة تجريب الكود

الدرس في لمحة

قِس تبنّي نظام التصميم (adoption)، وتغطية الـ tokens، وحداثة الإصدارات، ورضا الفرق، بعمليات مسح آلية واستبيانات، وقل «لا» للطلبات بطريقة تحمي النظام وتحفظ ثقة الفرق.

  1. 1ماذا تقيس
  2. 2جمع بيانات التبنّي بنزاهة
  3. 3قول «لا»
  4. 4أين وصلت الآن

لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.

بعد عامين من الحياة الثانية لـ Northwind UI، أعدت تشغيل سكربت الألوان من درس جرد الواجهة. صارت الدرجات الرمادية الأربع والستون تسعًا، وسبع منها primitives في ملف الـ tokens. هذا الرقم الواحد فعل لتمويل الفريق أكثر من أي عرض تقديمي، لأنه القياس نفسه، مأخوذًا بالطريقة نفسها، يُظهر «قبل» و«بعد». القياس هو الطريقة التي يثبت بها نظام التصميم أنه منتج يستحقّ أن يُدفع له، والطريقة التي يكتشف بها أين يخذل مستخدميه.

ماذا تقيس

لا يوجد رقم واحد يخبرك هل النظام يعمل. تتابع Northwind أربعة اتّجاهات، وتراجعها شهريًا:

المقياس السؤال الذي يجيب عنه كيف نجمعه
تبنّي المكوّنات كم من الواجهة مبني بمكوّنات النظام؟ مسح الاستيرادات في كل مستودع، ومسح الـ DOM للصفحات الرئيسية
تغطية الـ tokens هل تستخدم الأنماط الـ tokens أم القيم الخام؟ سكربت الألوان، موسّعًا ليشمل المسافات والطباعة
تأخّر الإصدارات كم تتأخّر الفرق؟ إصدارات الحزم عبر المستودعات
الرضا هل يجعل النظام الفرق أسرع؟ استبيان من خمسة أسئلة كل ربع سنة

معًا تقاوم هذه المقاييس التلاعب. يمكن لفريق أن يضخّم التبنّي بتغليف كل شيء في Box من النظام، لكن تغطية الـ tokens والرضا لن يتحرّكا.

جمع بيانات التبنّي بنزاهة

مسح الاستيرادات هو العمود الفقري. يمرّ سكربت على كل مستودع، ويحلّل ملفات المصدر، ويعدّ عناصر JSX التي استُورد مكوّنها من @northwind/ui مقابل المكوّنات المعرّفة محليًا. والبحث في الكود على GitHub يعطي إجابة أولى سريعة عن سؤال منفرد، مثل «أين ما زال الـ prop المُهمَل kind مستخدمًا؟»، وهكذا يعمل تتبّع الاستخدام في درس الـ deprecation.

ولصفحات الإنتاج، كل مكوّن في Northwind يعرض سمة علامة:

HTML
<button class="nw-button" data-variant="primary" data-nw-component="Button">Assign driver</button>

مسح الصفحة المعروضة يعدّ العناصر التي تحمل data-nw-component مقابل كل العناصر من النوع نفسه. وهذه السمة أهمّ مما تبدو. النسخة الأولى من مسحنا كانت تعدّ الـ class المسمّى nw-button، فأبلغت عن تبنٍّ بنسبة 94% لـ Button في الموقع التسويقي. ثم اكتشفنا أن ثلاث فرق نسخت الـ CSS الخاص بالـ Button إلى مكوّناتها، بأسماء الـ classes. المكوّن الحقيقي وحده يكتب الـ data attribute، فتتوقّف النسخ المنفصلة عن الاحتساب تبنّيًا.

ثم تُجمَّع الأرقام لكل فريق:

JavaScript
const scans = [
  { team: 'Dispatch', system: 412, total: 455, version: '5.2.0' },
  { team: 'Billing', system: 96, total: 180, version: '4.9.1' },
  { team: 'Marketing', system: 230, total: 251, version: '5.2.0' },
  { team: 'Reporting', system: 40, total: 160, version: '3.8.0' },
];
const latestMajor = 5;

for (const s of scans) {
  const percent = Math.round((s.system / s.total) * 100);
  const majorsBehind = latestMajor - Number(s.version.split('.')[0]);
  console.log(`${s.team.padEnd(10)} ${String(percent).padStart(3)}%  ${majorsBehind ? `${majorsBehind} major(s) behind` : 'current'}`);
}

نسبة 25% لدى فريق Reporting ليست سببًا لإرسال بريد إلى مديره. إنها سؤال بحثي: ما الذي يحتاجه Reporting ولا يملكه النظام؟ في حالة Northwind كانت الإجابة الرسوم البيانية والجداول الكثيفة، وصارتا خارطة الطريق لربعَي السنة التاليين.

قول «لا»

النظام الذي يقول نعم لكل شيء يعود إلى الدرجات الرمادية الأربع والستين، بخطوات إضافية. تقول Northwind «لا» للمكوّنات الخاصة بفريق واحد، ولتغييرات السلوك الخاصة بعلامة، وللـ props التي تتجاوز الـ tokens، ولأي شيء يكسر مبدأً. والمهارة في قولها بطريقة تحفظ ثقة الفريق:

  1. سمِّ السبب، مستخدمًا المبدأ: «الألوان الخاصة بكل مكوّن ستكسر الوضع الداكن وTidewater، ومبدؤنا هو إمكانية الوصول قبل الجمال».
  2. قدّم بديلًا: بناءً محليًا من قطع النظام، أو مكوّنًا موجودًا بتوثيق أفضل، أو مخرجًا موثّقًا مثل component token.
  3. اكتبها في سجلّ القرارات، حتى يحصل الفريق التالي صاحب الطلب نفسه على الإجابة نفسها والبديل نفسه.
  4. اترك الباب مفتوحًا: «إن احتاج فريقان آخران هذا، أعيدوه إلى مراجعة الـ API».

أين وصلت الآن

تابعت Northwind UI من تدقيق 64 درجة رمادي إلى نظام يستخدمه أربعون فريقًا: مبادئ ونموذج فريق، وtokens في ثلاث طبقات مع themes وعلامات، ومكوّنات بـ APIs قابلة للتركيب وإمكانية وصول مبنية من الأساس، وإصدارات مرقّمة بمسارات deprecation واختبارات بصرية، وcontribution model مع governance ومقاييس. لا شيء من هذا منتهٍ، وهذا بالضبط معنى أن تديره كمنتج. في التمرين تكتب مسح التبنّي الذي يخبرك أين تنظر بعد ذلك.

أهم النقاط

  • قِس التبنّي بإشارات لا ينتجها إلا النظام الحقيقي، مثل استيراد الحزمة أو data attribute خاصة بالمكوّن، لا بأسماء classes يمكن نسخها.
  • تابع بضعة اتّجاهات معًا - تبنّي المكوّنات، وتغطية الـ tokens، وتأخّر الإصدارات، والرضا - لأن أي رقم منفرد يمكن التلاعب به.
  • استخدم المقاييس لتجد أين يخذل النظام الفرق، لا لتُخجل الفرق بسبب أرقامها المنخفضة أبدًا.
  • «لا» الجيدة تسمّي المبدأ، وتقدّم بديلًا، وتُكتب حتى يمكن مراجعتها بأدلّة جديدة.

قراءات إضافية

تحقّق من فهمك

3 أسئلة

السؤال 1 من 3

يضع نائب الرئيس في Northwind هدفًا «تبنٍّ لنظام التصميم بنسبة 100% بحلول الربع الرابع». ما الخطر الرئيسي؟

السؤال 2 من 3

أيّ إشارة هي الأكثر موثوقية لعدّ المواضع التي يُستخدم فيها Button الحقيقي من النظام في صفحات الإنتاج؟

السؤال 3 من 3

يطلب فريق التقارير prop باسم chartColors على كل مكوّن ليطابق لوحات المعلومات الخاصة به. كيف يجب أن يقول فريق النواة «لا»؟

تدريب

بيئة تجريب الكود

اكتب مسح التبنّي

اكتب الدالة measureAdoption(root) بحيث تمسح عناصر <button> داخل root (مستند أو أي عنصر) وتعيد { total, system, percent }:

  • total: عدد عناصر <button>،
  • system: عدد ما يحمل منها data-nw-component="Button"، وهي العلامة التي لا يعرضها إلا المكوّن الحقيقي (الـ class المسمّى nw-button لا يُحتسب؛ فقد نسخته الفرق)،
  • percent: ناتج system / total كعدد صحيح مقرَّب بـ Math.round، أو 0 حين لا توجد أزرار.

ثم اكتب نتيجة الصفحة داخل #report بالشكل 4 of 8 buttons use Northwind UI (50%)، مستخدمًا الأرقام التي حسبتها.

<header class="bar">
  <button class="nw-button" data-nw-component="Button" data-variant="primary">New shipment</button>
  <button class="btn-legacy">Export</button>
</header>
<main>
  <button class="nw-button" data-nw-component="Button">Filter</button>
  <button class="nw-button" data-nw-component="Button">Sort</button>
  <button class="nw-button">Refresh</button>
  <section id="settings">
    <button class="nw-button" data-nw-component="Button">Save</button>
    <button class="btn-legacy">Reset</button>
    <button class="nw-button">Advanced</button>
  </section>
</main>
<p id="report"></p>جارٍ تحميل المحرّر…

Ctrl/⌘ + Enter للتشغيل · يعمل في بيئة معزولة داخل متصفّحك. لا شيء يغادر جهازك.

المعاينة

الـ console

(لا مخرجات)

الفحوص

  • measureAdoption(document) تعيد 8 أزرار، 4 منها من النظام، أي 50%
  • الـ classes المنسوخة باسم nw-button لا تُحتسب تبنّيًا
  • مسح #settings وحده يعيد 1 من 3 ‏(33%)
  • يتحدّث العدد حين يُضاف زر من النظام إلى الصفحة
  • يعرض #report النص «4 of 8» و«50%»