
هل تتذكر آخر مرة واجهت فيها خطأ في واجهة المستخدم واستغرق إصلاحه ساعات وساعات؟ ربما حدث هذا الخطأ بشكل دوري دون سبب واضح. ربما ظهرت في ظل ظروف معينة (يمكن أن تعتمد على الجهاز أو نظام التشغيل أو المتصفح أو إجراءات المستخدم) أو هل كانت مخفية في مكان ما في أعماق إحدى تقنيات الواجهة الأمامية العديدة التي تشكل جزءًا من جانب العميل في مشروع الويب؟
كان علي مؤخرًا أن أتذكر كيف يمكن أن تكون أسباب أخطاء واجهة المستخدم مربكة. وبالتحديد ، نحن نتحدث عن إصلاح خطأ مثير للاهتمام يؤثر على إخراج صور SVG في متصفح Safari. حدث هذا الخطأ بدون أي نظام محدد وبدون سبب واضح. عندما واجهت مشكلة ، حاولت العثور على حالات مماثلة ، على أمل أن يعطيني وصف مثل هذه الحالات لمحة عما يحدث. لكنني لم أتمكن من العثور على أي شيء مفيد. صحيح ، بالرغم من كل العوائق التي كانت أمامي ، تمكنت من التغلب على هذا الخطأ.
لقد قمت بتحليل المشكلة باستخدام بعض استراتيجيات التصحيح التي سأغطيها في هذه المقالة. بعد أن تخلصت من الخطأ تذكرت النصيحةالذي قدمه كريس كويير لقرائه على Twitter قبل بضع سنوات. تذهب هذه النصيحة على النحو التالي: "اكتب المقالة التي ترغب في العثور عليها عند زيارة أحد محركات البحث." في الحقيقة ، هذا ما فعلته.
نظرة عامة على المشكلة
في مشروع كنت أعمل عليه في موقع مباشر ، وجدت خطأً ، وهو مظهر من مظاهره سجلت في هذا الفيديو. هذا ما يبدو عليه الزر في حالته الطبيعية.

الزر في الحالة العادية
وهنا الزر نفسه بعد حدوث مشكلة.

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

لماذا يتم اقتصاص صورة SVG؟
في كل مرة يقع فيها الحدث
paint، لا يتم عرض صور SVG المستخدمة في الأزرار الكبيرة بشكل صحيح. يتم اقتصاص هذه الصور ببساطة. يمكن أن يحدث هذا ، بدون سبب واضح ، عند تحميل الصفحة. يمكن أن يحدث هذا حتى عندما يتم تغيير حجم النافذة. بشكل عام ، يظهر الخطأ في مواقف متنوعة.
نظرة عامة على المشروع الذي حدث فيه الخطأ
أعتقد أنه عند الحديث عن الخطأ ، سيكون من الجيد الكشف عن تفاصيل حول المشروع وظروف حدوثه.
- يستخدم المشروع React (لكن قارئ هذه المقالة لا يحتاج إلى معرفة React لفهمها).
- يتم استيراد صور SVG إلى المشروع كمكونات React وتضمينها في HTML باستخدام حزمة الويب.
- . .
- CSS.
- , , HTML-
<button>. - Safari ( 13 ).
دعنا نلقي نظرة على الخطأ ونفكر فيما إذا كان بإمكاننا وضع أي افتراضات حول ما يجري. عادة لا تكمن أسباب مثل هذه الأخطاء في مكان ما على السطح ، لذلك ، في مواجهة مثل هذه الأخطاء ، لا يمكن للمرء أن يقول على الفور بثقة ما يحدث. في محاولتنا الأولى لفهم مشكلة ما ، لا يتعين علينا السعي لتحديد سببها بدقة 100٪. سنقوم بالتحقيق في الخطأ خطوة بخطوة ، وصياغة واختبار الفرضيات التي ستساعدنا في تضييق نطاق قائمة الأسباب المحتملة لما يحدث.
صياغة الفرضية
للوهلة الأولى ، يبدو أن ما يحدث خطأ في CSS. ربما ، عند تحريك الماوس فوق الزر ، يتم تطبيق بعض الأنماط عليه ، مما يؤدي إلى تعطيل التخطيط. ربما يتم إلقاء اللوم على سمة
overflowصورة SVG. بالإضافة إلى ذلك ، هناك شعور بحدوث خطأ بدون أي نظام محدد عند إعادة رسم الصفحة لأسباب مختلفة (حدث paintعند تغيير حجم نافذة المتصفح ، وعندما يكون مؤشر الماوس فوق الزر ، عند النقر فوقه ، وما إلى ذلك).
لنبدأ بأبسط الافتراضات وأكثرها وضوحًا. لنفترض أن الخطأ موجود في CSS. يمكننا أن نفترض أن هناك خطأ في متصفح Safari ينتج عنه إخراج SVG غير صحيح عند تطبيق أنماط معينة على عناصر SVG. على سبيل المثال ، مثل الأنماط المستخدمة لبناء تخطيطات مرنة.
لقد قمنا للتو بصياغة فرضية. خطوتنا التالية هي إجراء اختبار يؤكد أو يدحض هذه الفرضية. ستعطينا نتيجة كل اختبار معلومات جديدة حول الخطأ وستساعد في صياغة الفرضيات التالية.
تبسيط المشكلة
سوف نستخدم استراتيجية تصحيح تسمى "تبسيط المشكلة". سيتيح لنا ذلك تحديد الموقع الدقيق للخطأ. في إحدى المحاضرات حول علوم الكمبيوتر في جامعة كورنيل ، تم وصف هذه الاستراتيجية بأنها "نهج للتخلص التدريجي من التعليمات البرمجية التي لا تتعلق بالخطأ."
بافتراض أن الخطأ يكمن في CSS ، يمكننا في النهاية إما العثور على سبب الخطأ أو استبعاد CSS من المعادلة ، مما سيقلل من عدد الأسباب المحتملة للخطأ ويقلل من تعقيد المشكلة.
دعونا نختبر فرضيتنا. دعنا نحاول تأكيد ذلك. في هذه الحالة ، إذا عطلت مؤقتًا جميع الأنماط غير القياسية من الصفحة ، فمن المفترض أن يؤدي ذلك إلى عدم ظهور الخطأ مرة أخرى.
إليك الكود لتضمين ورقة الأنماط المناسبة:
import 'css/app.css';
لقد قمت بإنشاء مشروع CodePen هذا لتوضيح إخراج العناصر بدون CSS . في React ، يتم استيراد رسومات SVG إلى مشروع كمكون ، ثم يتم تضمين الكود المقابل في HTML باستخدام حزمة الويب.

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

استمر الخطأ حتى عندما تم تعطيل CSS (Safari 13)
نتيجة لذلك ، يمكننا أن نستنتج أن CSS لا علاقة له به. ومع ذلك ، يمكننا الانتباه إلى حقيقة أنه في مثل هذه الظروف ، يتم عرض اثنين فقط من الأزرار الخمسة بشكل غير صحيح. دعونا نتذكر هذا وننتقل إلى الفرضية التالية.
عزل الخطأ
فرضيتنا التالية هي أن Safari لديه خطأ عند عرض صور SVG داخل عناصر HTML
<button>. نظرًا لأن المشكلة تظهر عند عرض أول زرين ، فإننا نعزل الزر الأول ونرى ما سيحدث.
سارة درازنر في هذاتوضح المادة أهمية العزل. أوصي بشدة بقراءة هذه المادة لأي شخص مهتم بمزيد من التفاصيل حول أدوات التصحيح والأساليب المختلفة للعثور على الأخطاء. وإليك اقتباس من تلك المادة: "ربما يكون العزل أهم مبدأ أساسي لتصحيح الأخطاء. يمكن أن يكون الكود الذي يعمل في مشاريعنا مبعثرًا عبر مكتبات وأطر عمل مختلفة. قد يشارك العديد من الأشخاص في العمل في المشاريع ، وبعض أولئك الذين ساهموا في تطوير المشاريع لم يعودوا يعملون عليها. يساعدنا عزل المشكلة على قطع ما لا يتسبب في ظهور الخطأ ببطء. وهذا يسمح في النهاية باكتشاف مصدر المشكلة والتركيز عليه ".
غالبًا ما يشار إلى عزل الأعطال باسم " حالة اختبار الاختزال ".
قمت بنقل الزر إلى صفحة فارغة منفصلة (أنشأت اختبارًا منفصلًا له). وبالتحديد ، تم إنشاء مشروع CodePen هذا للتحقيق في زر منفصل. بينما توصلنا إلى أن CSS ليس سبب المشكلة ، نحتاج إلى ترك الأنماط معطلة حتى نكتشف السبب الحقيقي للمشكلة. سيسمح لنا هذا بجعل المشكلة بسيطة قدر الإمكان.

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

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

رسم توضع فيه الصورة الثانية فوق الأولى ، مشوهاً نتيجة خطأ
فرق تسد
تمكنا من إعادة إنتاج الخطأ باستخدام أقل عدد من العناصر التي يمثلها زوج من صور SVG. سنقوم الآن بتضييق نطاق المشكلة بشكل أكبر ، وتضييقها إلى الجزء المحدد من كود SVG الذي يمثل مصدر المشكلة. إذا فهمنا كود SVG بشكل عام وما زلنا نرغب في العثور على مصدر المشكلة ، فيمكننا حينئذٍ استخدام استراتيجية بحث عن شجرة ثنائية باستخدام نهج فرق وقهر. هنا مقتطف آخر من المحاضرةمن جامعة كورنيل لعلوم الكمبيوتر: "على سبيل المثال ، يمكنك البدء بفحص جزء كبير من التعليمات البرمجية ووضع رمز التحقق في منتصف الجزء الذي تفحصه. إذا لم يحدث خطأ هنا ، فهذا يعني أن مصدره موجود في النصف الثاني من الكود. وبخلاف ذلك ، يكون مصدره في النصف الأول من الكود ".
عند فحص كود SVG ، يمكنك محاولة إزالة عنصر
<filter>من وصف الصورة الأولى (وأيضًا <defs>، نظرًا لعدم وجود أي شيء في هذه الكتلة على أي حال). لنهتم بنوع المهام التي يحلها العنصر <filter>. يمكن العثور على تفسير رائع لهذا هنا . أي أننا نتحدث عما يلي: "لتطبيق المرشحات على صور SVG ، يوجد عنصر خاص يسمى<filter>... إنه يشبه بشكل أساسي العناصر المصممة للعمل مع التدرجات الخطية والأقنعة والقوالب والتأثيرات الرسومية الأخرى. <filter>لا يتم عرض العنصر من تلقاء نفسه. يتم استخدامه فقط كشيء يمكن الرجوع إليه باستخدام سمة filterفي كود SVG أو وظيفة url()في CSS. "
في صورة SVG الخاصة بنا ، يتم استخدام مرشح لإضافة ظل داخلي صغير أسفل الصورة. بعد إزالة الفلتر من كود الصورة الأولى ، ننتظر حتى يختفي هذا الظل. إذا استمرت المشكلة بعد ذلك ، فيمكننا أن نستنتج أن هناك خطأ ما في الكود الآخر لوصف عنصر SVG.
لقد قمت بإنشاء مشروع CodePen آخر لتوضيح نتائج هذا الاختبار.

عواقب إزالة عنصر <filter>
المشكلة ، كما ترى بسهولة ، لم تذهب إلى أي مكان. ويستمر عرض الظل الداخلي حتى بعد إزالة كود المرشح. ولكن الآن ، من بين أمور أخرى ، تظهر المشكلة في جميع المتصفحات. هذا يسمح لنا باستنتاج أن الخطأ موجود في مكان ما في بقية كود وصف الزر. إذا قمت بإزالة الباقي
idمن<g filter="url(#filter0_ii)">، ثم يختفي الظل. ماذا يحدث هنا؟
دعنا نلقي نظرة أخرى على التعريف أعلاه للعنصر
<filter>ونلاحظ الكلمات التالية: "<filter>لا يتم عرضالعنصربمفرده. يتم استخدامه فقط كشيء يمكن الرجوع إليه باستخدام سمةfilterفي SVG. " (لقد أبرزت جزءًا من النص).
لذلك ، بمعرفة ذلك ، يمكننا أن نستنتج أن إعلان المرشح من صورة SVG الثانية يتم تطبيقه على صورة SVG الأولى ، مما يؤدي إلى الخطأ.
إصلاح الخلل
نحن نعلم الآن أن مشكلتنا مرتبطة بالعناصر
<filter>. نعلم أيضًا أن كلا من SVG لهما هذا العنصر ، حيث يتم استخدام المرشح لإنشاء ظل داخلي دائري. دعنا نقارن كود صورتي SVG ونفكر فيما إذا كان بإمكاننا شرح الخطأ وإصلاحه.
لقد قمت بتبسيط رمز كلتا الصورتين بحيث يمكنك رؤية ما يحدث فيهما بوضوح.
هذا هو الكود الخاص بأول صورة SVG:
<svg width="46" height="46" viewBox="0 0 46 46">
<g filter="url(#filter0_ii)">
<!-- ... -->
</g>
<!-- ... -->
<defs>
<filter id="filter0_ii" x="0" y="0" width="46" height="46">
<!-- ... -->
</filter>
</defs>
</svg>
ها هو كود الصورة الثانية:
<svg width="28" height="28" viewBox="0 0 28 28">
<g filter="url(#filter0_ii)">
<!-- ... -->
</g>
<!-- ... -->
<defs>
<filter id="filter0_ii" x="0" y="0" width="28" height="28">
<!-- ... -->
</filter>
</defs>
</svg>
عند تحليل هذين الجزأين ، يمكنك ملاحظة أنه
id=filter0_iiتم استخدام نفس المعرف في البناء . يطبق Safari آخر تعريف مرشح تم تحليله في المتصفح على العناصر (في هذه الحالة ، مرشح الصورة الثانية). هذا يؤدي إلى حقيقة أن الصورة الأولى تم اقتصاصها. حجمه الأصلي 48px، وبعد تطبيق الفلتر ، يتم قطع قطعة منه 26px. idيجب أن يكون لخاصية DOM قيمة فريدة. إذا كان هناك عدة متطابقة على الصفحة id، فلن يتمكن المتصفح من معرفة أي منها يحتاج إلى استخدامه. وبما أنه يتم filterتجاوز الخاصية عند حدوث كل حدثpaint، إذن ، بناءً على أي من التعريفات سيكون جاهزًا أولاً (يحدث شيء مثل حالة السباق هنا) ، إما أن يظهر الخطأ أم لا.
دعنا نحاول تعيين قيم فريدة
idفي رمز كل صورة ونرى النتائج. هنا هو مشروع CodePen المقابل.

أدى تعيين معرفات فريدة إلى حل المشكلة
إذا قمت الآن بفتح المشروع في Safari والنقر فوق الزر ، فيمكنك التأكد من أننا حللنا المشكلة عن طريق تعيين
idعوامل تصفيةفريدةمستخدمة في صور SVG. إذا كنت تفكر في حقيقة أن المشروع يحتوي على قيم غير فريدة لسمة مثلid، فسيؤدي ذلك إلى استنتاج مفاده أن المشكلة يجب أن تظهر في جميع المتصفحات ، وليس فقط في Safari. ولكن لسبب ما ، يبدو أن المتصفحات الأخرى (بما في ذلك Chrome و Firefox) قد تعاملت مع هذا الموقف غير المعتاد دون أخطاء. قد تكون مجرد مصادفة.
النتيجة
كانت مغامرة أخرى! بدأنا نعلم فقط أن هناك نوعًا من الخطأ في المشروع ، والذي يظهر أحيانًا ثم لا يظهر ، ولكن في النهاية فهمنا تمامًا أسباب ما كان يحدث وتعاملنا مع المشكلة. قد يكون تصحيح أخطاء رمز واجهة المستخدم ومعرفة سبب تشويه الرسومات أمرًا صعبًا إذا لم تفهم ما يحدث. لكن لحسن الحظ ، توجد استراتيجيات تصحيح يمكن أن تساعدنا في العثور على السبب الجذري حتى لأكثر الأخطاء إرباكًا.
أولاً ، قمنا بتبسيط المشكلة من خلال صياغة فرضيات سمحت لنا بإزالة المكونات التي لم تكن مرتبطة بالخطأ (الأنماط ، الترميز ، الأحداث الديناميكية ، إلخ) من المشروع. بعد ذلك قمنا بعزل الترميز ووجدنا مثالًا بسيطًا يمكن استنساخه. سمح لنا هذا بالتركيز على جزء صغير من التعليمات البرمجية. وأخيراً حددنا المشكلة باستخدام إستراتيجية فرق تسد للتخلص من الخطأ.
شكرا لكل من أخذ الوقت الكافي لقراءة هذا المقال. ولكن ، قبل أن ننهي المحادثة ، دعني أخبرك عن استراتيجية تصحيح أخطاء أخرى مذكورة في المحاضرات.جامعة كورنيل. النقطة المهمة هي أنه في عملية العمل تحتاج إلى أخذ فترات راحة والراحة وتحرير رأسك من كل الأفكار: "إذا استغرق الأمر وقتًا طويلاً للتصحيح ، فسيصاب المبرمج بالتعب. قد يتضح أنه ، في مثل هذه الحالة ، يعمل عبثًا. في مثل هذا الموقف ، يجدر بك أخذ قسط من الراحة وإلقاء كل شيء من رأسك. وبعد فترة يجب أن تحاول النظر إلى المشكلة من وجهة نظر مختلفة ".
كيف تصلح الأخطاء غير المفهومة؟
