بلوک های سفارشی: راهنمای سبک

در طول سال‌ها، تیم Blockly and Blockly Games درس‌های زیادی آموخته است که برای کسانی که بلاک‌های جدید را توسعه می‌دهند قابل استفاده است. موارد زیر مجموعه ای از اشتباهاتی است که ما مرتکب شده ایم یا اشتباهاتی که معمولاً توسط دیگران انجام می شود.

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

1. شرایط در مقابل حلقه ها

سخت ترین بلوک ها برای کاربران جدید شرطی ها و حلقه ها هستند. بسیاری از محیط‌های مبتنی بر بلوک، هر دوی این بلوک‌ها را در یک دسته «کنترل‌ها» دسته‌بندی می‌کنند که هر دو بلوک دارای شکل و رنگ یکسان هستند. این اغلب منجر به ناامیدی می شود زیرا کاربران جدید این دو بلوک را اشتباه می گیرند. Blockly توصیه می‌کند که شرط‌ها و حلقه‌ها را به دسته‌های «Logic» و «Loops» جداگانه منتقل کنید که هر کدام رنگ‌های متفاوتی دارند. این روشن می کند که این ایده های متمایز هستند که با وجود داشتن اشکال مشابه، رفتار متفاوتی دارند.

توصیه: شرطی ها و حلقه ها را از هم جدا نگه دارید.

2. لیست های یک پایه

برنامه نویسان تازه کار وقتی برای اولین بار با لیست های مبتنی بر صفر مواجه می شوند، واکنش بدی نشان می دهند. در نتیجه، Blockly از Lua و Lambda Moo با فهرست‌بندی و فهرست‌بندی رشته‌ای به‌صورت یک‌پایه پیروی می‌کند.

برای استفاده های پیشرفته تر از Blockly، لیست های مبتنی بر صفر پشتیبانی می شوند تا انتقال به متن آسان تر شود. برای مخاطبان جوانتر یا تازه کار، نمایه سازی تک پایه همچنان توصیه می شود.

توصیه: یک عدد اول است.

3. ورودی های کاربر

سه راه برای دریافت پارامتر از کاربر وجود دارد. یک کشویی محدود کننده ترین است و برای آموزش ها و تمرین های ساده خوب است. یک فیلد ورودی آزادی بیشتری را فراهم می‌کند و برای فعالیت‌های خلاقانه‌تر خوب است. ورودی بلوک مقدار (معمولاً با یک بلوک سایه) فرصتی را برای محاسبه یک مقدار (مثلاً یک مولد تصادفی) به جای اینکه فقط یک مقدار ثابت باشد، ارائه می دهد.

توصیه: یک روش ورودی مناسب برای کاربران خود انتخاب کنید.

4. تصاویر بلوک زنده

مستندات بلوک‌ها باید شامل تصاویر بلوک‌هایی باشد که به آنها اشاره می‌کند. گرفتن اسکرین شات آسان است. اما اگر 50 تصویر از این دست وجود داشته باشد و برنامه به 50 زبان ترجمه شود، ناگهان یکی در حال حفظ 2500 تصویر ثابت است. سپس طرح رنگ تغییر می کند و 2500 تصویر نیاز به به روز رسانی دارند -- دوباره.

برای اینکه خود را از این کابوس نگهداری خارج کنیم، Blockly Games همه اسکرین شات ها را با نمونه هایی از Blockly که در حالت فقط خواندنی اجرا می شود جایگزین کرد. نتیجه شبیه به یک عکس به نظر می رسد، اما به روز بودن آن تضمین شده است. حالت فقط خواندنی بین المللی شدن را ممکن کرده است.

توصیه: اگر از بیش از یک زبان پشتیبانی می کنید، از حالت فقط خواندنی استفاده کنید.

5. چپ دیگر شما

بازخورد کودکان در ایالات متحده (البته جالب است که نه از کشورهای دیگر) سردرگمی گسترده بین چپ و راست را نشان داد. این با اضافه کردن فلش حل شد. اگر جهت نسبی است (مثلاً نسبت به آواتار)، سبک پیکان مهم است. یک فلش → مستقیم یا یک فلش چرخشی ↱ زمانی که آواتار در جهت مخالف باشد گیج کننده است. مفیدترین فلش دایره ای ⟳ است، حتی در مواردی که زاویه چرخش کوچکتر از آن است که فلش نشان می دهد.

توصیه: در صورت امکان متن را با نمادهای یونیکد تکمیل کنید.

6. بلوک های سطح بالا

تا جایی که ممکن است باید رویکردی در سطح بالاتر اتخاذ شود، حتی اگر عملکرد یا انعطاف‌پذیری اجرا را کاهش دهد. این عبارت Apps Script را در نظر بگیرید:

SpreadsheetApp.getActiveSheet().getDataRange().getValues()

تحت یک نقشه برداری 1:1 که تمام قابلیت های بالقوه را حفظ می کند، عبارت فوق با استفاده از چهار بلوک ساخته می شود. اما Blockly یک سطح بالاتر را هدف قرار می دهد و یک بلوک را ارائه می دهد که کل عبارت را در بر می گیرد. هدف، بهینه سازی برای 95٪ مورد است، حتی اگر 5٪ باقیمانده را دشوارتر کند. Blockly قرار نیست جایگزینی برای زبان‌های مبتنی بر متن باشد، بلکه در نظر گرفته شده است که به کاربران کمک کند تا از منحنی یادگیری اولیه عبور کنند تا بتوانند از زبان‌های مبتنی بر متن استفاده کنند.

توصیه: کورکورانه کل API خود را به بلوک تبدیل نکنید.

7. مقادیر بازگشتی اختیاری

بسیاری از توابع در برنامه نویسی مبتنی بر متن یک عمل را انجام می دهند، سپس یک مقدار را برمی گردانند. این مقدار بازگشتی ممکن است استفاده شود یا نباشد. یک مثال تابع pop() پشته است. Pop ممکن است برای دریافت و حذف آخرین عنصر فراخوانی شود، یا ممکن است برای حذف آخرین عنصر با نادیده گرفتن مقدار بازگشتی فراخوانی شود.

var last = stack.pop();  // Get and remove last element.
stack.pop();  // Just remove last element.

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

الف) مشکل را حل کنید. بیشتر زبان‌های مبتنی بر بلوک، زبان را برای اجتناب از این موارد طراحی می‌کنند. به عنوان مثال، Scratch هیچ بلوکی ندارد که هم عوارض جانبی و هم مقدار بازگشتی داشته باشد.

ب) دو بلوک ارائه دهید. اگر فضای جعبه ابزار مشکلی نیست، یک راه حل ساده این است که دو مورد از هر یک از این نوع بلوک ها را فراهم کنید، یکی با و دیگری بدون مقدار بازگشتی. نقطه ضعف این است که این می تواند به یک جعبه ابزار گیج کننده با تعداد زیادی بلوک تقریباً یکسان منجر شود.

ج) یک بلوک را جهش دهید. از یک کشویی، چک باکس یا کنترل دیگری استفاده کنید که به کاربر امکان می دهد مقدار بازگشتی وجود داشته باشد یا خیر. سپس بلوک بسته به گزینه هایش شکل خود را تغییر می دهد. نمونه ای از آن را می توان در بلوک دسترسی به لیست Blockly مشاهده کرد.

د) ارزش را بخورید. اولین نسخه App Inventor یک بلوک لوله مخصوص ایجاد کرد که هر مقدار متصل را می خورد. کاربران این مفهوم را درک نکردند و نسخه دوم App Inventor بلوک لوله را حذف کرد و به جای آن توصیه کرد که کاربران به سادگی مقدار را به یک متغیر دور ریخته اختصاص دهند.

توصیه: هر استراتژی دارای مزایا و معایب است، آنچه را که برای کاربران شما مناسب است انتخاب کنید.

8. بلوک های در حال رشد

بلوک های خاص ممکن است به تعداد متغیر ورودی نیاز داشته باشند. به عنوان مثال، یک بلوک جمعی که مجموعه دلخواه اعداد را جمع می کند، یا یک بلوک if/elseif/else با مجموعه دلخواه از عبارت های elseif، یا یک سازنده لیست با تعداد دلخواه از عناصر اولیه هستند. چندین استراتژی وجود دارد که هر کدام مزایا و معایب خود را دارند.

الف) ساده ترین روش این است که کاربر را وادار کنیم بلوک را از بلوک های کوچکتر بسازد. به عنوان مثال می توان سه عدد را با تودرتو کردن دو بلوک جمع دو عددی جمع کرد. مثال دیگر فقط ارائه بلوک‌های if/else و ساختن کاربر برای ایجاد شرایط elseif است.

مزیت این رویکرد سادگی اولیه آن است (هم برای کاربر و هم برای توسعه دهنده). عیب آن این است که در مواردی که تعداد زیادی تودرتو وجود دارد، کد بسیار دست و پا گیر می شود و خواندن و نگهداری آن برای کاربر دشوار می شود.

ب) یک جایگزین این است که بلوک را به صورت پویا گسترش دهیم تا همیشه یک ورودی آزاد در انتها وجود داشته باشد. به همین ترتیب، اگر دو ورودی آزاد در پایان وجود داشته باشد، بلوک آخرین ورودی را حذف می کند. این رویکردی است که اولین نسخه App Inventor از آن استفاده کرد.

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

ج) برای حل مشکل حفره، برخی از توسعه دهندگان دکمه های +/- را به بلوک ها اضافه می کنند که به صورت دستی ورودی ها را اضافه یا حذف می کنند. Open Roberta از دو دکمه برای افزودن یا حذف ورودی ها از پایین استفاده می کند. سایر توسعه دهندگان دو دکمه در هر ردیف اضافه می کنند تا درج و حذف از وسط پشته امکان پذیر باشد. دیگران دو دکمه بالا/پایین را در هر ردیف اضافه می‌کنند تا ترتیب مجدد پشته انجام شود.

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

د) منعطف ترین روش افزودن یک حباب جهش دهنده به بلوک است. این به عنوان یک دکمه واحد نمایش داده می شود که یک گفتگوی پیکربندی را برای آن بلوک باز می کند. عناصر ممکن است به دلخواه اضافه، حذف یا مرتب شوند.

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

توصیه: هر استراتژی دارای مزایا و معایب است، آنچه را که برای کاربران شما مناسب است انتخاب کنید.

9. تولید کد پاک

کاربران پیشرفته Blockly باید بتوانند به کد تولید شده (جاوا اسکریپت، پایتون، پی اچ پی، لوا، دارت و غیره) نگاه کنند و فوراً برنامه ای را که نوشته اند تشخیص دهند. این بدان معناست که باید تلاش بیشتری برای خوانایی این کد تولید شده توسط ماشین انجام شود. پرانتزهای اضافی، متغیرهای عددی، فضاهای خالی خرد شده و الگوهای کد پرمخاطب، همگی مانع از تولید کد ظریف می شوند. کد تولید شده باید شامل نظرات باشد و باید با راهنماهای سبک Google مطابقت داشته باشد.

توصیه: به کد تولید شده خود افتخار کنید. آن را به کاربر نشان دهید.

10. وابستگی زبان

یک عارضه جانبی تمایل به کد پاک این است که رفتار Blockly تا حد زیادی بر اساس نحوه رفتار زبان متقابل کامپایل شده تعریف می شود. رایج‌ترین زبان خروجی جاوا اسکریپت است، اما اگر Blockly به زبان دیگری کامپایل می‌کند، هیچ تلاش غیرمنطقی برای حفظ رفتار دقیق در هر دو زبان نباید انجام شود. به عنوان مثال، در جاوا اسکریپت یک رشته خالی false است، در حالی که در Lua درست است. تعریف یک الگوی رفتاری واحد برای اجرای کد Blockly بدون توجه به زبان مقصد، منجر به ایجاد کد غیرقابل نگهداری می شود که به نظر می رسد از کامپایلر GWT خارج شده است.

توصیه: Blockly یک زبان نیست، اجازه دهید زبان موجود بر رفتار تأثیر بگذارد.