التحليل الثابت

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

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

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

  try {
    const result = await complexFetchFromNetwork();
    if (!result.ok) {
      throw new Error("failed to fetch");
    }
  } finally {
    // warning - this will 'overrule' the previous exception!
    return false;
  }

وبالتالي، فإن ESLint ليست بديلاً لعملية مراجعة سليمة (وأسلوب يحدد الشكل الذي ينبغي أن يبدو عليه قاعدة التعليمات البرمجية)، لأنها لن لتوضيح كل نهج غير تقليدي قد يحاول مطوِّر البرامج تقديمه في قاعدة التعليمات البرمجية. يتضمن دليل الممارسات الهندسية من Google قسمًا قصيرًا حول "البساطة".

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

  finally {
    // eslint-disable-next-line no-unsafe-finally
    return false;
  }

إذا وجدت نفسك تخرق قاعدة ما باستمرار، ففكِّر في إيقافها. هذه تشجعك على كتابة التعليمات البرمجية بطريقة معينة، ولكن قد يتم استخدام فريقك إلى كتابة التعليمات البرمجية بطريقة مختلفة وأن تكون على دراية بالفعل بمخاطر ذلك الخاص بك.

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

مكونات ESLint الإضافية لدعم المتصفح

يمكنك إضافة مكوّن إضافي إلى ESLint يشير إلى استخدام واجهات برمجة التطبيقات غير الرائجة على نطاق واسع. متوافقة أو غير متوافقة مع قائمة المتصفّحات المستهدَفة. تشير رسالة الأشكال البيانية eslint-plugin-compat لتحذيرك عندما لا تتوفر واجهة برمجة تطبيقات للمستخدمين، وبالتالي مهما كان مسارها،

التحقق من النوع للتحليل الثابت

عند تعلم JavaScript، عادةً ما يتعرّف المطورون الجدد على الفكرة أنها لغة مكتوبة بشكل ضعيف. أي أنه من الممكن الإعلان عن متغير كنوع واحد، ثم استخدم نفس الموقع لشيء ما بالكامل مختلفة. وهي تشبه لغة بايثون ولغات البرمجة النصية الأخرى، ولكنها على عكس لغات مجمعة مثل C/C++ وRust.

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

TypeScript

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

للحصول على مثال سريع، هذا الرمز الذي يتوقع أن يتم معاودة الاتصال به لقبول اسم string وعمر number:

const callback = (name: string, age: string): void => {
  console.info(name, 'is now', age, 'years old!');
};
onBirthday(callback);

إنشاء الخطأ التالي عند تنفيذه من خلال TypeScript، أو حتى عند التمرير فوقه في بيئة تطوير متكاملة:

bad.ts:4:12 - error TS2345: Argument of type '(name: string, age: string) => void' is not assignable to parameter of type '(name: string, age: number) => void'.
  Types of parameters 'age' and 'age' are incompatible.
    Type 'number' is not assignable to type 'string'.

4 onBirthday(callback);
             ~~~~~~~~

Found 1 error in bad.ts:4
التعليمات البرمجية من
  في المثال السابق، معروض في بيئة تطوير متكاملة (IDE) مع ظهور رسالة الخطأ في
  المنبثقة.
رمز VSCode يشير إلى أنك اجتزت خطأ غير صحيح الكتابة.

في نهاية المطاف، الهدف من استخدام TypeScript هو منع مثل هذه الأخطاء— يجب أن يكون العمر number، وليس string، ما يؤدي إلى التسلّل إلى مشروعك. هذا النمط قد يصعب اكتشاف نوع الخطأ باستخدام أنواع أخرى من الاختبار. بالإضافة إلى ذلك، يمكن أن يقدم نظام الكتابة ملاحظات قبل كتابة الاختبار. يساعد ذلك في تسهيل عملية كتابة الرمز البرمجي من خلال منحك ملاحظات مبكرة. حول أخطاء الكتابة أثناء قيامك بتطوير البرامج، وليس عندما تقوم التعليمات البرمجية المشروع في النهاية.

يتمثل الجزء الأكثر تحديًا في استخدام TypeScript في إعداده بشكلٍ صحيح. كلّ إلى ملف tsconfig.json، الذي يُستخدم في المقام الأول من قِبل tsc بأداة سطر الأوامر نفسها، تتم قراءتها أيضًا بواسطة بيئات IDE مثل VSCode إلى جانب العديد لإنشاء الأدوات والأدوات، بما في ذلك Vitest يحتوي هذا الملف على مئات والخيارات والعلامات، ويمكنك العثور على بعض الموارد الجيدة لإعدادها هنا:

نصائح عامة حول TypeScript

عند إعداد TypeScript واستخدامه من خلال ملف tsconfig.json، احرِص على مع وضع ما يلي في الاعتبار:

  • تأكَّد من تضمين ملفات المصدر والتحقّق منها. إذا كان الملف بشكل غامض "لا توجد أخطاء"، وذلك على الأرجح بسبب عدم التحقق منه.
  • تقديم وصف صريح للأنواع والواجهات داخل ملفات .d.ts بدلاً من كما أن وصفها ضمنيًا أثناء كتابة الدوال، يمكن أن يجعل قاعدة التعليمات البرمجية أسهل في الاختبار. من الأسهل كتابة نماذج تجريبية ومحاكاة إصدارات من الرموز البرمجية عندما تكون الواجهات المعنية واضحة. .

تتضمن TypeScript أيًّا

يعد أحد خيارات التهيئة الأكثر فاعلية وربحًا في TypeScript علم واحد (noImplicitAny) ومع ذلك، غالبًا ما يكون ذلك هو الأصعب أيضًا، خاصةً إذا كان لديك بالفعل قاعدة رموز كبيرة. (علامة noImplicitAny هي سيتم تفعيلها تلقائيًا إذا كنت في وضع strict، وليس في الوضع الآخر).

ستجعل هذه العلامة هذه الدالة تعرض خطأ:

export function fibonacci(n) {
  if (n <= 1) {
    return 0;
  } else if (n === 2) {
    return 1;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
}

وعلى الرغم من أنه من الواضح إلى حدٍ ما كقارئ أن n يجب أن يكون رقمًا، ليس بإمكان TypeScript تأكيد ذلك بثقة. إذا كنت تستخدم VSCode، مرِّر مؤشر الماوس فوق فستصفه الدالة على النحو التالي:

function fibonacci(n: any): any

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

الحل البسيط هنا هو وضع علامة على كل من الوسيطة n ونوع إرجاع fibonacci باعتبارهما number.

لا تمنعك العلامة noImplicitAny من كتابة any بشكلٍ صريح. قاعدة التعليمات البرمجية. لا يزال بإمكانك كتابة دالة تقبل أو تُرجع النوع any. إنه يضمن فقط أنك تعطي كل متغير نوعًا.