"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > مفارقة الكتابة الثابتة في اللغات الديناميكية

مفارقة الكتابة الثابتة في اللغات الديناميكية

تم النشر بتاريخ 2024-11-07
تصفح:122

يمكنك أيضًا قراءة هذه المقالة على موقع Medium.

من المضحك دائمًا أن نرى كيف تتطور لغات البرمجة مع مرور الوقت.

ذات مرة، عندما بدأت رحلتي في عالم تطوير البرمجيات، كانت اللغات الديناميكية مثل Python وPHP وJavaScript موضع تقدير لمرونتها وتركيبها المختصر المناسب للتطوير السريع.

ومع ذلك، مع تطور هذه اللغات ضعيفة الكتابة، فإنها تتضمن ميزات اللغات المكتوبة بقوة، مما يجعلها مشابهة إلى حد كبير لـ C وJava:

  • Python: تم تقديم إمكانات تلميح النوع منذ الإصدار 3.5 في عام 2015، وتم تحسينها في الإصدار 3.12 في عام 2022.
  • PHP: الأنواع المعلنة التي تم تقديمها في الإصدار 7 عام 2015.
  • JavaScript: تم توسيعه من خلال إصدار TypeScript في عام 2012 والذي تم تعريفه على أنه "JavaScript مع بناء جملة للأنواع".

لماذا هذا التحول؟

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

// C   example: 'y' will be an integer
float x = 3.14;
int y = x;  //  y = 3 (ignored the decimal part of the number)

من ناحية أخرى، تسمح لنا اللغات المكتوبة ديناميكيًا مثل Python وPHP وJavaScript بإنشاء متغيرات والسماح للمترجم بتحديد نوعها أثناء وقت التشغيل:

# In python and PHP: 'y' will take the same type as 'x'
x = 3.14
y = x  // y = 3.14 (float)

كيف يتم تقديم الكتابة الصريحة في اللغات الديناميكية؟

في المثال التالي، نعلن عن نفس الوظيفة باستخدام الكتابة الديناميكية والثابتة.

بايثون:

# using the classic syntax:
def add(x, y):
    return x   y
# using explicit typing:
def add(x: int, y:int) -> int:
    return x   y

جافا سكريبت / تايب سكريبت:

// using the classic syntax
function add(x, y) {
    return x   y;
}
// using explicit typing
function add(x: number, y: number): number {
    return x   y;
}

PHP:

// using the classic syntax:
function add($x, $y) {
    return $x   $y;
}
// using explicit typing:
function add(int $x, int $y): int {
    return $x   $y;
}

PHP 8.2 (تم إصداره في ديسمبر 2022) دفعه إلى أبعد من ذلك من خلال تقديم دعم للقيم الفارغة والصحيحة والخاطئة كأنواع مستقلة:

public null $nil = null;
public false $false = false;`

أين المفارقة؟

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

x: int = 0
x = "John" 
print(type(x))   # 

نفس الشيء بالنسبة لـ PHP، فهو سيطبع فقط تحذيرًا مهجورًا على وحدة التحكم.

قد يتساءل المرء لماذا يسمح لنا المترجم بتنفيذ هذا الكود إذن؟
وذلك لأن هذه اللغات مبنية بهذه الطريقة: يتم كتابتها ديناميكيًا حسب التعريف. إذا أزلنا هذه الخاصية، فلن تكون ديناميكية بعد الآن؛ ستصبح لغات مكتوبة بدقة مثل لغة C، ولكنها أبطأ.

نأمل أن تتمكن من مطالبة المترجم الفوري بأن يكون أكثر صرامة من خلال تعيين الأنواع الصارمة على القيمة true في ملف PHP الخاص بك:

declare(strict_types=1);

أثناء وجودك في بايثون، يمكنك استخدام الحزمة "mypy" لتحليل التعليمات البرمجية الخاصة بك واكتشاف الأخطاء:

$ mypy program.py
error: Incompatible types in assignment (expression has type "str", variable has type "int")  [assignment]

يمكنك رؤية "mypy" كمستشار يخبرك بالخطأ الذي ارتكبته، لكنه لا يمنعك من تنفيذ التعليمات البرمجية الخاصة بك على مسؤوليتك الخاصة.

The Irony of Static Typing in Dynamic Languages

حتى إذا لم تكن متأكدًا من نوع المتغير الخاص بك، فلا يزال بإمكانك استخدام عامل التشغيل الموحد لتقليل قائمة الأنواع المقبولة:

الأمثلة التالية من PHP وPython توضح كيفية القيام بذلك:

y: int | float = f(x)   # introduced in Python 3.10
int | float $y = f($x)  // introduced in PHP 8.0
let y: number | string  // typescript

هل نضحي بإمكانية قراءة التعليمات البرمجية؟

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

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

دعونا نلقي نظرة على مثال لوظيفة تطبع عناصر القاموس. إليك النسخة الأولية:

def print_attributes(**kwargs):
    for key, value in kwargs.items():
        print(key, value)

person = {"name": "John", "height": 1.84}
print_attributes(**person)

باستخدام توصيات PEP 692 المقدمة في Python 3.12، يصبح الكود:

from typing import TypedDict, Unpack

class Person(TypedDict):   # create a class inheriting from TypedDict
    name: str                  
    height: float           

def print_attributes(**kwargs: Unpack[Person]) -> None:  # use the Unpack operator
    for key, value in kwargs.items():
        print(key, value)

person: Person = {"name": "John", "height": 1.84}  # create an instance of the class
print_attributes(**person)

باختصار: أنشأنا فئة ترث من TypedDict، وحددنا اسم ونوع كل عنصر، واستخدمنا عامل Unpack لإخبار "mypy" أن الكائن المستلم هو TypedDict.

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

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

The Irony of Static Typing in Dynamic Languages

متى يجب أن نستخدمه؟

لا تشعر بالضغط لإعادة كتابة قاعدة التعليمات البرمجية بالكامل لمجرد أنك تعلمت ميزة جديدة ورائعة.

تشبه هذه الميزات الجديدة الأدوات. نصيحتي هي استخدامها بحكمة:

استخدم الكتابة الثابتة في السيناريوهات التالية:

  • عند استرداد البيانات من مصادر خارجية، مثل قواعد البيانات والمكتبات وواجهات برمجة التطبيقات.
  • في الأجزاء المهمة من التعليمات البرمجية الخاصة بك حيث لا يُسمح بالفشل.
  • عندما تكون قاعدة التعليمات البرمجية الخاصة بك عرضة للأخطاء المتكررة.

تجنب استخدام الكتابة الثابتة عندما تكون:

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

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

بيان الافراج تم نشر هذه المقالة على: https://dev.to/aminehorseman/the-irony-of-static-typing-in-dynamic-languages-31g1?1 إذا كان هناك أي انتهاك، يرجى الاتصال بـ [email protected] للحذف هو - هي
أحدث البرنامج التعليمي أكثر>

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

Copyright© 2022 湘ICP备2022001581号-3