تحديث بنية أدوات مطوّري البرامج: نقل أدوات مطوّري البرامج إلى TypeScript

Tim van der Lippe
Tim van der Lippe

تشكّل هذه المشاركة جزءًا من سلسلة من مشاركات المدوّنات التي تصف التغييرات التي نُجريها على بنية أدوات مطوّري البرامج وكيفية إنشائها.

في إطار عملية نقل البيانات إلى وحدات JavaScript والانتقال إلى مكونات الويب، نواصل اليوم نشر سلسلة مشاركات المدونة حول التغييرات التي نُجريها على بنية أدوات مطوّري البرامج وكيفية إنشائها. (لقد نشرنا فيديو حول ترقية بنية أدوات مطوّري البرامج إلى شبكة الويب الحديثة، إذا لم يسبق لكم ذلك، ويتضمّن 14 نصيحة حول كيفية إجراء تحسينات على مشاريع الويب).

في هذه المشاركة، سنوضّح مسيرتنا التي تمتدّ على 13 شهرًا للانتقال من أداة التحقّق من نوع مجمّع الإغلاق إلى TypeScript.

مقدمة

نظرًا لحجم قاعدة رموز أدوات مطوّري البرامج والحاجة إلى توفير الثقة للمهندسين الذين يعملون على تطويرها، من الضروري استخدام مدقق النوع. تحقيقًا لهذه الغاية، اعتمدت أدوات مطوّري البرامج أداة Closure Compiler في عام 2013. وساهم اعتماد مهندسي أدوات مطوّري البرامج في إجراء التغييرات بثقة. ويُجري برنامج تجميع Closure عمليات التحقق من النوع لضمان كتابة جميع عمليات دمج النظام بشكل جيد.

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

تقييم أدوات فحص الأنواع

بما أنّ أدوات مطوّري البرامج كانت تستخدم مدققًا من النوع، كان السؤال الذي كان ينبغي لنا الإجابة عنه هو:

هل نواصل استخدام Closure Compiler أو ننتقل إلى مدقق نوع جديد؟

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

ركّز تقييمنا على الانحدارات التي دفعناها وتحديد الأسباب الأساسية لهذه الانحدارات. يتلخص الافتراض هنا في أنه نظرًا لأننا كنا نستخدم Closure Compiler بالفعل، فلن يكتشف Closure هذه المشكلات. وبالتالي، سيتعين علينا تحديد ما إذا كان بإمكان أي أداة فحص لنوع آخر القيام بذلك.

صحة الكتابة في TypeScript

وحيث إن TypeScript كانت لغة برمجة معتمدة رسميًا في Google وزادت شعبيتها سريعًا، فقد قررنا تقييم TypeScript أولاً. كان TypeScript خيارًا مثيرًا للاهتمام حيث كان فريق TypeScript نفسه يستخدم أدوات مطوّري البرامج باعتباره أحد مشاريع الاختبار لتتبُّع مدى توافقه مع فحص نوع JavaScript. أظهرت نتيجة اختبار المرجع الأساسي أنّ TypeScript كانت تواجه عددًا كبيرًا من المشاكل في النوع، وهي مشاكل لم يرصدها بالضرورة برنامج تجميع Closure. كان من المحتمل أن تكون العديد من هذه المشاكل السبب الأساسي للانحدار الذي كنا نشحنه، وهذا بدوره جعلنا نعتقد أنّ TypeScript قد يكون خيارًا قابلاً للتطبيق لـ "أدوات مطوري البرامج".

أثناء نقل البيانات إلى وحدات JavaScript، اكتشفنا أنّ Closure Compiler كان يكشف عن مشاكل أكثر مما كان عليه في السابق. وأدى الانتقال إلى تنسيق الوحدة العادي إلى زيادة قدرة Closure على فهم قاعدة الرموز الخاصة بنا وبالتالي زيادة فعالية فاحصات الأنواع. مع ذلك، كان فريق TypeScript يستخدم إصدارًا أساسيًا من "أدوات مطوري البرامج" يعود قبل عملية نقل وحدات JavaScript. لذا، كان علينا معرفة ما إذا كان الترحيل إلى وحدات JavaScript قد قلل أيضًا من مقدار الأخطاء التي قد يرصدها المحول البرمجي لـ TypeScript.

تقييم TypeScript

تأسست أدوات مطوّري البرامج منذ أكثر من عشر سنوات، وتطوّرت بعد ذلك إلى تطبيق ويب ذي حجم كبير ومليء بالميزات. في وقت كتابة مشاركة المدونة هذه، تضمّنت "أدوات مطوري البرامج" ما يقرب من 150,000 سطر من رمز JavaScript الخاص بالطرف الأول. عندما شغَّلنا المحول البرمجي لـ TypeScript على كود المصدر الخاص بنا، كان الحجم الهائل من الأخطاء يمثل عبئًا هائلاً. لقد تمكنا من اكتشاف أنه على الرغم من أن المحول البرمجي لـ TypeScript كان يُصدر أخطاءً أقل تتعلق بدقة الكود (حوالي 2000 خطأ)، إلا أنه لا يزال هناك 6000 خطأ آخر في قاعدة التعليمات البرمجية لدينا ذات صلة بتوافق النوع.

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

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

أظهر تحليل متعدد للانحدارات مع أخطاء النوع التي اكتشفناها TypeScript أيضًا تداخلاً، الأمر الذي دفعنا للاعتقاد بأن TypeScript كان من الممكن أن تمنع هذه المشكلات (شرط أن تكون الأنواع نفسها صحيحة).

جارٍ إجراء مكالمة "any".

في هذه المرحلة، كان علينا الاختيار بين تحسين استخدام Closure Compiler أو الانتقال إلى TypeScript. (نظرًا لأن التدفق لم يكن متاحًا في Google أو في Chromium، كان علينا التخلي عن هذا الخيار). بناءً على المناقشات مع، والتوصيات الواردة من مهندسي Google الذين يعملون على أدوات جافا سكريبت/TypeScript، اخترنا اختيار المحول البرمجي لـ TypeScript. (نشرنا أيضًا مؤخرًا مشاركة مدونة حول نقل بيانات Puppeteer إلى TypeScript.)

كانت الأسباب الرئيسية لاستخدام المحول البرمجي لـ TypeScript هي تحسين دقة النوع، في حين تضمنت المزايا الأخرى الدعم من فرق TypeScript داخليًا في Google وميزات لغة TypeScript، مثل interfaces (بالمقارنة مع typedefs في JSDoc).

كان اختيار المحول البرمجي TypeScript يعني أنه كان علينا الاستثمار بشكل كبير في قاعدة رموز DevTools وبنيتها الداخلية. على هذا النحو، قدّرنا أنّنا بحاجة إلى عام واحد على الأقل للانتقال إلى TypeScript (سيتم إطلاقه في الربع الثالث من عام 2020).

إجراء نقل البيانات

ويبقى السؤال الأكثر أهمية: كيف سننتقل إلى TypeScript؟ لدينا 150,000 سطر من الرموز البرمجية ولا يمكننا نقلها في دفعة واحدة. كنا نعلم أيضًا أن تشغيل TypeScript على قاعدة التعليمات البرمجية سيكشف عن آلاف الأخطاء.

لقد قيمنا خيارات متعددة:

  1. الحصول على جميع أخطاء TypeScript ومقارنتها بمخرجات "ذهبية": قد يكون هذا المنهج مشابهًا لما يمتلكه فريق TypeScript. أكبر الجانب السلبي لهذا النهج هو الورود الكبير لتضاربات الدمج، نظرًا لأن عشرات المهندسين يعملون في نفس قاعدة الرموز.
  2. اضبط جميع أنواع المشاكل على any. وهذا من شأنه أن يؤدي في الأساس إلى منع كتابة الأخطاء في TypeScript. لم نحدِّد هذا الخيار، لأنّ هدفنا من عملية نقل البيانات كان تصحيح نوع البيانات، ما قد يؤدي إلى تراجع النتيجة.
  3. إصلاح جميع أخطاء TypeScript يدويًا ويشمل ذلك إصلاح آلاف الأخطاء، وهو ما يستغرق وقتًا طويلاً.

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

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

دعم JavaScript للمحول البرمجي TypeScript

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

تمكّنا من موازاة عملنا من خلال إضافة @ts-nocheck بشكل استباقي إلى كل ملف في "أدوات مطوري البرامج". تتمثل عملية "إصلاح TypeScript" في إزالة التعليق التوضيحي @ts-nocheck وحل أي أخطاء قد ترصدها TypeScript. وهذا يعني أنّنا واثقون من أنّه تم التحقّق من كل ملف وأنّه تم حلّ أكبر عدد ممكن من المشاكل من حيث النوع.

بوجه عام، نجح هذا الأسلوب في حلّ بعض المشاكل. لقد واجهنا العديد من الأخطاء في المحول البرمجي TypeScript، لكن معظمها كان غامضًا:

  1. يتم التعامل مع المعلمة الاختيارية ذات نوع الدالة التي تعرض any على أنها مطلوبة: #38551
  2. تخصيص خاصية لطريقة ثابتة لبيان فواصل فئة: #38553
  3. إعلان الفئة الفرعية التي تحتوي على الدالة الإنشائية بدون وسيطات والفئة الفائقة باستخدام الدالة الإنشائية للوسيطات تحذِف الدالة الإنشائية الفرعية: #41397

وتسلط هذه الأخطاء الضوء على أنه في حالة% 99، يُعد المحول البرمجي TypeScript أساسًا متينًا يمكن الاعتماد عليه. نعم، قد تتسبب هذه الأخطاء الغامضة أحيانًا في حدوث مشاكل في "أدوات مطوّري البرامج"، ولكن في أغلب الأحيان كانت هذه الأخطاء الغامضة يتعذّر علينا تفاديها بسهولة.

كانت المشكلة الوحيدة التي تسببت في حدوث بعض الالتباس كانت الإخراج غير الحاسم لملفات .tsbuildinfo: #37156. في Chromium، نشترط أن يؤدي أي إصداران من نفس Chromium إلى الحصول على الناتج نفسه بالضبط. تعذَّر على مهندسي إصدار Chromium اكتشاف أنّ ناتج .tsbuildinfo لم يكن محددًا: crbug.com/1054494. لحل هذه المشكلة، كان علينا إجراء تصحيح على ملف .tsbuildinfo (الذي يتضمّن تنسيق JSON بشكل أساسي) ثم إجراء المعالجة اللاحقة له لعرض ناتج حتمي: https://crrev.com/c/2091448 لحسن الحظ، تمكّن فريق TypeScript من حلّ المشكلة المتعلقة بالإرسال، وتمكّنا قريبًا من إزالة الحل البديل الذي نقدّمه. نشكر فريق TypeScript على استيعاب تقارير الأخطاء وحلّ هذه المشاكل على الفور.

بشكل عام، يسعدنا (نوع) صحة المحول البرمجي لـ TypeScript. نأمل أن تكون أدوات Devtools كمشروع كبير ومفتوح المصدر لJavaScript، قد ساعد في تعزيز دعم JavaScript في TypeScript.

تحليل النتائج المترتبة

لقد تمكنا من إحراز تقدم جيد في معالجة أخطاء الأنواع هذه وزيادة كمية الرموز التي يتم فحصها بواسطة TypeScript ببطء. ومع ذلك، في آب (أغسطس) 2020 (بعد 9 أشهر من عملية النقل هذه)، أجرينا تحققًا واكتشفنا أننا لن نصل إلى الموعد النهائي بالوتيرة الحالية. أنشأ أحد مهندسينا رسمًا بيانيًا للتحليل لإظهار مدى التقدم المحرز في "TypeScriptification" (الاسم الذي قدمناه لعملية النقل هذه).

مستوى تقدُّم عملية نقل بيانات TypeScript

مستوى تقدُّم عملية نقل البيانات من النوع TypeScript: تتبُّع سطور الرمز المتبقية والتي تحتاج إلى نقل بيانات

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

في هذه المرحلة، أصبحت عملية TypeScriptification جهدًا على مستوى الفريق. بمساعدة إضافية، تمكّنا من إنهاء عملية النقل في نهاية تشرين الثاني (نوفمبر) 2020، بعد 13 شهرًا من البدء، وقبل أكثر من عام من توقّعنا الأوّلي.

بشكل إجمالي، كان هناك 771 قائمة تغيير (على نحو يشبه طلب سحب) أرسلها 18 مهندسًا. يتضمّن خطأ التتبّع (https://crbug.com/1011811) أكثر من 1,200 تعليق (كلّها تقريبًا مشاركات مبرمَجة من قوائم التغييرات). تحتوي ورقة التتبُّع على أكثر من 500 صف لجميع الملفات المطلوب كتابتها، والمعيَّن لها، وقائمة التغييرات التي تم "الكتابة فيها".

الحد من تأثير أداء المحول البرمجي لـ TypeScript

تتمثل أكبر مشكلة نتعامل معها حاليًا في بطء الأداء في المحول البرمجي TypeScript. ونظرًا إلى عدد المهندسين الذين ينشئون Chromium وأدوات مطوّري البرامج، فإنّ هذا المؤثِّر السلبي مكلف. للأسف، لم نتمكن من تحديد هذا الخطر قبل نقل البيانات، ولم نكتشف زيادة ملحوظة في الوقت الذي يتم قضاؤه في إصدارات Chromium في المرحلة التي تم فيها نقل معظم الملفات إلى TypeScript إلا: https://crbug.com/1139220

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

للأسف، الحلول المتاحة لنا اليوم لا تناسب دائمًا المساهمين غير التابعين لشركة Google. نظرًا للأهمية الكبيرة للمساهمات المفتوحة المصدر في Chromium (خاصةً المساهمات التي يقدّمها فريق Microsoft Edge)، نبحث عن بدائل تناسب جميع المساهمين. ولكن في الوقت الحالي، لم نتوصّل إلى حل بديل مناسب.

الحالة الحالية للترميز TypeScript في "أدوات مطوري البرامج"

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

تنزيل قنوات المعاينة

يمكنك استخدام إصدار Canary أو إصدار مطوّري البرامج أو الإصدار التجريبي من Chrome كمتصفّح تلقائي للتطوير. تتيح لك قنوات المعاينة هذه الوصول إلى أحدث ميزات "أدوات مطوري البرامج" واختبار واجهات برمجة التطبيقات المتطورة للأنظمة الأساسية على الويب والعثور على المشاكل في موقعك الإلكتروني قبل المستخدمين.

التواصل مع فريق "أدوات مطوري البرامج في Chrome"

يُرجى استخدام الخيارات التالية لمناقشة الميزات والتغييرات الجديدة في المشاركة أو أي موضوع آخر ذي صلة بـ "أدوات مطوري البرامج".

  • يمكنك إرسال اقتراحات أو ملاحظات إلينا عبر crbug.com.
  • يمكنك الإبلاغ عن مشكلة في "أدوات مطوري البرامج" باستخدام خيارات إضافية   المزيد > مساعدة > الإبلاغ عن مشاكل في "أدوات مطوري البرامج" في "أدوات مطوري البرامج".
  • يمكنك نشر تغريدة على @ChromeDevTool.
  • يمكنك إضافة تعليقات على الميزات الجديدة في فيديوهات YouTube أو نصائح حول أدوات مطوّري البرامج في فيديوهات YouTube حول الميزات الجديدة.