Yandex.Practicum محاكي الويب. كيف تعمل

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



في محاولة لفعل شيء مشابه ، أطلقنا مرة واحدة محاكي ويب في Yandex MVP ، حيث يمكن للمستخدم كتابة التعليمات البرمجية والنصوص وكل شيء آخر في علامات تبويب مختلفة ، وفي الجوار عرض كل هذا كنتيجة نهائية.







أظهر برنامج MVP نفسه جيدًا ، وأدخلنا محاكي الويب إلى مستوى أداة كاملة لاختبار معرفة طلابنا في Yandex . اسمي أرتيم ، وسأخبرك كيف صنعنا جهاز محاكاة لتعليم تطوير الويب ، وكيف يعمل وما يمكنه فعله.



من الخارج ، يبدو أن كل شيء بسيط هنا - لقد حشرت كل التعليمات البرمجية المخصصة في إطار iframe ، ونشرتها عبر رسالة بريدية ، ثم قمت بتقديمها بأي طريقة ممكنة ، وكل شيء يعمل. مثل هذا القليل من معاينة التعليمات البرمجية عبر الإنترنت.



لكن هناك فروق دقيقة.



كيف تعمل



في البداية ، لاحظنا مشكلة محتملة: إذا قمت بنشر المحاكي على مجال Yandex (مثل ورشة العمل نفسها ، على سبيل المثال) ، فهناك احتمال غير صفري أن المستخدمين سيصبحون أكثر فضولًا. وبالتحديد ، سوف يأخذون ويرمون بعض الأكواد في المحاكي ، والتي سيعالجها المحاكي بحماس. وسيتضح أن الكود احتيالي وسيزيل ملف تعريف ارتباط Yandex الحالي ، وإدخاله في بعض خدمات الطرف الثالث ، وبعد ذلك سيتمكن المحتال من الوصول إلى حساب المستخدم الشخصي في Yandex وجميع البيانات الشخصية. من السهل جدًا تنفيذ ذلك إذا كان إطار iframe هذا موجودًا في مجال yandex.ru. لذلك ، قمنا بإنشاء مجال منفصل على yandex.net خصيصًا لجهاز المحاكاة وأطلقنا عليه اسم Feynman. تكريما لريتشارد ، نعم.



بشكل عام ، يقوم جهاز المحاكاة الخاص بنا بتخزين الملفات التي نرسلها إليه في الخلفية بتنسيق نص عادي ، وتنسيقات json و base64 للصور. ثم يتم تحويلها إلى ملفات حقيقية وتوزيعها بالفعل في شكل ثابت ، والذي يمكننا وضعه في إطار iframe لتقديمه.



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







وهنا نصل مرة أخرى إلى المجالات. يتم وضع رمز المستخدم ، كما كتبت بالفعل ، في جهاز المحاكاة في مجال Feynman ، ونتحقق منه من Yandex ، من مجال praktikum.yandex.ru . تعتبر سياسة نفس المصدر للمتصفح على أهبة الاستعداد ولا تسمح لك بالتلاعب بالأجزاء الداخلية لإطار iframe إذا كان لديك نطاقات مختلفة.



لذلك ، قررنا حشر iframe في iframe.







تحول الوضع التالي:



  • نقوم بإنشاء إطار iframe ، وهو فارغ بالفعل في البداية.
  • يرسم نوعًا من الصفحات الفارغة.
  • نحن من بريدنا الأمامي رسالة بريدية تحتوي على رابط لما قدمه لنا فاينمان (من حيث يستضيف الإحصائيات).
  • يأخذ إطار iframe الأول هذا الرابط ويستبدله في src من إطار iframe الداخلي.


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



ليس بالاختبارات وحدها



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







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



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



لإرجاع نتيجة الاختبار الأولي للمستخدم ، نستخدم أيضًا postmessage - نرسل الرسائل من خلاله ، سواء كانت هناك أي أخطاء أو كل شيء رائع. بالمناسبة ، يتم أيضًا فحص رمز الطالب الموجود على محاكي الويب من خلال es-lint linter مع الترجمة إلى اللغة الروسية ويسلط الضوء دائمًا على أخطاء بناء الجملة.



مشاكل مع مراجعات الكود (وليس فقط)



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



بالمناسبة ، حول الحلقات اللانهائية. كانت المشكلة الرئيسية هنا هي أن المستخدم يمكنه عن عمد أن يأخذ ويكتب التعليمات البرمجية التي من شأنها أن تنتقل بسعادة إلى حلقة لا نهائية (لا يوجد سوى مؤشر ترابط جافا سكريبت واحد في المتصفح) ، ونتيجة لذلك ، ذهب المتصفح بأكمله للاستلقاء.



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



  • لكل دورة نضيف وظيفة معينة تحسب عدد المكالمات.
  • إذا تجاوز هذا العدد من المكالمات 100000 ، فسنطرح على الفور استثناءً ، ونرسله أيضًا عبر postmessage. بالإضافة إلى ذلك ، فقط في حالة حدوث ذلك ، نتحقق من المهلة إذا كانت الدورة تعمل لأكثر من 10 ثوانٍ.
  • على طول الطريق ، نتتبع ذلك ، نظرًا لظهور استثناء ، هناك خطأ ما هنا ، ولم يعد الاختبار نفسه منطقيًا - فالشفرة حلقية.


يجب ملاحظة الوضع مع الروابط بشكل منفصل. لنفترض أن المستخدم داخل الكود الخاص به قد يكون لديه بعض الروابط التي يجب أن تفتح عند النقر في علامة تبويب جديدة ، على سبيل المثال ، محفظته أو حساب جيثب. ولم نكن بحاجة إلى فتح مثل هذه الروابط مباشرة داخل iframe - وإلا ، فبدلاً من iframe ، سيكون لدينا صفحة بها رابطها. من الضروري فتح مثل هذه الأشياء في علامة تبويب جديدة ، عبر Tab. عادة ، لفتح ارتباط ليس داخل الإطار ، ولكن في الإطار الأصلي ، تحتاج فقط إلى تحديد الهدف = "_ الأصل". لكن في حالتنا ، احتجنا إلى إضافة معالج يحدد ما إذا كان الارتباط خارجيًا.



وبالنسبة لجميع الروابط ، كتبنا معالجًا خاصًا: إذا رأينا أن الرابط خارجي ، فسنرسل رسالة postmessage للخارج ، ونقطع معالج الارتباط نفسه (منع الافتراضي) ، ويعود postmessage إلى المقدمة. نرى أن لدينا رابطًا خارجيًا هنا ، ونعرض إشعارًا - هل نحن متأكدون من أننا ذاهبون إلى موقع خارجي؟ وبعد ذلك نفتح علامات تبويب جديدة.



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



جميع البيانات الوصفية (إذا كان لدى المستخدم رمز مفضل مسجل في صفحة HTML ، على سبيل المثال ، أو عنوان محدد) ، فإننا نرسل أيضًا عبر postmessage بعد تحميل إطار iframe. باستخدام أداة تحديد الاستعلام ، نحصل على هاتين العلامتين ، ونرسلهما مرة أخرى إلى الأمام من خلال postmessage ، وتقوم الواجهة نفسها بإدراج كل هذه الرموز عند الضرورة. يبدو أنه أمر تافه ، ولكن لدى المستخدم انطباع بأن لديه متصفحًا كاملاً داخل المتصفح.



محاولات لتجاوز جهاز المحاكاة



يستخدم محاكي الويب الخاص بنا ، بخلاف المحاكيات التي صنعناها لـ Python و SQL وغيرها ، الواجهة الأمامية ، وليس الخلفية ، لإجراء عمليات الفحص. لذلك ، عندما يكمل المستخدم الاختبارات بشكل صحيح ، يتم إرسال طلب POST المقابل إلى الواجهة الخلفية. من حيث المبدأ ، يمكن للمستخدم ، بالمهارة المناسبة ، فعل الشيء نفسه وإرسال مثل هذا الطلب يدويًا.



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



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



نحن نعمل باستمرار على تحسين محاكي الويب ، باستخدام كل من قائمة الرغبات الخاصة بنا وردود الفعل من المستخدمين ، لذلك سنواصل إخبارك عن تطويره. الآن يتم الانتهاء منه ، مع مراعاة احتياجات الطلاب الذين لديهم طلب لتقنيات محددة ، على سبيل المثال ، أضفنا العمل مع React و NodeJS. يعد محاكي الويب هو الأكثر شعبية على الإطلاق ، ويليه محاكي Python - ويرجع ذلك إلى حد كبير إلى كل من الحد الأدنى للدخول وشعبية التقنيات نفسها. بالإضافة إلى الجزء الفني ، هناك أيضًا العديد من الميكانيكا داخل جهاز المحاكاة للعمل مع النظرية التفاعلية (وهناك ما يكفي منها في جميع دوراتنا). لا يوجد جهاز محاكاة منفصل فقط لتخصص ضمان الجودة ، حيث قمنا بعمل مجموعة خاصة من الاختبارات + المواقف التي يدرس عليها المختبرين. بالمناسبة ، اثنان من المختبرين ،الذين يساعدوننا الآن في تنظيم ورشة العمل هم من خريجينادورة ضمان الجودة .



تعد محاكيات C ++ ومحاكي التعلم الآلي أكثر تعقيدًا ، إذا كنت مهتمًا ، فسنحاول التحدث عنها في المنشورات التالية.



شكرًا على القراءة ، إذا كان لديك أي أسئلة حول أجهزة المحاكاة الخاصة بنا أو حول ورشة العمل بشكل عام - اكتب ، وسنجيب.



All Articles