درک بسیار ساده تفاوت میان Static Type و Dynamic Type

گردآوری و تالیف : ارسطو عباسی
تاریخ انتشار : 17 تیر 1398
دسته بندی ها : برنامه نویسی

در ابتدای کار برنامه‌نویسی که قصد انتخاب یک زبان را داشتم با دو اصطلاح Dynamic Type و Static Type بسیار زیاد مواجه می‌شدم، البته هر کدام از وبسایت‌ها نیز تعریفی ارائه داده بودند اما با خواندن آن‌ها بیشتر از پیش سردرگم می‌شدم و نمی‌دانستم دقیقا منظورشان چیست. بعد از انجام یکسری کار و مطالعات زیاد به این نتیجه رسیدم که یک مطلب کوتاه در این رابطه بنویسم. به قول کریس کویر: «مقاله‌ای بنویس که آرزو داشتی زمان سرچ توی گوگل بهش رسیده بودی.»

ابتدا بیایید با یکسری از تعاریف پایه‌ای آشنا شویم و بدانیم که منظورمان از کلماتی مانند سورس کد، زمان اجرا، ترجمه کد و… چیست.

کامپایل شده در مقابل تفسیر شده

«زمانی که سورس‌ کدها ترجمه می‌شوند»

  • سورس کد: منظور از سورس کد همان کدهای اصلی برنامه است که معمولا توسط انسان‌ها نوشته می‌شود.
  • ترجمه کد: تبدیل سورس کد به کدی که کامپیوتر آن را متوجه شود. (کد ماشین)
  • زمان اجرا: به مدت زمانی که یک برنامه بعد از دستور اجرا، شروع بکار می‌کند. (بعد از ترجمه شدن البته)
  • کامپایل شده: کدهای ترجمه شده را کدهای کامپایل شده می‌نامند.
  • تفسیر شده: کدهایی که در زمان اجرا ترجمه می‌شوند را کدهای تفسیر شده می‌گویند.

Typing

«زمانی که نوع‌ها یا Typeها بررسی می‌شوند»

در زبان‌هایی که اصطلاحا Strong Type هستند نوشتن برنامه "3" + 5 یک خطا نوعی را بوجود می‌آورد. منظور از این زبان‌ها، آن دسته‌ای هستند که اجازه «Type coercion» را نمی‌دهند. منظور از این حالت زمانی است که خود زبان به صورت سر خود تصمیم می‌گیرید که یک عدد را به رشته (یا بلعکس) تبدیل کند. پایتون و GO از جمله زبان‌هایی هستند که چنین قابلیتی ندارند. از طرفی دیگر زبان‌هایی مانند جاوااسکریپت که Weak Type هستند این امکان را در خود پیاده‌سازی کرده‌اند و با محاسبه "3" + 5 مشکلی ندارند. (نتیجه "35" خواهد بود).

در زبان‌های برنامه‌نویسی استاتیک نوع داده‌ها قبل از زمان اجرا بررسی می‌شوند. اما در زبان‌های برنامه‌نویسی پویا یا Dynamic این کار در زمان اجرای برنامه صورت می‌گیرد. (اصطلاحا به این حالت on fly گفته می‌شود)

تعاریف مربوط به Static و Complied بسیار شبیه به هم دیگر هستند، چنین حالتی برای Dynamic و Interpreted نیز وجود دارد. اما دو جمله اصلی که در این مطلب نوشته شده را بخاطر بسپارید:

«زمانی که سورس کدها ترجمه می‌شوند» و «زمانی که نوع‌ها بررسی می‌شوند» 

بررسی نوعی یا Type-Checking ربطی به کامپایلی یا تفسیری بودن یک زبان برنامه‌نویسی ندارد. باید موضوع بررسی نوعی را از شیوه ترجمه کدها جدا کنید.

یک مثال 

پایتون – زبانی پویا و تفسیری

def foo(a):
    if a > 0:
        print 'Hi'
    else:
        print "3" + 5
foo(2)

از آنجایی که کدهای پایتون در زمان اجرای برنامه تفسیر می‌شوند تنها بخش‌هایی از برنامه ترجمه و بررسی نوعی می‌شود که در معرض اجرای منطقی قرار می‌گیرد. اگر به تابع نگاه کنید متوجه می‌شوید که بلوک else اجرا نمی‌شود و از این رو ما با خطای type error نیز برخورد نخواهیم کرد. (اگر بلوک else اجرا شود خطای نوعی نمایش داده می‌شود چرا که نمی‌توان عملگر جمع را روی یک رشته و عدد اعمال کرد).

اگر پایتون یک زبان برنامه‌نویسی ایستا بود چه؟

در این صورت برنامه هیچوقت اجرا نمی‌شد چرا که در این زبان‌ها قبل از اجرای برنامه عملیات بررسی نوعی را انجام می‌دهند. از این رو که رشته ۳ نمی‌تواند با عدد ۵ جمع شود در نهایت با type error مواجه می‌شد. 

اگر پایتون یک زبان کامپایلی بود چه؟

اگر پایتون زبانی کامپایلی اما پویا بود با هیچ خطایی روبرو نمی‌شد. در واقع در بحث کامپایل، برنامه به صورت کامل ترجمه می‌شد اما از آنجایی که زبان پویایی بود تا زمان اجرای دستور فرایند type checking را انجام نمی‌داد. بلوک else هیچگاه اجرا نمی‌شد و در نهایت هیچ خطایی هم وجود نداشت.

یک مثال

گو – زبانی ایستا و کامپایلی

package main
import ("fmt"
)
func foo(a int) {
  if (a > 0) {
      fmt.Println("Hi")
  } else {
      fmt.Println("3" + 5)
  }
}
func main() {
  foo(2)
}

از آنجایی که گو یک زبان برنامه‌نویسی ایستا است، در چنین حالتی نوع‌های داده‌ای قبل از اجرا بررسی می‌شدند و در نهایت قبل از اجرای برنامه خطای type error ظاهر می‌شد. اما اگر گو یک زبان پویا می‌بود با چنین خطایی روبرو نمی‌شد چرا که همانطور گفته شد در برنامه‌های پویا تنها قسمت‌هایی بررسی نوعی می‌شوند که اجرا شوند نه کل برنامه‌.

کارایی

یک زبان برنامه‌نویسی کامپایلی و البته استاتیک کارایی بسیار بهتری نسبت به زبان تفسیری ارائه می‌کند. این موضوع بدان دلیل است که دانستن نوع داده و بررسی درست آن باعث می‌شود که در کدهای ماشین بهینه‌تر باشند.

از آنجایی هم که در هر خط از دستور نیازی به بررسی نوع داده‌ای ندارند در زمان اجرا بسیار سریع‌تر از زبان‌های پویا هستند. همانطور که گفتیم در زبان‌های پویا با اجرای کدها برنامه خط به خط بررسی می‌شود. این مسئله زمان‌بر است.

البته یک نکته مهم دیگر آن است که هر دو زبان‌های ایستا و کامپایلی قبل از اجرای برنامه، برای ترجمه شدن مدت زمانی وقفه دارند.

تفاوت‌های بیشتر

زبان‌های ایستا قبل از اجرای برنامه خطاها را به شما نشان می‌دهند، این موضوع از آن جایی مهم است که در زمان ساخت یک برنامه بسیار بزرگ با خطاهای نامعلوم مواجه نخواهید شد. چرا که در زبان‌های پویا اگر یک سورس ۱۰۰۰ خط کد باشد باید خط به خط در زمان اجرا به دنبال خطا باشد و این موضوع به خودی خود کمی ناامن به نظر می‌رسد. بنابراین استفاده از زبان‌های ایستا شما را از خطاهای ناگهانی دور نگه می‌دارد.

num = 2
num = '3' // ERROR

از طرفی دیگر زبان‌های پویا بیشترین سازگاری و انعطاف‌پذیری را دارند. نوشتن برنامه در این زبان‌ها بسیار سریع‌تر انجام می‌شود.

منبع

مقالات پیشنهادی

  • آشنایی سریع با Typescript

    تایپ‌اسکریپت یک مدل دیگر از جاوااسکریپت است که توسط مایکروسافت توسعه‌ داده شده و برای ساخت اپلیکیشن‌های بزرگ استفاده می‌شود. تایپ‌اسکریپت ویژگی‌ها مهم...

    ارسطو عباسی
  • آموزش Typescript در ۳۰ دقیقه

    امروز در این مقاله راکت قصد داریم نگاهی به تایپ‌اسکریپت بیاندازیم. یک زبان کامپایل شده از جاوااسکریپت که به توسعه‌دهندگان اجازه ایجاد اپلیکیشن‌های بزر...

    ارسطو عباسی