مسیر یک زبان
جیمز گاسلینگ در Sun و در چارچوب پروژهٔ Green روی زبانی کار کرد که ابتدا Oak نام داشت و سپس Java شد. این مسیر حاصل همکاری با دیگر اعضای تیم بود. ماشین مجازی در رویکرد اجرای برنامه روی محیطهای متفاوت اهمیت داشت.
پرسش فنی
قابلیت حمل تنها مسئلهٔ syntax نیست؛ runtime، کتابخانه و رفتار محیط هم مهماند. برای ارزیابی اجرای چندسکویی، همان برنامه را با وابستگیهای واقعی و شرایط هدف آزمایش کنید.
ماشین مجازی چه چیزی را یکسان میکند؟
یک ماشین مجازی میتواند هدف مشترکی برای اجرای برنامه فراهم کند، در حالی که پیادهسازی آن روی سختافزارها و سیستمعاملهای مختلف متفاوت است. این لایه، بخشی از تفاوت محیطها را مدیریت میکند. اما برنامه هنوز ممکن است به فایل، شبکه، کتابخانهٔ بومی یا رفتار خاص سیستمعامل وابسته باشد؛ بنابراین قابلیت حمل یک ویژگی است که باید آزموده شود.
در تاریخ Java، پروژهٔ Green، نام اولیهٔ Oak و کار گروهی در Sun زمینهٔ مهمی دارند. تمرکز صرف بر یک شعار چندسکویی، مسیر آزمایش و تغییر هدفهای پروژه را پنهان میکند. زبان، runtime و کتابخانهها با هم تجربهٔ توسعه را میسازند.
مثال آموزشی: همان برنامه، دو محیط
برنامهای را تصور کن که فایل پیکربندی میخواند و به یک سرویس شبکه وصل میشود. حتی اگر منطق آن یکسان باشد، مسیر فایل، مجوز دسترسی، encoding و گواهیهای مورد اعتماد میتوانند در دو محیط متفاوت باشند. آزمون چندسکویی باید این مرزها را بسنجد، نه اینکه فقط اجرای یک پیام ساده را تأیید کند.
همچنین مدیریت خودکار حافظه به معنی نبود همهٔ خطاهای منابع نیست. برنامه میتواند فایل یا اتصال را باز نگه دارد، دادهٔ زیادی را بیدلیل حفظ کند یا صفی بدون حد بسازد. شناخت مدل اجرا، برای نوشتن نرمافزار قابل اتکا ضروری است.
برداشت آموزشی IROSG
برای یک پروژهٔ کوچک، وابستگیهای محیطی را فهرست کن: نسخهٔ runtime، کتابخانهها، متغیرهای تنظیمات و دسترسیهای لازم. آن را در دو محیط تمیز بساز و اجرا کن، سپس اختلافها را مستند کن. با این کار، «روی سیستم من اجرا شد» به یک آزمون بازتولیدپذیر تبدیل میشود.
مطالعهٔ گاسلینگ فرصتی است برای دیدن طراحی زبان در کنار طراحی محیط اجرا. انتخاب یک فناوری فقط تصمیم برنامهنویس دربارهٔ syntax نیست؛ به عملیات، انتشار، خطایابی و نگهداری نیز مربوط میشود. جزئیات تاریخی در منبع موزهٔ تاریخ رایانه قابل پیگیری است.
قابلیت حمل را به چند پرسش کوچک بشکنیم
وقتی میگوییم برنامه روی چند محیط اجرا میشود، باید مشخص کنیم کدام بخش قابل حمل است: متن منبع، قالب میانی، کتابخانهها یا رفتار نهایی. یک برنامه ممکن است ساخته شود اما به مسیر فایل، قلم، شبکه یا تنظیم زمانِ یک محیط وابسته بماند. برای مطالعهٔ ایدهٔ ماشین مجازی، این لایهها را جدا ببینید. مثالهای این قسمت آموزشیاند و بازنشر کد پروژهٔ Green یا Java نیستند.
یک برنامهٔ سادهٔ خواندن فایل را در نظر بگیرید. اگر مسیر فایل در متن برنامه ثابت باشد، تغییر محیط میتواند آن را بشکند. حالا مسیر را به ورودیِ روشن تبدیل کنید و رفتار در برابر نبود فایل را تعریف کنید. این تغییر کوچک نشان میدهد قابلیت حمل فقط ویژگی ابزار اجرا نیست؛ تصمیمهای خود برنامه هم در آن سهم دارند. قرارداد ورودی و وابستگی بیرونی باید قابل فهم و آزمون باشد.
ماشین مجازی بهعنوان مرز قراردادی
در یک مدل آموزشی، برنامه دستورهایی برای یک ماشینِ تعریفشده تولید میکند و پیادهسازی آن ماشین در هر محیط رفتار لازم را فراهم میسازد. این توضیح ساده همهٔ جزئیات اجرایی را پوشش نمیدهد، اما کمک میکند نقش یک لایهٔ میانی را بفهمیم. مزیت بالقوه، جداکردن بخشی از برنامه از جزئیات سختافزار است؛ هزینهها و محدودیتهای اجرا همچنان باید اندازهگیری شوند.
برای تمرین، یک زبان بسیار کوچک با سه عملیات حسابی تعریف کنید و دو مفسر ساده برای آن بنویسید. داده و دامنهٔ دستورها را محدود نگه دارید و کد ناشناخته اجرا نکنید. اگر دو مفسر برای ورودی یکسان نتیجهٔ متفاوت دادند، قرارداد نیاز به اصلاح دارد. این تجربه بهجای حفظ اصطلاح، نشان میدهد توافق بر سر رفتار چگونه استقلال پیادهسازی را ممکن میکند.
وابستگیهای بیرونی را فراموش نکنیم
قالب متن، منطقهٔ زمانی و قواعد مقایسهٔ رشتهها میتوانند نتیجهٔ کاربرد را تغییر دهند. به همین دلیل آزمون چندسکویی باید دادههای متنوع و شرایط واقعی را ببیند. فایلی با نویسهٔ فارسی، یک تاریخ نزدیک مرز روز و مقدار خالی میتوانند فرضهایی را آشکار کنند که در نمونهٔ ساده دیده نشدهاند. اینها پیشنهاد آزموناند، نه ادعای وجود اشکال در یک نسخهٔ مشخص از Java.
برای گزارش، محیط و نتیجهٔ هر اجرا را جدا ثبت کنید. عبارت «همهجا کار میکند» را به فهرست شرایطی تبدیل کنید که واقعاً آزموده شدهاند. اگر محیطی بررسی نشده، آن را صریح نامشخص بگذارید. این شیوهٔ بیان شاید از یک شعار تبلیغاتی کمهیجانتر باشد، اما برای مصرفکنندهٔ فنی قابل اتکاتر است و محدودهٔ مسئولیت تیم را روشن میکند.
مدیریت منابع، فراتر از حافظه
وجود ابزار مدیریت حافظه، نیاز به مدیریت فایل، اتصال و سایر منابع را حذف نمیکند. برنامه باید بداند چه چیزی را باز میکند، چه زمانی آزاد میکند و در مسیر خطا چه رفتاری دارد. در یک تمرین کوچک، عملیات خواندن فایل را عمداً در میانهٔ کار متوقف کنید و وضعیت منبع را بررسی کنید. آزمایش باید روی فایل ساختگی انجام شود تا دادهٔ واقعی در معرض خطر قرار نگیرد.
سپس یک بار موفقیت و یک بار شکست را دنبال کنید. آیا پاکسازی در هر دو مسیر انجام میشود؟ آیا پیام خطا اطلاعات کافی و نه بیش از حد لازم دارد؟ این سؤالها به کیفیت مهندسی کمک میکنند و مستقل از شهرت زباناند. ابزار اجرا میتواند بعضی مسئولیتها را ساده کند، اما قراردادِ چرخهٔ عمر منابع همچنان باید در طراحی برنامه دیده شود.
از نمونهٔ اولیه تا سامانهٔ قابل نگهداری
پروژهٔ کوچک معمولاً با یک مثال موفق شروع میشود. برای ادامه باید وابستگی، آزمون، انتشار و سازگاری نیز تعریف شوند. تغییر یک کتابخانه میتواند روی مصرفکننده اثر بگذارد، حتی وقتی متن اصلی برنامه ثابت مانده است. بنابراین نسخه و شرایط اجرا را بخشی از مستند بدانید. چنین مستندی لازم نیست طولانی باشد؛ باید پاسخ دهد نفر بعدی چگونه همان نتیجه را بازتولید میکند.
در پایان مطالعهٔ گاسلینگ، یک برنامهٔ خود را در دو محیطِ کنترلشده بررسی کنید و تفاوتها را به سه دسته تقسیم کنید: قرارداد برنامه، وابستگی بیرونی و رفتار محیط اجرا. این دستهبندی از تعمیم عجولانه جلوگیری میکند. برای مسیر تاریخی Oak و Java و نقش اعضای تیم به منابع انتهای صفحه رجوع کنید؛ تمرین حاضر برای فهم یک ایدهٔ معماری است و هیچ تضمین چندسکویی برای محصول خاصی ارائه نمیدهد.