eshpilen
چهارشنبه 03 فروردین 1390, 23:21 عصر
اسکریپت نویسی: برنامه نویسی سطح بالاتر برای قرن 21
مقاله ای از John K. Ousterhout
آزمایشگاههای Sun Microsystems
مارچ 1998
افزایش ها در سرعت رایانه و تغییرات در ترکیب اپلیکیشن درحال مهمتر کردن بیشتر و بیشتر زبانهای اسکریپتی برای اپلیکیشن های آینده هستند. زبانهای اسکریپتی از این جهت از زبانهای سیستمی تفاوت دارند که آنها برای اتصال اپلیکیشن ها به همدیگر طراحی شده اند. آنها برای دستیابی به یک سطح بالاتر از برنامه نویسی و توسعهء سریعتر اپلیکیشن از یک مشی بدون نوع (typeless) استفاده میکنند.
در طول 15 سال گذشته یک تغییر بنیادین در روشی که مردم برنامه های رایانه را مینویسند درحال رخ دادن بوده است. آن تغییر یک گذار از زبانهای سیستمی همچون سی و سی++ به زبانهای اسکریپتی همچون پرل یا Tcl است. هرچند مردم زیادی در حال مشارکت در این تغییر هستند، عدهء کمی میدانند که تغییری در حال رخ دادن است و عدهء حتی کمتری میدانند که چرا آن درحال اتفاق افتادن است. این مقاله توضیح خواهد داد که چرا زبانهای اسکریپتی بسیاری از کارهای برنامه نویسی را در قرن آینده بهتر از زبانهای سیستمی اداره خواهند کرد.
زبانهای اسکریپتی برای کارهای متفاوتی نسبت به زبانهای سیستمی طراحی شده اند و این منجر به تفاوت های بنیادین در زبانها میشود. زبانهای سیستمی برای ساختن ساختمان های داده ای و الگوریتم ها از صفر که از بدوی ترین اجزای رایانه همچون کلمه های حافظه شروع میشوند طراحی شده بودند. در مقابل، زبانهای اسکریپتی برای اتصال طراحی شده اند: آنها فرض میکنند که مجموعه ای از کامپوننت های قوی وجود دارند و عمدتا برای اتصال کامپوننت ها طراحی شده اند. زبانهای سیستمی از نوع نوعگذاری قوی (strongly typed) هستند تا به مدیریت پیچیدگی کمک کنند، درحالیکه زبانهای اسکریپتی بدون نوع هستند تا اتصالات میان کامپوننت ها را ساده کرده و توسعهء سریع اپلیکیشن را فراهم سازند.
زبانهای اسکریپتی و سیستمی مکمل هستند، و بیشتر پلتفرم های رایانه ای از سال 1960 هر دو نوع زبانها را شامل شده اند. این زبانهای معمولا همراه با همدیگر در فریمورک های کامپوننت بکار میروند که کامپوننت ها با زبانهای سیستمی ایجاد شده و بوسیلهء زبانهای اسکریپتی متصل میشوند. هرچند، چند رویهء اخیر، همچون ماشین های سریعتر، زبانهای اسکریپتی بهتر، و اهمیت فزایندهء رابطهای کاربر گرافیکی و معماری های کامپوننتی و رشد اینترنت، کاربرد زبانهای اسکریپتی را به میزان زیادی افزایش داده اند. این رویه ها در طول دههء آینده ادامه پیدا خواهند کرد و اپلیکیشن های بیشتر و بیشتری بطور کامل با زبانهای اسکریپتی نوشته خواهند شد و زبانهای سیستمی عمدتا برای ایجاد کامپوننت ها بکار خواهند رفت.
-- زبانهای سیستمی
برای درک تفاوتها میان زبانهای اسکریپتی و سیستمی، مهم است بدانیم چطور زبانهای سیستمی بوجود آمدند. زبانهای سیستمی بعنوان جایگزینی برای زبان اسمبلی ایجاد شدند. در زبان اسمبلی، عملا هر جنبهء ماشین در برنامه منعکس شده است. هر عبارت برنامه نویسی نمایندهء یک دستورالعمل ماشین است و برنامه نویسان باید با جزییات سطح پایینی همچون اختصاص رجیستر و فرایند فراخوانی پراسیجرها کار کنند. بعنوان یک نتیجه، نوشتن و نگهداری برنامه های بزرگ در زبانهای اسمبلی دشوار است.
در اواخر 1950، زبانهای سطح بالاتر همچون Lisp، فرترن، و Algol شروع به پدیدار شدن کردند. در این زبانها، عبارت ها دیگر دقیقا معادل دستورالعمل های ماشین نبودند؛ یک کامپایلر هر عبارت را در کد منبع به یک توالی از دستورالعمل های باینری تبدیل میکند. در طول زمان یک سری از زبانهای سیستمی از Algol بوجود آمدند که شامل PL/1، پاسکال، سی، سی++ و جاوا است. زبانهای سیستمی پرفورمنس کمتری نسبت به زبانهای اسمبلی دارند اما اجازه میدهند تا اپلیکیشن ها بسیار سریعتر توسعه بیابند. بعنوان یک نتیجه، زبانهای برنامه نویسی سیستمی تقریبا بصورت کامل جایگزین زبانهای اسمبلی برای توسعهء اپلیکیشن های بزرگ شدند.
-- زبانهای سطح بالاتر
زبانهای سیستمی به دو شکل با زبان اسمبلی تفاوت دارند: آنها سطح بالاتر هستنند و آنها نوع قوی (strongly typed) هستند. اصطلاح «سطح بالاتر» به معنای آنست که جزییات زیادی بصورت خودکار انجام میشوند، بنابراین برنامه نویسان میتوانند کد کمتری را برای انجام کار یکسانی بنویسند. بطور مثال:
- اختصاص رجیستر بوسیلهء کامپایلر انجام شده و بنابراین برنامه نویس نیازی به نوشتن کد برای انتقال اطلاعات بین رجیسترها و حافظه ندارد.
- روند فراخوانی رویه ها (Procedure calling sequences) بصورت خودکار تولید میشوند؛ برنامه نویسان نیازی ندارند دربارهء انتقال آرگومانها به و از پشتهء فراخوانی نگران باشند.
- برنامه نویسان میتوانند کلمات کلیدی ساده ای همچون while و if را برای ساختارهای کنترلی استفاده کنند؛ کامپایلر تمام جزییات دستورالعمل ها را برای پیاده سازی ساختارهای کنترلی تولید میکند.
بطور میانگین، هر خط از کد در یک زبان سیستمی به حدود پنج دستورالعمل ماشین ترجمه میشود، در مقایسه با یک دستورالعمل بر هر خط در یک برنامهء اسمبلی (م: حذف بخشی از متن). برنامه نویسان میتوانند تقریبا تعداد یکسانی خط کد را در هر سال صرفنظر از زبان بنویسند، بنابراین زبانهای سیستمی اجازه میدهند تا اپلیکیشن ها بسیار سریعتر از زبانهای اسمبلی توسعه داده شوند.
-- نوعگذاری (Typing)
تفاوت دوم میان زبان اسمبلی و زبانهای سیستمی نوعگذاری است. من اصطلاح نوعگذاری را برای رجوع به حدی که اطلاعات پیش از استفاده اش مشخص میشود استفاده میکنم. در یک زبان نوع قوی، برنامه نویس اعلان میکند که هر قطعه از اطلاعات چگونه استفاده خواهد شد، و زبان از استفاده از اطلاعات به هر شکل دیگری جلوگیری میکند. در یک زبان نوع ضعیف (weakly typed)، محدودیتهای از پیش تعیین شده برای روی چگونگی استفاده از اطلاعات وجود ندارند؛ معنای اطلاعات صرفا بوسیلهء روشی که آنها استفاده میشوند تعیین میشود، نه بوسیلهء هر قول و قرارداد قبلی.
رایانه های مدرن اساسا بدون نوع هستند. هر کلمهء حافظه میتواند هر نوعی از مقدار را نگهداری کند، همچون یک عدد صحیح، یک عدد اعشاری، یک اشاره گر، یا یک دستورالعمل. معنای یک مقدار بوسیلهء روش استفادهء آن تعیین میشود. اگر شمارندهء برنامه (program counter) به یک کلمه از حافظه اشاره کند با آن بصورت یک دستورالعمل رفتار میشود؛ اگر یک کلمه بوسیلهء یک دستورالعمل جمع صحیح مورد ارجاع قرار گیرد، با آن بصورت یک عدد صحیح رفتار میشود؛ و غیره. کلمهء یکسانی میتواند به شکلهای مختلف در زمانهای مختلف استفاده شود.
در مقابل، زبانهای سیستمی امروزی نوع قوی هستند. بطور مثال:
- هر متغییر در یک زبان سیستمی باید با یک نوع خاص همچون متغییر یا اشاره گر به رشته اعلان شود، و بایست به شکلهایی استفاده شود که برای آن نوع مناسب هستند.
- داده و کد جدا شده اند؛ ایجاد کد بصورت on the fly، اگر غیرممکن نباشد، دشوار است.
- متغییرها میتوانند در داخل ساختارها یا اشیایی با زیر ساختارهای بخوبی تعریف شده و رویه ها یا متدهایی برای دستکاری آنها جمع شوند. یک شیء از یک نوع نمیتواند جاییکه یک شیء از نوع دیگری مورد انتظار است استفاده شود.
نوعگذاری چند مزیت دارد. نخست، برنامه های بزرگ را بوسیلهء روشن کردن اینکه چطور چیزها استفاده میشوند و تمیز دادن میان چیزهایی که باید با آنها بصورت متفاوتی رفتار شود بیشتر قابل مدیریت میسازد. دوم، کامپایلرها اطلاعات نوع را برای آشکارسازی بعضی انواع مشخص از خطاها، همچون تلاشی برای استفاده از یک عدد اعشاری بعنوان یک اشاره گر استفاده میکنند. سوم، نوعگذاری پرفورمنس را بوسیلهء اجازه دادن به کامپایلرها برای تولید کد اختصاصی بهبود میدهد. برای مثال، اگر یک کامپایلر بداند که یک متغییر همیشه یک مقدار عدد صحیح را نگهداری میکند، سپس آن میتواند دستورالعمل های عدد صحیح را برای دستکاری آن متغییر تولید کند؛ اگر کامپایلر نداند که نوع یک متغییر چیست، آن باید دستورالعمل های اضافه ای را برای چک کردن نوع متغییر در زمان اجرا تولید کند. شکل 1 یک مجموعهء متنوع از زبانها را بر اساس سطح برنامه نویسی و قدرت نوعگذاری مقایسه میکند.
-- زبانهای اسکریپتی
زبانهای اسکریپتی همچون پرل، پایتون، Rexx، Tcl، ویژوال بیسیک، و شل های یونیکس یک استایل برنامه نویسی کاملا متفاوت نسبت به زبانهای سیستمی را ارائه میدهند. زبانهای اسکریپتی فرض میکنند که مجموعه ای از کامپوننت های سودمند از پیش در زبانهای دیگر وجود دارند. آنها برای نوشتن اپلیکیشن ها از صفر درنظر گرفته نشده اند بلکه بیشتر برای ترکیب کردن کامپوننت ها درنظر گرفته شده اند. برای مثال Tcl و ویژوال بیسیک میتوانند برای چیدن مجموعه هایی از کنترل های رابط کاربری بر روی صفحه استفاده شوند، و اسکریپت های شل یونیکس برای سوار کردن برنامه های فیلتر کننده در خط لوله ها (pipeline - م: اصطلاحی در روش اتصال ورودی و خروجی برنامه ها در خط فرمان) استفاده میشوند. زبانهای اسکریپتی اغلب برای گسترش ویژگیهای کامپوننت ها استفاده میشوند؛ هرچند، آنها به ندرت برای الگوریتم های پیچیده و ساختارهای داده ای که معمولا توسط کامپوننت ها فراهم میشوند مورد استفاده قرار میگیرند. به زبانهای اسکریپتی بعضی اوقات تحت عنوان زبانهای متصل کننده/چسباننده (glue languages) یا زبانهای یکپارچه سازی سیستم (system integration languages) ارجاع میشود.
-- زبانهای اسکریپتی عموما بدون نوع هستند
برای ساده کردن کار اتصال کامپوننت ها، زبانهای اسکریپتی تمایل دارند تا بدون نوع باشند. همهء چیزها بطور یکسانی بنظر میرسند و بطور یکسانی رفتار میکنند تا بتوانند قابل تبادل باشند. برای مثال، در Tcl یا ویژوال بیسیک یک متغییر میتواند در یک لحظه یک رشته را نگهداری کند و دفعهء بعد یک عدد صحیح را. کد و داده اغلب قابل تبادل هستند، بنابراین یک برنامه میتواند برنامهء دیگری را نوشته و آن را درجا (on the fly) اجرا کند. زبانهای اسکریپتی اغلب رشته گرا (string-oriented) هستند، چراکه این یک نمایش یک شکل را برای بسیاری چیزهای متفاوت فراهم میاورد.
یک زبان بدون نوع بهم متصل کردن کامپوننت ها را خیلی ساده تر میکند. محدودیت های از پیش تعیین شده ای بر روی آنکه چیزها چطور میتوانند استفاده شوند وجود ندارد، و همهء کامپوننت ها و مقدارها به روش یک شکلی معرفی میشوند. بنابراین هر کامپوننت یا مقدار میتواند در هر شرایطی استفاده شود؛ کامپوننت هایی که برای یک مقصود طراحی شده اند میتوانند برای مقاصد کاملا متفاوتی که هرگز بوسیلهء طراح پیشبینی نمیشدند بکار روند. برای مثال، در شل های یونیکس (Unix shells) تمام برنامه های فیلتر یک جریان (stream) از بایتها را از ورودی خوانده و یک جریان از بایتها را در خروجی مینویسند. هر دو برنامه میتوانند بوسیلهء ضمیمه کردن خروجی یک برنامه به ورودی برنامهء دیگر بهم متصل شوند. فرمان شل روبرو سه فیلتر را برای شمارش تعداد خطهایی در متن انتخاب شده که حاوی کلمهء scripting هستند بهم متصل میکند: select | grep scripting | wc
برنامهء select متنی را که درحال حاضر در روی صفحهء نمایش انتخاب شده است میخواند و متن را در خروجی خودش چاپ میکند؛ برنامهء grep ورودی خودش را میخواند و در خروجی خطهایی را که شامل کلمهء scripting هستند چاپ میکند؛ برنامهء wc تعداد خطهای موجود در ورودی اش را میخواند. هر یک از این برنامه ها میتوانند در تعداد بیشماری شرایط دیگر برای انجام کارهای متفاوتی بکار روند.
طبیعت نوع قوی زبانهای سیستمی استفادهء مجدد را مشکل میکند. آن برنامه نویسان را تشویق میکند تا یک مجموعهء متنوع از رابطهای (interface) ناسازگار را بنویسند که هریک از آنها اشیایی از نوع خاصی را نیاز دارد. کامپایلر از استفاده از هر نوع دیگری از اشیاء با رابط مورد نظر جلوگیری میکند، حتی اگر آن میتوانست مفید باشد. پس برای استفاده از یک شیء جدید با یک رابط جدید، برنامه نویس باید کد تبدیلی را برای ترجمه بین نوع شیء و نوع مورد انتظار بوسیلهء رابط بنویسند. این خود باعث میشود که به کامپایل مجدد بخشی یا تمام اپلیکیشن نیاز باشد؛ بسیاری اپلیکیشن ها امروزه در شکل باینری توزیع میشوند و بنابراین این کار امکان ندارد.
برای تقدیر از فواید یک زبان بدون نوع، به فرمان Tcl زیر توجه کنید:
button .b -text Hello! -font {Times16} -command {puts hello}
این فرمان یک کنترل دکمهء جدید که یک رشتهء متنی را با یک فونت 16point Times نمایش داده و یک پیغام کوتاه را موقعی که کاربر روی کنترل کلیک میکند چاپ میکند ایجاد میکند. این فرمان شش نوع مختلف از چیزها را در یک عبارت ترکیب میکند: یک نام فرمان (button)، یک کنترل دکمه (.b)، نام پراپرتی ها (-text، -font، -command)، رشته های ساده (Hello! و hello) یک نام فونت (Times 16) که یک نام typeface (ا Times) و یک اندازه در واحد نقطه (16) را شامل میشود، و یک اسکریپت Tcl (ا puts hello). زبان Tcl تمام این چیزها را بوسیلهء رشته ها به شکل مشابهی نشان میدهد. در این مثال، پراپرتی ها میتوانند در هر ترتیبی مشخص شوند و پراپرتی های مشخص نشده مقدارهای پیشفرض را بدست میاورند؛ بیش از 20 پراپرتی در این مثال بصورت مشخص نشده بودند.
مثال یکسان وقتی در جاوا پیاده سازی شود نیاز به 7 خط کد در دو متد دارد. با سی++ و MFC آن به حدود 25 خط کد در سه procedure نیاز دارد. تنها تعیین فونت به چندین خط کد در MFC نیاز دارد:
CFont *fontPtr = new CFont();
fontPtr->CreateFont(16, 0, 0, 0, 700,
0, 0, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
“Times New Roman”);
buttonPtr->SetFont(fontPtr);
بسیاری از این کد نتیجهء نوع قوی بودن است. برای تعیین فونت یک دکمه، متد SetFont آن باید فراخوانی شود، اما به این متد باید یک اشاره گر به یک شیء CFont پاس شود. این خود باعث میشود نیاز باشد یک شیء جدید اعلان و مقداردهی اولیه شود. برای مقداردهی اولیهء شیء CFont متد CreateFont آن باید فراخوانی شود، اما متد CreateFont یک اینترفیس غیرمنعطف دارد که نیاز دارد 14 آرگومان مختلف مشخص شود. در Tcl، مشخصه های اساسی فونت (typeface Times, size 16 points) میتوانند بلافاصله بدون هیچ اعلان یا تبدیلی استفاده شوند. بعلاوه، Tcl اجازه میدهد تا رفتار دکمه مستقیما در فرمانی که دکمه را ایجاد میکند درج شود، درحالیکه در سی++ یا جاوا آن باید در یک متد بصورت جداگانه اعلان شده قرار داده شود (در عمل، یک مثال جزیی مانند این احتمالا بوسیلهء یک محیط توسعهء گرافیکی که پیچیدگی زبان زیرین را پنهان میکند مدیریت خواهد شد. کاربر مقدار پراپرتی ها را در یک فرم وارد کرده و محیط توسعه کد را تولید میکند. اما، در شرایط پیچیده تر، همچون اختصاص شرطی مقدار پراپرتی ها یا رابطهای تولید شده بصورت برنامه ای، توسعه دهنده باید کد را در زبان زیرین بنویسد).
ممکن است بنظر برسد که طبیعت بدون نوع زبانهای اسکریپتی میتواند به خطاها اجازه بدهد تا آشکارسازی نشوند، اما در عمل زبانهای اسکریپتی همانقدر امن هستند که زبانهای سیستمی هستند. برای مثال، یک خطا رخ خواهد داد اگر اندازهء فونت مشخص شده برای مثال دکمهء بالا یک رشتهء غیر عدد صحیح همچون xyz باشد. زبانهای اسکریپتی چک کردن خطای خود را در آخرین لحظهء ممکن انجام میدهد، وقتی که یک مقدار استفاده میشود. نوع قوی بودن اجازه میدهد تا خطاها در زمان کامپایل آشکارسازی شوند، بنابراین از هزینهء اجرای چک های زمان اجرا اجتناب میشود. هرچند، قیمت پرداخته شده برای کارایی، محدودیت هایی بر روی آنکه اطلاعات چطور میتوانند استفاده شوند است؛ این موجب کد بیشتر و برنامه هایی با انعطاف کمتر میشود.
-- زبانهای اسکریپتی تفسیر میشوند
تفاوت کلیدی دیگر بین زبانهای اسکریپتی و سیستمی آن است که زبانهای اسکریپتی معمولا تفسیر میشوند، درحالیکه زبانهای سیستمی معمولا کامپایل میشوند. زبانهای تفسیر شونده قابلیت تغییرات سریع را در زمان توسعه با حذف زمانهای کامپایل فراهم میکنند. مفسرها همچنین اپلیکیشن ها را بوسیلهء اجازه دادن کاربران به برنامه ریزی اپلیکیشن ها در زمان اجرا منعطف تر میسازند. برای مثال، بسیاری از ابزارهای ترکیب و تحلیل برای مدارهای مجتمع شامل یک مفسر Tcl هستند؛ کاربران برنامه ها اسکریپت های Tcl را برای مشخص کردن طراحی شان و کنترل عملیات ابزارها مینویسند. مفسرها همچنین با تولید کد بصورت درجا امکان ایجاد اثرهای قدرتمند را میدهند. برای مثال، یک مرورگر وب بر اساس Tcl میتواند یک صفحهء وب را با ترجمهء HTML به یک اسکریپت Tcl با استفاده از معدودی جایگزینی عبارات منظم (regular expression) تجزیه کند. آن سپس اسکریپت Tcl را برای نمایش صفحه بر روی صفحهء نمایش اجرا میکند.
زبانهای اسکریپتی از زبانهای سیستمی پرفورمنس کمتری دارند، بخشی بخاطر آنکه آنها از مفسرها بجای کامپایلرها استفاده میکنند اما همچنین بخاطر آنکه اجزای پایهء آنها برای قدرت و استفادهء آسان انتخاب شده اند تا یک نگاشت با پرفورمنس بالا به سخت افزار زیرین. برای مثال، زبانهای اسکریپتی اغلب در شرایطی که یک زبان سیستمی از یک مقدار باینری که در یک کلمهء منفرد حافظه جا میگیرد استفاده خواهد کرد از رشته های با طول متغییر استفاده میکنند، و آنها از hash table ها در جایی که زبانهای سیستمی از آرایه های ایندکس شده استفاده میکنند استفاده میکنند.
خوشبختانه، معمولا پرفورمنس یک زبان اسکریپتی یک مشکل عمده نیست. اپلیکیشن ها برای زبانهای اسکریپتی عموما کوچکتر از اپلیکیشن ها برای زبانهای سیستمی هستند، و پرفورمنس یک زبان اسکریپتی تمایل دارد تا بوسیلهء پرفورمنس کامپوننت هایی مورد احاطه قرار گیرد که معمولا در یک زبان سیستمی پیاده میشوند.
زبانهای اسکریپتی از زبانهای سیستمی سطح بالاتر هستند از این جهت که یک عبارت منفرد بطور میانگین کار بیشتری را انجام میدهد. یک عبارت عادی در یک زبان اسکریپتی صدها یا هزاران دستورالعمل ماشین را اجرا میکند، درحالیکه یک عبارت عادی در یک زبان سیستمی درحدود پنج دستورالعمل ماشین را اجرا میکند (همانطور که شکل 1 نشان میدهد). بخشی از این تفاوت بخاطر آنست که زبانهای اسکریپتی از مفسرها استفاده میکنند، اما خیلی از این تفاوت بخاطر آنست که عملیات اولیه در زبانهای اسکریپتی امکانات بیشتری دارند. برای مثال، در پرل فراخوانی یک جایگزینی عبارت منظم تقریبا به آسانی فراخوانی یک جمع عدد صحیح است. در Tcl، یک متغییر میتواند trace هایی را پیوند شده به آن داشته باشد تا تعیین مقدار متغییر باعث اثرات جانبی شود؛ برای مثال، یک trace میتواند برای آپدیت نگه داشتن مقدار متغییر در روی صفحهء نمایش بکار رود.
زبانهای اسکریپتی اجازه میدهند تا توسعهء سریع کاربردهای اتصال گرا انجام شود. جدول 1 پشتیبانی روایتی برای این ادعا فراهم میکند. آن چند اپلیکیشن را توصیف میکند که در یک زبان سیستمی پیاده سازی شده بودند و سپس در یک زبان اسکریپتی پیاده سازی مجدد شدند یا بعکس. در همهء موارد، نسخهء اسکریپتی نیاز به کد و زمان توسعهء کمتری نسبت به نسخهء زبان سیستمی داشته است؛ اختلاف از یک فاکتور 2 تا یک فاکتور 60 متغییر است. زبانهای اسکریپتی فایدهء کمتری فراهم میکنند وقتی که آنها برای نخستین پیاده سازی استفاده میشوند؛ این اشاره میکند که هر پیاده سازی مجدد از تجربهء بدست آمده از نخستین پیاده سازی سود قابل توجهی میبرد و اختلاف واقعی بین اسکریپت نویسی و برنامه نویسی سیستمی به احتمال بیشتر یک فاکتور از 5 تا 10 میباشد. منافع اسکریپت نویسی همچنین بسته به اپلیکیشن است. در مثال آخر در جدول 1، بخش رابط کاربر گرافیکی اپلیکیشن اتصال گرا است اما بخش شبیه ساز اینطور نیست؛ این میتواند توضیح دهد که چرا اپلیکیشن مورد نظر نسبت به اپلیکیشن های دیگر کمتر از اسکریپت نویسی سود برده است.
ااطلاعات جدول بوسیلهء توسعه دهندگان مختلف Tcl در پاسخ به مقاله ای که در گروه خبری comp.lang.tcl پست شده بود فراهم شده بود.
-- ابزارهای مختلف برای کارهای مختلف
یک زبان اسکریپتی یک جایگزین برای یک زبان سیستمی نیست یا بعکس. هر یک برای یک مجموعه از کارهای متفاوت مناسبند. برای اتصال و یکپارچه سازی سیستم، اپلیکیشن ها میتوانند از 5 تا 10 بار سریعتر بوسیلهء یک زبان اسکریپتی توسعه داده شوند؛ زبانهای برنامه نویسی سیستمی نیاز به مقدار زیادی کدهای پایه و کد تبدیل برای اتصال قطعات دارند، درحالیکه این میتواند مستقیما توسط یک زبان اسکریپتی انجام شود. برای الگوریتم های پیچیده و ساختمان داده ها، نوعگذاری قوی یک زبان سیستمی مدیریت برنامه را ساده تر میسازد. جاییکه سرعت اجرا یک مسئلهء کلیدی است، یک زبان سیستمی میتواند 10 تا 20 برابر سریعتر از یک زبان اسکریپتی اجرا شود زیرا آن چک های زمان اجرای کمتری انجام میدهد.
بقیهء مقاله در پست بعدی (بعلت محدودیت حجم پست در فروم)...
مقاله ای از John K. Ousterhout
آزمایشگاههای Sun Microsystems
مارچ 1998
افزایش ها در سرعت رایانه و تغییرات در ترکیب اپلیکیشن درحال مهمتر کردن بیشتر و بیشتر زبانهای اسکریپتی برای اپلیکیشن های آینده هستند. زبانهای اسکریپتی از این جهت از زبانهای سیستمی تفاوت دارند که آنها برای اتصال اپلیکیشن ها به همدیگر طراحی شده اند. آنها برای دستیابی به یک سطح بالاتر از برنامه نویسی و توسعهء سریعتر اپلیکیشن از یک مشی بدون نوع (typeless) استفاده میکنند.
در طول 15 سال گذشته یک تغییر بنیادین در روشی که مردم برنامه های رایانه را مینویسند درحال رخ دادن بوده است. آن تغییر یک گذار از زبانهای سیستمی همچون سی و سی++ به زبانهای اسکریپتی همچون پرل یا Tcl است. هرچند مردم زیادی در حال مشارکت در این تغییر هستند، عدهء کمی میدانند که تغییری در حال رخ دادن است و عدهء حتی کمتری میدانند که چرا آن درحال اتفاق افتادن است. این مقاله توضیح خواهد داد که چرا زبانهای اسکریپتی بسیاری از کارهای برنامه نویسی را در قرن آینده بهتر از زبانهای سیستمی اداره خواهند کرد.
زبانهای اسکریپتی برای کارهای متفاوتی نسبت به زبانهای سیستمی طراحی شده اند و این منجر به تفاوت های بنیادین در زبانها میشود. زبانهای سیستمی برای ساختن ساختمان های داده ای و الگوریتم ها از صفر که از بدوی ترین اجزای رایانه همچون کلمه های حافظه شروع میشوند طراحی شده بودند. در مقابل، زبانهای اسکریپتی برای اتصال طراحی شده اند: آنها فرض میکنند که مجموعه ای از کامپوننت های قوی وجود دارند و عمدتا برای اتصال کامپوننت ها طراحی شده اند. زبانهای سیستمی از نوع نوعگذاری قوی (strongly typed) هستند تا به مدیریت پیچیدگی کمک کنند، درحالیکه زبانهای اسکریپتی بدون نوع هستند تا اتصالات میان کامپوننت ها را ساده کرده و توسعهء سریع اپلیکیشن را فراهم سازند.
زبانهای اسکریپتی و سیستمی مکمل هستند، و بیشتر پلتفرم های رایانه ای از سال 1960 هر دو نوع زبانها را شامل شده اند. این زبانهای معمولا همراه با همدیگر در فریمورک های کامپوننت بکار میروند که کامپوننت ها با زبانهای سیستمی ایجاد شده و بوسیلهء زبانهای اسکریپتی متصل میشوند. هرچند، چند رویهء اخیر، همچون ماشین های سریعتر، زبانهای اسکریپتی بهتر، و اهمیت فزایندهء رابطهای کاربر گرافیکی و معماری های کامپوننتی و رشد اینترنت، کاربرد زبانهای اسکریپتی را به میزان زیادی افزایش داده اند. این رویه ها در طول دههء آینده ادامه پیدا خواهند کرد و اپلیکیشن های بیشتر و بیشتری بطور کامل با زبانهای اسکریپتی نوشته خواهند شد و زبانهای سیستمی عمدتا برای ایجاد کامپوننت ها بکار خواهند رفت.
-- زبانهای سیستمی
برای درک تفاوتها میان زبانهای اسکریپتی و سیستمی، مهم است بدانیم چطور زبانهای سیستمی بوجود آمدند. زبانهای سیستمی بعنوان جایگزینی برای زبان اسمبلی ایجاد شدند. در زبان اسمبلی، عملا هر جنبهء ماشین در برنامه منعکس شده است. هر عبارت برنامه نویسی نمایندهء یک دستورالعمل ماشین است و برنامه نویسان باید با جزییات سطح پایینی همچون اختصاص رجیستر و فرایند فراخوانی پراسیجرها کار کنند. بعنوان یک نتیجه، نوشتن و نگهداری برنامه های بزرگ در زبانهای اسمبلی دشوار است.
در اواخر 1950، زبانهای سطح بالاتر همچون Lisp، فرترن، و Algol شروع به پدیدار شدن کردند. در این زبانها، عبارت ها دیگر دقیقا معادل دستورالعمل های ماشین نبودند؛ یک کامپایلر هر عبارت را در کد منبع به یک توالی از دستورالعمل های باینری تبدیل میکند. در طول زمان یک سری از زبانهای سیستمی از Algol بوجود آمدند که شامل PL/1، پاسکال، سی، سی++ و جاوا است. زبانهای سیستمی پرفورمنس کمتری نسبت به زبانهای اسمبلی دارند اما اجازه میدهند تا اپلیکیشن ها بسیار سریعتر توسعه بیابند. بعنوان یک نتیجه، زبانهای برنامه نویسی سیستمی تقریبا بصورت کامل جایگزین زبانهای اسمبلی برای توسعهء اپلیکیشن های بزرگ شدند.
-- زبانهای سطح بالاتر
زبانهای سیستمی به دو شکل با زبان اسمبلی تفاوت دارند: آنها سطح بالاتر هستنند و آنها نوع قوی (strongly typed) هستند. اصطلاح «سطح بالاتر» به معنای آنست که جزییات زیادی بصورت خودکار انجام میشوند، بنابراین برنامه نویسان میتوانند کد کمتری را برای انجام کار یکسانی بنویسند. بطور مثال:
- اختصاص رجیستر بوسیلهء کامپایلر انجام شده و بنابراین برنامه نویس نیازی به نوشتن کد برای انتقال اطلاعات بین رجیسترها و حافظه ندارد.
- روند فراخوانی رویه ها (Procedure calling sequences) بصورت خودکار تولید میشوند؛ برنامه نویسان نیازی ندارند دربارهء انتقال آرگومانها به و از پشتهء فراخوانی نگران باشند.
- برنامه نویسان میتوانند کلمات کلیدی ساده ای همچون while و if را برای ساختارهای کنترلی استفاده کنند؛ کامپایلر تمام جزییات دستورالعمل ها را برای پیاده سازی ساختارهای کنترلی تولید میکند.
بطور میانگین، هر خط از کد در یک زبان سیستمی به حدود پنج دستورالعمل ماشین ترجمه میشود، در مقایسه با یک دستورالعمل بر هر خط در یک برنامهء اسمبلی (م: حذف بخشی از متن). برنامه نویسان میتوانند تقریبا تعداد یکسانی خط کد را در هر سال صرفنظر از زبان بنویسند، بنابراین زبانهای سیستمی اجازه میدهند تا اپلیکیشن ها بسیار سریعتر از زبانهای اسمبلی توسعه داده شوند.
-- نوعگذاری (Typing)
تفاوت دوم میان زبان اسمبلی و زبانهای سیستمی نوعگذاری است. من اصطلاح نوعگذاری را برای رجوع به حدی که اطلاعات پیش از استفاده اش مشخص میشود استفاده میکنم. در یک زبان نوع قوی، برنامه نویس اعلان میکند که هر قطعه از اطلاعات چگونه استفاده خواهد شد، و زبان از استفاده از اطلاعات به هر شکل دیگری جلوگیری میکند. در یک زبان نوع ضعیف (weakly typed)، محدودیتهای از پیش تعیین شده برای روی چگونگی استفاده از اطلاعات وجود ندارند؛ معنای اطلاعات صرفا بوسیلهء روشی که آنها استفاده میشوند تعیین میشود، نه بوسیلهء هر قول و قرارداد قبلی.
رایانه های مدرن اساسا بدون نوع هستند. هر کلمهء حافظه میتواند هر نوعی از مقدار را نگهداری کند، همچون یک عدد صحیح، یک عدد اعشاری، یک اشاره گر، یا یک دستورالعمل. معنای یک مقدار بوسیلهء روش استفادهء آن تعیین میشود. اگر شمارندهء برنامه (program counter) به یک کلمه از حافظه اشاره کند با آن بصورت یک دستورالعمل رفتار میشود؛ اگر یک کلمه بوسیلهء یک دستورالعمل جمع صحیح مورد ارجاع قرار گیرد، با آن بصورت یک عدد صحیح رفتار میشود؛ و غیره. کلمهء یکسانی میتواند به شکلهای مختلف در زمانهای مختلف استفاده شود.
در مقابل، زبانهای سیستمی امروزی نوع قوی هستند. بطور مثال:
- هر متغییر در یک زبان سیستمی باید با یک نوع خاص همچون متغییر یا اشاره گر به رشته اعلان شود، و بایست به شکلهایی استفاده شود که برای آن نوع مناسب هستند.
- داده و کد جدا شده اند؛ ایجاد کد بصورت on the fly، اگر غیرممکن نباشد، دشوار است.
- متغییرها میتوانند در داخل ساختارها یا اشیایی با زیر ساختارهای بخوبی تعریف شده و رویه ها یا متدهایی برای دستکاری آنها جمع شوند. یک شیء از یک نوع نمیتواند جاییکه یک شیء از نوع دیگری مورد انتظار است استفاده شود.
نوعگذاری چند مزیت دارد. نخست، برنامه های بزرگ را بوسیلهء روشن کردن اینکه چطور چیزها استفاده میشوند و تمیز دادن میان چیزهایی که باید با آنها بصورت متفاوتی رفتار شود بیشتر قابل مدیریت میسازد. دوم، کامپایلرها اطلاعات نوع را برای آشکارسازی بعضی انواع مشخص از خطاها، همچون تلاشی برای استفاده از یک عدد اعشاری بعنوان یک اشاره گر استفاده میکنند. سوم، نوعگذاری پرفورمنس را بوسیلهء اجازه دادن به کامپایلرها برای تولید کد اختصاصی بهبود میدهد. برای مثال، اگر یک کامپایلر بداند که یک متغییر همیشه یک مقدار عدد صحیح را نگهداری میکند، سپس آن میتواند دستورالعمل های عدد صحیح را برای دستکاری آن متغییر تولید کند؛ اگر کامپایلر نداند که نوع یک متغییر چیست، آن باید دستورالعمل های اضافه ای را برای چک کردن نوع متغییر در زمان اجرا تولید کند. شکل 1 یک مجموعهء متنوع از زبانها را بر اساس سطح برنامه نویسی و قدرت نوعگذاری مقایسه میکند.
-- زبانهای اسکریپتی
زبانهای اسکریپتی همچون پرل، پایتون، Rexx، Tcl، ویژوال بیسیک، و شل های یونیکس یک استایل برنامه نویسی کاملا متفاوت نسبت به زبانهای سیستمی را ارائه میدهند. زبانهای اسکریپتی فرض میکنند که مجموعه ای از کامپوننت های سودمند از پیش در زبانهای دیگر وجود دارند. آنها برای نوشتن اپلیکیشن ها از صفر درنظر گرفته نشده اند بلکه بیشتر برای ترکیب کردن کامپوننت ها درنظر گرفته شده اند. برای مثال Tcl و ویژوال بیسیک میتوانند برای چیدن مجموعه هایی از کنترل های رابط کاربری بر روی صفحه استفاده شوند، و اسکریپت های شل یونیکس برای سوار کردن برنامه های فیلتر کننده در خط لوله ها (pipeline - م: اصطلاحی در روش اتصال ورودی و خروجی برنامه ها در خط فرمان) استفاده میشوند. زبانهای اسکریپتی اغلب برای گسترش ویژگیهای کامپوننت ها استفاده میشوند؛ هرچند، آنها به ندرت برای الگوریتم های پیچیده و ساختارهای داده ای که معمولا توسط کامپوننت ها فراهم میشوند مورد استفاده قرار میگیرند. به زبانهای اسکریپتی بعضی اوقات تحت عنوان زبانهای متصل کننده/چسباننده (glue languages) یا زبانهای یکپارچه سازی سیستم (system integration languages) ارجاع میشود.
-- زبانهای اسکریپتی عموما بدون نوع هستند
برای ساده کردن کار اتصال کامپوننت ها، زبانهای اسکریپتی تمایل دارند تا بدون نوع باشند. همهء چیزها بطور یکسانی بنظر میرسند و بطور یکسانی رفتار میکنند تا بتوانند قابل تبادل باشند. برای مثال، در Tcl یا ویژوال بیسیک یک متغییر میتواند در یک لحظه یک رشته را نگهداری کند و دفعهء بعد یک عدد صحیح را. کد و داده اغلب قابل تبادل هستند، بنابراین یک برنامه میتواند برنامهء دیگری را نوشته و آن را درجا (on the fly) اجرا کند. زبانهای اسکریپتی اغلب رشته گرا (string-oriented) هستند، چراکه این یک نمایش یک شکل را برای بسیاری چیزهای متفاوت فراهم میاورد.
یک زبان بدون نوع بهم متصل کردن کامپوننت ها را خیلی ساده تر میکند. محدودیت های از پیش تعیین شده ای بر روی آنکه چیزها چطور میتوانند استفاده شوند وجود ندارد، و همهء کامپوننت ها و مقدارها به روش یک شکلی معرفی میشوند. بنابراین هر کامپوننت یا مقدار میتواند در هر شرایطی استفاده شود؛ کامپوننت هایی که برای یک مقصود طراحی شده اند میتوانند برای مقاصد کاملا متفاوتی که هرگز بوسیلهء طراح پیشبینی نمیشدند بکار روند. برای مثال، در شل های یونیکس (Unix shells) تمام برنامه های فیلتر یک جریان (stream) از بایتها را از ورودی خوانده و یک جریان از بایتها را در خروجی مینویسند. هر دو برنامه میتوانند بوسیلهء ضمیمه کردن خروجی یک برنامه به ورودی برنامهء دیگر بهم متصل شوند. فرمان شل روبرو سه فیلتر را برای شمارش تعداد خطهایی در متن انتخاب شده که حاوی کلمهء scripting هستند بهم متصل میکند: select | grep scripting | wc
برنامهء select متنی را که درحال حاضر در روی صفحهء نمایش انتخاب شده است میخواند و متن را در خروجی خودش چاپ میکند؛ برنامهء grep ورودی خودش را میخواند و در خروجی خطهایی را که شامل کلمهء scripting هستند چاپ میکند؛ برنامهء wc تعداد خطهای موجود در ورودی اش را میخواند. هر یک از این برنامه ها میتوانند در تعداد بیشماری شرایط دیگر برای انجام کارهای متفاوتی بکار روند.
طبیعت نوع قوی زبانهای سیستمی استفادهء مجدد را مشکل میکند. آن برنامه نویسان را تشویق میکند تا یک مجموعهء متنوع از رابطهای (interface) ناسازگار را بنویسند که هریک از آنها اشیایی از نوع خاصی را نیاز دارد. کامپایلر از استفاده از هر نوع دیگری از اشیاء با رابط مورد نظر جلوگیری میکند، حتی اگر آن میتوانست مفید باشد. پس برای استفاده از یک شیء جدید با یک رابط جدید، برنامه نویس باید کد تبدیلی را برای ترجمه بین نوع شیء و نوع مورد انتظار بوسیلهء رابط بنویسند. این خود باعث میشود که به کامپایل مجدد بخشی یا تمام اپلیکیشن نیاز باشد؛ بسیاری اپلیکیشن ها امروزه در شکل باینری توزیع میشوند و بنابراین این کار امکان ندارد.
برای تقدیر از فواید یک زبان بدون نوع، به فرمان Tcl زیر توجه کنید:
button .b -text Hello! -font {Times16} -command {puts hello}
این فرمان یک کنترل دکمهء جدید که یک رشتهء متنی را با یک فونت 16point Times نمایش داده و یک پیغام کوتاه را موقعی که کاربر روی کنترل کلیک میکند چاپ میکند ایجاد میکند. این فرمان شش نوع مختلف از چیزها را در یک عبارت ترکیب میکند: یک نام فرمان (button)، یک کنترل دکمه (.b)، نام پراپرتی ها (-text، -font، -command)، رشته های ساده (Hello! و hello) یک نام فونت (Times 16) که یک نام typeface (ا Times) و یک اندازه در واحد نقطه (16) را شامل میشود، و یک اسکریپت Tcl (ا puts hello). زبان Tcl تمام این چیزها را بوسیلهء رشته ها به شکل مشابهی نشان میدهد. در این مثال، پراپرتی ها میتوانند در هر ترتیبی مشخص شوند و پراپرتی های مشخص نشده مقدارهای پیشفرض را بدست میاورند؛ بیش از 20 پراپرتی در این مثال بصورت مشخص نشده بودند.
مثال یکسان وقتی در جاوا پیاده سازی شود نیاز به 7 خط کد در دو متد دارد. با سی++ و MFC آن به حدود 25 خط کد در سه procedure نیاز دارد. تنها تعیین فونت به چندین خط کد در MFC نیاز دارد:
CFont *fontPtr = new CFont();
fontPtr->CreateFont(16, 0, 0, 0, 700,
0, 0, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
“Times New Roman”);
buttonPtr->SetFont(fontPtr);
بسیاری از این کد نتیجهء نوع قوی بودن است. برای تعیین فونت یک دکمه، متد SetFont آن باید فراخوانی شود، اما به این متد باید یک اشاره گر به یک شیء CFont پاس شود. این خود باعث میشود نیاز باشد یک شیء جدید اعلان و مقداردهی اولیه شود. برای مقداردهی اولیهء شیء CFont متد CreateFont آن باید فراخوانی شود، اما متد CreateFont یک اینترفیس غیرمنعطف دارد که نیاز دارد 14 آرگومان مختلف مشخص شود. در Tcl، مشخصه های اساسی فونت (typeface Times, size 16 points) میتوانند بلافاصله بدون هیچ اعلان یا تبدیلی استفاده شوند. بعلاوه، Tcl اجازه میدهد تا رفتار دکمه مستقیما در فرمانی که دکمه را ایجاد میکند درج شود، درحالیکه در سی++ یا جاوا آن باید در یک متد بصورت جداگانه اعلان شده قرار داده شود (در عمل، یک مثال جزیی مانند این احتمالا بوسیلهء یک محیط توسعهء گرافیکی که پیچیدگی زبان زیرین را پنهان میکند مدیریت خواهد شد. کاربر مقدار پراپرتی ها را در یک فرم وارد کرده و محیط توسعه کد را تولید میکند. اما، در شرایط پیچیده تر، همچون اختصاص شرطی مقدار پراپرتی ها یا رابطهای تولید شده بصورت برنامه ای، توسعه دهنده باید کد را در زبان زیرین بنویسد).
ممکن است بنظر برسد که طبیعت بدون نوع زبانهای اسکریپتی میتواند به خطاها اجازه بدهد تا آشکارسازی نشوند، اما در عمل زبانهای اسکریپتی همانقدر امن هستند که زبانهای سیستمی هستند. برای مثال، یک خطا رخ خواهد داد اگر اندازهء فونت مشخص شده برای مثال دکمهء بالا یک رشتهء غیر عدد صحیح همچون xyz باشد. زبانهای اسکریپتی چک کردن خطای خود را در آخرین لحظهء ممکن انجام میدهد، وقتی که یک مقدار استفاده میشود. نوع قوی بودن اجازه میدهد تا خطاها در زمان کامپایل آشکارسازی شوند، بنابراین از هزینهء اجرای چک های زمان اجرا اجتناب میشود. هرچند، قیمت پرداخته شده برای کارایی، محدودیت هایی بر روی آنکه اطلاعات چطور میتوانند استفاده شوند است؛ این موجب کد بیشتر و برنامه هایی با انعطاف کمتر میشود.
-- زبانهای اسکریپتی تفسیر میشوند
تفاوت کلیدی دیگر بین زبانهای اسکریپتی و سیستمی آن است که زبانهای اسکریپتی معمولا تفسیر میشوند، درحالیکه زبانهای سیستمی معمولا کامپایل میشوند. زبانهای تفسیر شونده قابلیت تغییرات سریع را در زمان توسعه با حذف زمانهای کامپایل فراهم میکنند. مفسرها همچنین اپلیکیشن ها را بوسیلهء اجازه دادن کاربران به برنامه ریزی اپلیکیشن ها در زمان اجرا منعطف تر میسازند. برای مثال، بسیاری از ابزارهای ترکیب و تحلیل برای مدارهای مجتمع شامل یک مفسر Tcl هستند؛ کاربران برنامه ها اسکریپت های Tcl را برای مشخص کردن طراحی شان و کنترل عملیات ابزارها مینویسند. مفسرها همچنین با تولید کد بصورت درجا امکان ایجاد اثرهای قدرتمند را میدهند. برای مثال، یک مرورگر وب بر اساس Tcl میتواند یک صفحهء وب را با ترجمهء HTML به یک اسکریپت Tcl با استفاده از معدودی جایگزینی عبارات منظم (regular expression) تجزیه کند. آن سپس اسکریپت Tcl را برای نمایش صفحه بر روی صفحهء نمایش اجرا میکند.
زبانهای اسکریپتی از زبانهای سیستمی پرفورمنس کمتری دارند، بخشی بخاطر آنکه آنها از مفسرها بجای کامپایلرها استفاده میکنند اما همچنین بخاطر آنکه اجزای پایهء آنها برای قدرت و استفادهء آسان انتخاب شده اند تا یک نگاشت با پرفورمنس بالا به سخت افزار زیرین. برای مثال، زبانهای اسکریپتی اغلب در شرایطی که یک زبان سیستمی از یک مقدار باینری که در یک کلمهء منفرد حافظه جا میگیرد استفاده خواهد کرد از رشته های با طول متغییر استفاده میکنند، و آنها از hash table ها در جایی که زبانهای سیستمی از آرایه های ایندکس شده استفاده میکنند استفاده میکنند.
خوشبختانه، معمولا پرفورمنس یک زبان اسکریپتی یک مشکل عمده نیست. اپلیکیشن ها برای زبانهای اسکریپتی عموما کوچکتر از اپلیکیشن ها برای زبانهای سیستمی هستند، و پرفورمنس یک زبان اسکریپتی تمایل دارد تا بوسیلهء پرفورمنس کامپوننت هایی مورد احاطه قرار گیرد که معمولا در یک زبان سیستمی پیاده میشوند.
زبانهای اسکریپتی از زبانهای سیستمی سطح بالاتر هستند از این جهت که یک عبارت منفرد بطور میانگین کار بیشتری را انجام میدهد. یک عبارت عادی در یک زبان اسکریپتی صدها یا هزاران دستورالعمل ماشین را اجرا میکند، درحالیکه یک عبارت عادی در یک زبان سیستمی درحدود پنج دستورالعمل ماشین را اجرا میکند (همانطور که شکل 1 نشان میدهد). بخشی از این تفاوت بخاطر آنست که زبانهای اسکریپتی از مفسرها استفاده میکنند، اما خیلی از این تفاوت بخاطر آنست که عملیات اولیه در زبانهای اسکریپتی امکانات بیشتری دارند. برای مثال، در پرل فراخوانی یک جایگزینی عبارت منظم تقریبا به آسانی فراخوانی یک جمع عدد صحیح است. در Tcl، یک متغییر میتواند trace هایی را پیوند شده به آن داشته باشد تا تعیین مقدار متغییر باعث اثرات جانبی شود؛ برای مثال، یک trace میتواند برای آپدیت نگه داشتن مقدار متغییر در روی صفحهء نمایش بکار رود.
زبانهای اسکریپتی اجازه میدهند تا توسعهء سریع کاربردهای اتصال گرا انجام شود. جدول 1 پشتیبانی روایتی برای این ادعا فراهم میکند. آن چند اپلیکیشن را توصیف میکند که در یک زبان سیستمی پیاده سازی شده بودند و سپس در یک زبان اسکریپتی پیاده سازی مجدد شدند یا بعکس. در همهء موارد، نسخهء اسکریپتی نیاز به کد و زمان توسعهء کمتری نسبت به نسخهء زبان سیستمی داشته است؛ اختلاف از یک فاکتور 2 تا یک فاکتور 60 متغییر است. زبانهای اسکریپتی فایدهء کمتری فراهم میکنند وقتی که آنها برای نخستین پیاده سازی استفاده میشوند؛ این اشاره میکند که هر پیاده سازی مجدد از تجربهء بدست آمده از نخستین پیاده سازی سود قابل توجهی میبرد و اختلاف واقعی بین اسکریپت نویسی و برنامه نویسی سیستمی به احتمال بیشتر یک فاکتور از 5 تا 10 میباشد. منافع اسکریپت نویسی همچنین بسته به اپلیکیشن است. در مثال آخر در جدول 1، بخش رابط کاربر گرافیکی اپلیکیشن اتصال گرا است اما بخش شبیه ساز اینطور نیست؛ این میتواند توضیح دهد که چرا اپلیکیشن مورد نظر نسبت به اپلیکیشن های دیگر کمتر از اسکریپت نویسی سود برده است.
ااطلاعات جدول بوسیلهء توسعه دهندگان مختلف Tcl در پاسخ به مقاله ای که در گروه خبری comp.lang.tcl پست شده بود فراهم شده بود.
-- ابزارهای مختلف برای کارهای مختلف
یک زبان اسکریپتی یک جایگزین برای یک زبان سیستمی نیست یا بعکس. هر یک برای یک مجموعه از کارهای متفاوت مناسبند. برای اتصال و یکپارچه سازی سیستم، اپلیکیشن ها میتوانند از 5 تا 10 بار سریعتر بوسیلهء یک زبان اسکریپتی توسعه داده شوند؛ زبانهای برنامه نویسی سیستمی نیاز به مقدار زیادی کدهای پایه و کد تبدیل برای اتصال قطعات دارند، درحالیکه این میتواند مستقیما توسط یک زبان اسکریپتی انجام شود. برای الگوریتم های پیچیده و ساختمان داده ها، نوعگذاری قوی یک زبان سیستمی مدیریت برنامه را ساده تر میسازد. جاییکه سرعت اجرا یک مسئلهء کلیدی است، یک زبان سیستمی میتواند 10 تا 20 برابر سریعتر از یک زبان اسکریپتی اجرا شود زیرا آن چک های زمان اجرای کمتری انجام میدهد.
بقیهء مقاله در پست بعدی (بعلت محدودیت حجم پست در فروم)...