مرحبا ، اسمي ... رجل. عدد اليدين هو 2. عدد الساقين هو 2. فصيلة الدم هي 1. ريزوس صحيح.
قد يبدو لك أنه من خلال هذه المعلومات فقط ، بدون اسم أو لقب أو حتى اسم مستعار ، من الصعب التمييز بيني وبين العديد من مؤلفي المقالات الآخرين. وسوف تكون على حق. ومع ذلك ، في النهاية الأمامية ، أرى غالبًا كيف يتم استبدال اسم العنصر بوصفه. ولا أحد يهتم.

امتلك مقعدًا ، تنتظرك رحلة رائعة أمام المشكلات الخطيرة للمشاريع الخطيرة ، والتي غالباً ما يتم التقليل من قيمتها.
اختبارات
تخيل نفسك ككاتب لاختبارات تلقائية شاملة. تحتاج إلى اختبار ذلك ، على سبيل المثال ، في Yandex في الزاوية اليمنى العليا يتم عرض الاسم الصحيح للمستخدم الذي قام بتسجيل الدخول.

أعط هذه الصفحة لمصمم تخطيط نموذجي وسيمنحك شيئًا مثل هذا:
<body> <aside> <div class="card"> <div class="username">admin</div> </div> </aside> <section> </section> </body>
ردم السؤال: كيفية العثور على عنصر المنزل حيث يتم عرض اسم المستخدم؟

هنا يمتلك المختبر إمكانية اختيار كرسيين:
- اكتب محدد css أو xpath للنموذج
aside > .card > .username
و صلّي حتى لا تظهر أي بطاقات أخرى في الشريط الجانبي. ولم تظهر أي أسماء مستخدمين أخرى على البطاقة. وحتى لا أحد غيره إلى أي زر. ولم يلفها في أي مأخذ. باختصار ، هذا محدد هش للغاية ، والذي سيؤدي استخدامه إلى كسر الاختبارات في أدنى التغييرات على الصفحة. - اطلب من المطور إضافة معرف فريد للصفحة . هذه هي الطريقة الصحيحة لتحمل غضب المطور. بعد كل شيء ، لديه كل شيء على المكونات. ويتم عرض المكونات كثيرًا فيها ، ولا تعرف (ولا ينبغي أن تعرف) أي شيء عن التطبيق. من السذاجة الاعتقاد بأن أي مكون سيكون دائمًا على الصفحة في نسخة واحدة ، مما يعني أنه لا يمكن خياطة المعرف في المكون نفسه. ولكن على مستوى التطبيق ، هناك فقط استخدام مكون LegoSidebar. وإلقاء المعرفات عبر عدة مستويات من تداخل المكونات يعد أيضًا فرصة.
كما ترون ، خيار واحد هو أسوأ من الآخر - يعاني إما المطورين أو المختبرين. علاوة على ذلك ، كقاعدة عامة ، تحيز تجاه الأخير. لأنهم يدخلون العمل كقاعدة ، عندما يكون الأول قد أكمل بالفعل تطوير هذه الميزة ، ويقومون بقص الآخر بالقوة والرئيسية.
دعونا نرى كيف تعامل مصممو التخطيط من Yandex مع تخطيط هذه الكتلة البسيطة (اضطررت إلى إزالة 90 ٪ من القمامة بحيث كان الجوهر مرئيًا):
<div class="desk-notif-card"> <div class="desk-notif-card__card"> <div class="desk-notif-card__domik-user usermenu-link"> <a class="home-link usermenu-link__control" href="https://passport.yandex.ru"> <span class="username desk-notif-card__user-name">admin</span> </a> </div> </div> </div>
بفضل BEM ، يحتوي العنصر الذي نحتاج إليه على معلومات في اسم الفصل الدراسي حول السياق بمستوى أعلى (نوع من اسم المستخدم في بعض البطاقات). ولكن هل يمكنك التأكد من أن هذه البطاقة ستكون دائمًا وحدك على الصفحة؟ افتراض جريء. لذلك ، مرة أخرى ، عليك أن تختار بين اثنين من البراز.

وإليك مثال آخر في حقل البحث حيث أجبر المطور على وضع معرف. حسنًا ، قال:
<input class="input__control input__input" id="text" name="text" />
هل المطور سيء؟ لا ، البنية السيئة التي لا تساعد على إنشاء معرفات فريدة من نوعها على مستوى العالم.
إحصائيات
تخيل نفسك كمحلل. عليك أن تفهم لماذا ينقر المستخدمون غالبًا لفتح قائمة الحساب في الشريط الجانبي لـ Yandex : حسب اسم المستخدم أو بواسطة صورة الملف الشخصي.

أنت بحاجة إلى معلومات في الوقت الحالي ، لذلك لا يوجد لديك سوى مقعد واحد - العمل مع الإحصاءات التي تم جمعها بالفعل. حتى إذا تأكد المطورون من أن جميع النقرات على جميع الصفحات قد تم تسجيلها بالفعل مع الحفاظ على التسلسل الهرمي للعناصر بأكملها في وقت النقرة ، فلا يزال بإمكانك عمل المحدد الصحيح لتصفية النقرات اللازمة. وحتى إذا طلبت من المطور القيام بذلك ، فمن المحتمل أيضًا أن يرتكب خطأ في مكان ما. خاصة إذا كان التخطيط قد تغير مع مرور الوقت.
أي أنك تحتاج إلى معرفات فريدة عالمية للعناصر التي تحتاج إليها. وعلاوة على ذلك ، الملصقة بشكل جيد للغاية مقدما. ولكن نظرًا لأن غالبية المطورين يتعاملون بشكل سيء مع التنبؤ الدقيق للمستقبل ، فإن هذا يبدو عادةً كما يلي: يأتي المحلل إلى المطورين ويسأل عن المعرف ، ويتلقى المعلومات في أفضل الأحوال خلال شهر.

في حالة ياندكس ، تبدو ثمرة الجهود البطولية للمطورين كما يلي:
<div class="desk-notif-card__domik-user usermenu-link"> <a class="home-link usermenu-link__control" href="https://passport.yandex.ru" data-statlog="notifications.mail.login.usermenu.toggle" > </a> <a class="home-link desk-notif-card__user-icon-link usermenu-link__control avatar" href="https://passport.yandex.ru" data-statlog="notifications.mail.login.usermenu.toggle-icon" > </a> </div>
أوه ، وكيف سيكون من الرائع لأي عنصر أن يكون له دائمًا هذه المعرّفات. بحيث تكون مفهومة أيضًا للإنسان. وفي الوقت نفسه كانت مستقرة ، ولم يتغير مع أي تغيير في التخطيط. ولكن مع ناقل الحركة اليدوي ، لا يمكن تحقيق السعادة.
الأنماط
تخيل نفسك كمصمم تخطيط. تحتاج إلى تصميم اسم المستخدم في البطاقة في الشريط الجانبي Yandex بشكل خاص. سوف نجعل النهج الأول للقذيفة ، دون استخدام BEM. هنا هو المكون الخاص بك:
const Morda = ()=> <div class="morda"> {} <LegoSidebar /> </div>
وهنا حزمة من المكونات التي يدعمها مختلف اللاعبين تماما:
const LegoSidebar = ( { username } )=> <aside className="lego-sidebar"> <LegoCard> <LegoUsername>{ username }</LegoUsername> </LegoCard> </aside> const LegoCard = ( {} , ... children )=> <div className="lego-card"> { ... children } </div> const LegoUsername = ( {} , ... children )=> <div className="lego-username"> { ... children } </div>
الكل في الكل يعطي النتيجة التالية:
<body class="morda"> <aside class="lego-sidebar"> <div class="lego-card"> <div class="lego-username">admin</div> </div> </aside> </body>

إذا تم استخدام عزل الأنماط ، فلن يكون لديك ما تجلس عليه. قف وانتظر هؤلاء الأشخاص الآخرين لإضافة فئة مخصصة لمكوناتهم من خلال LegoSidebar ، إلى LegoUsername:
const LegoSidebar = ( { username , rootClass , cardClass , usernameClass } )=> <aside className={ "lego-sidebar " + rootClass }> <LegoCard rootClass={ cardClass }> <LegoUsername rootClass={ usernameClass}>{ username }</LegoUsername> </LegoCard> </aside> const LegoCard = ( { rootClass } , ... children )=> <div className={ "lego-card " + rootClass }> { ... children } </div> const LegoUsername = ( { rootClass } , ... children )=> <div className={ "lego-username " + rootClass }> { ... children } </div>
ومن الجيد أن يتم دمجها مباشرة في بعضها البعض ، وليس من خلال عشرات المكونات الوسيطة. خلاف ذلك ، سوف يموتون تحت عبء المعكرونة من نسخ لصق.

إذا لم يتم استخدام العزل ، فمرحبا بكم في كرسي مصنوع من محددات هشة:
.morda .lego-sidebar > .lego-card > .lego-username:first-letter { color : inherit; }
ومع ذلك ، إذا كان لدينا أداة تأخذ الأسماء المحلية:
const Morda = ()=> <div> {} <Lego_sidebar id="sidebar" /> </div> const Lego_sidebar = ( { username } )=> <aside> <Lego_card id="profile"> <Lego_username id="username">{ username }</Lego_username> </Lego_card> </aside> const Lego_card = ( {} , ... children )=> <div> { ... children } </div> const Lego_username = ( {} , ... children )=> <div> { ... children } </div>
أود أن أقوم بتوحيدها مع الأخذ في الاعتبار تداخل المكونات ، وإنشاء فئات وصولاً إلى جذر التطبيق:
<body class="morda"> <aside class="lego_sidebar morda_sidebar"> <div class="lego_card lego_sidebar_profile morda_sidebar_profile"> <div class="lego_username lego_sidebar_username morda_sidebar_username">admin</div> </div> </aside> </body>
بعد ذلك يمكننا أن نسلب أي عنصر ، بغض النظر عن عمقه:
.morda_sidebar_username:first-letter { color : inherit; }
لا ، إنه رائع. هذا لا يحدث.

نقل البند
تخيل نفسك كمطور لمكتبة تقديم. تسمح الخوارزميات التفاعلية عالية الأداء باستخدام VirtualDOM و IncrementalDOM و DOM Batching وغيرها من WhateverDOM بتوليد هذا النوع من DOM بلوحة scrum في بضع ثوانٍ فقط:
<div class="dashboard"> <div class="column-todo"> <div class="task"> </div> </div> <div class="column-wip"> </div> <div class="column-done"> </div> </div>
من هذا النوع من الحالات:
{ todo : [ { }, ] , wip : [] , done : [] , }
وإليكم الحظ السيئ: يبدأ المستخدم في سحب المهام وإلقائها ذهابًا وإيابًا ويتوقع حدوث ذلك سريعًا. يبدو أنك تحتاج فقط إلى أخذ عنصر DOM للمهمة ونقله إلى مكان آخر في DOM-e. ولكن سيتعين عليك العمل يدويًا مع DOM والتأكد من أن المهام في جميع الأماكن يتم تقديمها دائمًا في نفس شجرة DOM ، والتي عادة ما لا تكون كذلك - عادة ما تكون هناك اختلافات بسيطة. باختصار ، فإن تغيير DOM يدويًا يشبه الجلوس على دراجة هوائية: حركة واحدة غير مقصودة ولن ينقذك شيء من الجاذبية. من الضروري شرح نظام التقديم بطريقة أو بأخرى بحيث يفهم أين تم نقل المهمة ، وأين تم حذف أحدهم وتم إضافة الآخر.

لحل هذه المشكلة ، من الضروري تجهيز طرق العرض بمعرفات. في حالة تطابق المعرفات ، يمكن ببساطة نقل العرض المقدم إلى موقع جديد. إذا لم تتطابق ، فهذه كيانات مختلفة وتحتاج إلى تدمير واحد وإنشاء كيان آخر. من المهم ألا تتكرر المعرفات ، ولا يمكن أن تتزامن بالصدفة.
أثناء قيامك بنقل عناصر داخل نفس عنصر DOM الأصلي ، يمكن أن تساعدك السمة الرئيسية من React ومعلمة ngForTrackBy من Angular والأشياء المماثلة في أطر عمل أخرى. لكن هذه قرارات خاصة للغاية. يجدر نقل المهمة إلى عمود آخر ، وكل هذه التحسينات تتوقف عن العمل.
ولكن إذا كان لكل عنصر DOM معرف فريد عالميًا ، بغض النظر عن مكان تقديم هذا العنصر ، فإن استخدام getElementById
سيعيد استخدام شجرة DOM الحالية بسرعة عند نقل كيان من مكان إلى آخر. على عكس العكازات الخاصة بقوائم العرض المذكورة أعلاه ، تعمل المعرفات العالمية على حل المشكلة بشكل منهجي ولن تنكسر حتى إذا ظهرت التجمعات أو بعض الألعاب الأخرى في الأعمدة:
<div id="/dashboard"> <div id="/dashboard/column-todo"> <div id="/dashboard/todo/priority=critical"> <div id="/dashboard/task=y43uy4t6"> </div> </div> </div> <div id="/dashboard/column-wip"> <div id="/dashboard/wip/assignee=jin"></div> </div> <div id="/dashboard/column-done"> <div id="/dashboard/done/release=0.9.9"></div> </div> </div>

دلالات
تخيل نفسك كمصمم تخطيط. وتحتاج إلى إضافة div
هناك. قدمت؟ الآن تقتل نفسك. أنت تالف بالفعل بواسطة html.
في الواقع ، لا تحتاج إلى إضافة div
، ولكن كتلة اسم البطاقة. title
- اسم هذه الكتلة ، مما يعكس دلالاتها في مكان الاستخدام. div
هي نوع من البلوك يعكس مظهره وسلوكه ، بغض النظر عن مكان استخدامه. إذا كنا ننضج على TypeScript ، فسيتم التعبير عنه بالشكل التالي:
const Title : DIV
يمكننا على الفور إنشاء مثيل من النوع:
const Title : DIV = new DIV({ children : [ taskName ] })
ودع البرنامج النصي الوقت يطبع النوع تلقائيًا:
const Title = new DIV({ children : [ taskName ] })
حسنًا ، هنا ، حتى HTML ليس بعيدًا:
const Title = <div>{ taskName }</div>
لاحظ أن Title
ليس مجرد اسم متغير عشوائي يُستخدم ويتم التخلص منه. هذا هو الدلالات الأساسية لهذا العنصر. ولكي لا تفقدها ، يجب أن تنعكس نتيجة:
const Title = <div id="title">{ taskName }</div>
ومرة أخرى نتخلص من علم التروتولوجيا:
<div id="title">{ taskName }</div>
أضف العناصر المتبقية:
<div id="task"> <div id="title">{ taskName }</div> <div id="deadline">{ taskDue }</div> <div id="description">{ taskDescription }</div> </div>
لاحظ أنه بالإضافة إلى عنوان بطاقة المهمة ، يمكن أن يكون هناك العديد من الرؤوس الأخرى ، بما في ذلك رؤوس البطاقات للمهام الأخرى:
<div id="/dashboar/column-todo"> <div id="/dashboard/column-todo/title">To Do</div> <div id="/dashboard/task=fh5yfp6e"> <div id="/dashboard/task=fh5yfp6e/title">{ taskName }</div> <div id="/dashboard/task=fh5yfp6e/deadline">{ taskDue }</div> <div id="/dashboard/task=fh5yfp6e/description">{ taskDescription }</div> </div> <div id="/dashboard/task=fhty50or"> <div id="/dashboard/task=fhty50or/title">{ taskName }</div> <div id="/dashboard/task=fhty50or/deadline">{ taskDue }</div> <div id="/dashboard/task=fhty50or/description">{ taskDescription }</div> </div> </div>
وبالتالي ، تتشكل معرفات لكل عنصر من العناصر القابلة للقراءة التي تعكس بدقة دلالاتها وبالتالي فهي فريدة من نوعها على مستوى العالم.
يرجى ملاحظة أنه يتم تحديد الدلالات حسب العضوية ، وليس الموقع. على الرغم من أن بطاقة /dashboard/task=fh5yfp6e
موجودة في عمود /dashboard/todo
، إلا أنها تنتمي إلى /dashboard
. كان هو الذي خلقها. لقد وضعه. أعطاها اسمًا وضمن تفرد معرفها. يسيطر عليه بالكامل. سوف يدمرها.

لكن استخدام "علامات html الصحيحة" ليس دلالات ، إنه كتابة:
<section id="/dashboard/column-todo"> <h4 id="/dashboard/column-todo/title">To Do</h4> <figure id="/dashboard/task=fh5yfp6e"> <h5 id="/dashboard/task=fh5yfp6e/title">{ taskName }</h5> <time id="/dashboard/task=fh5yfp6e/created">{ taskCreated }</time> <time id="/dashboard/task=fh5yfp6e/deadline">{ taskDue }</time> <div id="/dashboard/task=fh5yfp6e/description">{ taskDescription }</div> </figure> </section>
إيلاء الاهتمام لاثنين من علامات time
مع دلالات مختلفة تماما.
التعريب
تخيل نفسك كمترجم. لديك مهمة بسيطة للغاية - ترجمة سطر من النص من الإنجليزية إلى الروسية. حصلت على السلسلة "تم". إذا كان هذا الإجراء ، فأنت بحاجة إلى ترجمة كـ "مكتمل" ، وإذا كانت الحالة ، ثم "مكتملة" ، ولكن إذا كانت هذه هي حالة المهمة ، ثم "مكتملة". بدون معلومات حول سياق الاستخدام ، يستحيل ترجمة النص بشكل صحيح. وهنا المطور مرة أخرى اثنين من المحلات التجارية:
- توفير النصوص مع تعليقات مع معلومات السياق. والتعليقات كسول جدا في الكتابة. ومدى اكتمال المعلومات غير واضح. ويتم الحصول على المزيد من التعليمات البرمجية بالفعل أكثر من تلقي النصوص حسب المفتاح.
- تلقي النصوص حسب المفتاح ، وبعد قراءة والتي يمكنك فهم سياق الاستخدام. لا يتم ضمان اكتمال المعلومات يدويًا ، لكنه سيكون فريدًا على الأقل.

ولكن ماذا لو كنا لا نريد بأي حال كيف نجلس ، ولكن نريد أن نقف بفخر على أساس راسخ من أفضل الممارسات؟ نحتاج بعد ذلك إلى استخدام مزيج من اسم النوع (المكون ، القالب) ، والاسم المحلي للعنصر داخل هذا النوع ، واسم ملكيته كمفتاح. بالنسبة للنص "تم" كاسم للعمود ، سيكون هذا المفتاح هو github_issues_dashboard:column-done:title
. وبالنسبة للنص "تم" الموجود على زر إكمال المهمة في بطاقة المهمة ، سيكون المعرف بالفعل github_issues_task-card:button-done:label
). هذه ، بالطبع ، ليست المعرفات التي تحدثنا عنها سابقًا ، ولكن هذه المفاتيح تتشكل من نفس الأسماء التي نعطيها بشكل صريح أو ضمني للعناصر المكونة. إذا قمنا بتسميتها بشكل صريح ، فلدينا الفرصة لأتمتة إنشاء المفاتيح والمعرّفات المختلفة. ولكن إذا كان ذلك ضمنيًا ، فيجب عليك تعيين هذه المفاتيح والمعرفات يدويًا ونأمل ألا تندلع الفوضى التي تحمل اسم نفس الكيان في أماكن مختلفة بطرق مختلفة.
التصحيح
تخيل نفسك كمطور تطبيق. يصل تقرير الأخطاء إليك:
! ! , : Uncaught TypeError: f is not a function at <Button> at <Panel> at <App>
"نعم ، نفس الشهرة الشهيرة من زر ما ، على لوحة ،" يقول خبير الأريكة ، "كل شيء واضح".

أم لا؟ وإذا كان مجرد معرف فريد واحد:
/morda/sidebar/close
- نعم ، زر إغلاق الشريط الجانبي مكسور. VasyaPas ، وهذا هو لك ، انتقلوا لفات.
يجلس Vasya في مرفق ، ويدفع المعرف المستلم إلى وحدة التحكم في التطوير ، ثم يتلقى مثيلًا للمكون ، حيث يتضح على الفور أن شخصًا ذكيًا قام بتمرير الخط إلى الزر كمعالج نقرات:

من الجيد أن يكون لكل مكون معرف. وبواسطة هذا المعرف ، من السهل الحصول على هذا المكون ، دون الرقص حول مصحح الأخطاء. صحيح ، نحن بحاجة إلى أداة تسمح لك بالعثور على مكون بواسطة المعرف. ولكن ماذا لو كان المعرف نفسه هو رمز البرنامج للحصول على المكون؟
<button id="Components['/morda/sidebar/close']">X</button>
بعد ذلك ، يمكن نسخ هذا الرمز مباشرة إلى وحدة التحكم للوصول السريع إلى حالة المكون ، بغض النظر عن عدد المرات التي نقوم فيها بإعادة تحميل الصفحة وتغيير الرمز.
ما يجب القيام به
إذا كنت تستخدم $ mol ، فأنت لست بحاجة إلى فعل أي شيء - ما عليك سوى الجلوس والحصول على تدليك الاهتزاز بالكامل:
$ya_morda $mol_view sub / <= Sidebar $ya_lego_sidebar $ya_lego_sidebar $mol_view sub / <= Profile $ya_lego_card sub / <= Username $ya_lego_username sub / <= username \ $ya_lego_card $mol_view $ya_lego_username $mol_view
لا يمكن للمبرمج ببساطة أن يفشل في إعطاء اسم فريد للمكون. يتم إنشاء DOM التالي من وصف المكون هذا:
<body id="$ya_morda.Root(0)" ya_morda mol_view > <ya_lego_sidebar id="$ya_morda.Root(0).Sidebar()" ya_lego_sidebar mol_view ya_morda_sidebar > <ya_lego_card id="$ya_morda.Root(0).Sidebar().Profile()" ya_lego_card mol_view ya_lego_sidebar_profile ya_morda_sidebar_profile > <ya_lego_username id="$ya_morda.Root(0).Sidebar().Username()" ya_lego_username mol_view ya_lego_sidebar_username ya_morda_sidebar_username > admin </ya_lego_username> </ya_lego_card> </ya_lego_sidebar> </body>
الرمز في المعرفات ليس فريدًا على مستوى العالم فحسب ، بل هو أيضًا واجهة برمجة تطبيقات يمكنك من خلالها الوصول إلى أي مكون. حسنًا ، stektrays مجرد حكاية خرافية:
Uncaught (in promise) Error: Test error at $mol_state_local.value("mol-todos-85").calculate at $mol_state_local.value("mol-todos-85").pull at $mol_state_local.value("mol-todos-85").update at $mol_state_local.value("mol-todos-85").get at $mol_app_todomvc.Root(0).task at $mol_app_todomvc.Root(0).task_title at $mol_app_todomvc.Root(0).task_title(85).calculate at $mol_app_todomvc.Root(0).task_title(85).pull at $mol_app_todomvc.Root(0).task_title(85).update at $mol_app_todomvc.Root(0).task_title(85).get at $mol_app_todomvc.Root(0).Task_row(85).title at $mol_app_todomvc.Root(0).Task_row(85).Title().value at $mol_app_todomvc.Root(0).Task_row(85).Title().event_change

إذا كنت مدمن مخدرات على React ، فيمكنك التحويل إلى محول JSX مخصص لإنشاء معرفات فريدة على مستوى العالم من خلال أسماء محلية للعناصر المضمنة في المكون. يمكنك أن تفعل الشيء نفسه مع جيل من الطبقات للتصميم. على سبيل المثال مع لوحة القيادة ، تبدو القوالب مثل هذا:
const Dashboard = ()=> ( <div> <Column id="/column-todo" title="To Do"> <Task id="/task=fh5yfp6e" title="foobar" deadline="yesterday" content="Do it fast!" /> </Column> <Column id="/column-wip" title="WIP" /> <Column id="/column-done" title="Done" /> </div> ) const Column = ( { title } , ... tasks )=> ( <div> <div id="/title">{ title }</div> { tasks } </div> ) const Task = ({ title , deadline , description })=> ( <div> <div id="/title">{ title }</div> <div id="/deadline">{ deadline }</div> <div id="/description">{ description }</div> </div> ) const App = ()=> <Dashboard id="/dashboard" />
في انتاج توليد:
<div id="/dashboar"> <div id="/dashboar/column-todo"> <div id="/dashboard/column-todo/title">To Do</div> <div id="/dashboard/task=fh5yfp6e"> <div id="/dashboard/task=fh5yfp6e/title">foobar</div> <div id="/dashboard/task=fh5yfp6e/deadline">yesterday</div> <div id="/dashboard/task=fh5yfp6e/description">Do it fast!</div> </div> </div> <div id="/dashboar/wip"> <div id="/dashboard/column-wip/title">WIP</div> </div> <div id="/dashboar/done"> <div id="/dashboard/column-done/title">Done</div> </div> </div>

إذا كنت رهينة لأي إطار عمل آخر ، فقم بإنشائه لمؤلفي المشكلات لإضافة القدرة الاختيارية على إنشاء معرفات وفئات. أو على الأقل لإضافة API يمكن من خلالها تنفيذ هذه الميزات بشكل مستقل.
بإيجاز ، أذكرك لماذا تحتاج إلى إعطاء أسماء فريدة لجميع العناصر:
- بساطة وثبات اختبارات E2E.
- سهولة جمع إحصائيات استخدام التطبيق وتحليله.
- سهل التصميم.
- تقديم الكفاءة.
- دلالات دقيقة وشاملة.
- سهولة التوطين.
- سهولة التصحيح.