اگر قرار باشد یک اپ یادداشت بسازیم، انتخاب فناوری ظاهراً ساده است: چند صفحه فهرست، یک ویرایشگر و دکمه ذخیره. اما همین اپ وقتی باید روی دو سیستمعامل کار کند، آفلاین بماند و بعد از بستن برنامه نوشتهها را حفظ کند، سؤالهای جدیتری پیش میآورد. آیا تیم دو نسخه مستقل میخواهد؟ رابط چقدر باید با رفتار هر پلتفرم هماهنگ باشد؟ کدام قابلیت دستگاه برای محصول حیاتی است؟
این مقاله آغاز مسیر ساخت یک اپ یادداشت نمونه است. هنوز سراغ پیادهسازی نمیرویم؛ اول تصمیم میگیریم توسعه بومی یا چندسکویی برای همین محصول، با همین تیم و محدودیتها چه معنایی دارد. با دانستن مفاهیم ابتدایی توسعه نرمافزار میتوانید بحث را دنبال کنید. خروجی، یک تصمیم مستند و یک برنامه آزمایش کوتاه است؛ نه فهرستی از برندهها و بازندههای همیشگی.
دو اصطلاح، چند انتخاب متفاوت
در توسعه بومی یا Native، بخش اصلی اپ با ابزارهای پلتفرم هدف ساخته میشود. برای اندروید معمولاً از Kotlin و ابزارهای رابط اندروید و برای پلتفرم اپل از Swift و ابزارهای همان محیط استفاده میشود. اگر هر دو پلتفرم لازم باشند، مسئولیت نگهداری تجربه و انتشار هر دو نسخه هم وجود دارد؛ حتی وقتی تیم بخشی از منطق یا قراردادها را مشترک نگه دارد.
توسعه چندسکویی یک روش واحد نیست. Flutter رابط را با چارچوب و سازوکار رندر خودش میسازد؛ React Native به اجزای پلتفرم و کد اختصاصی هر محیط هم راه میدهد. میتوان بعضی بخشها را مشترک کرد و برای قابلیت خاص، پیادهسازی بومی داشت. بنابراین «یک بار مینویسیم و همهجا بدون تغییر اجرا میشود» وعده مناسبی برای برنامهریزی پروژه نیست.
در این مقاله، مقایسه در سطح تصمیم محصول است. دستور نصب یا API وابسته به نسخه ارائه نمیکنیم؛ جزئیات اجرا باید هنگام شروع نمونه فنی با نسخه مشخص ابزارها ثبت شود. توضیح سازوکار Flutter و امکان کد اختصاصی پلتفرم در React Native را از مستندات رسمی انتهای مقاله میتوان دقیقتر دنبال کرد.
اپ نمونه دقیقاً چه کاری انجام میدهد؟
کاربر باید بتواند یک یادداشت متنی بسازد، بعداً آن را پیدا کند و ویرایش کند. نوشته پس از خروج از اپ باقی میماند. در ادامه مجموعه، کار آفلاین، همگامسازی و حل تعارض دو دستگاه را اضافه میکنیم. فعلاً ویرایش همزمان چندنفره، دستنویس با قلم و پردازش سنگین فایل جزو محدوده نیستند.
همین مرزبندی مهم است. اپی که فقط متن ثبت میکند با اپی که باید تأخیر قلم را به حداقل برساند، فایل صوتی طولانی ضبط کند و در پسزمینه پردازش انجام دهد، مسئله یکسانی ندارد. هرچه وابستگی به رفتار خاص دستگاه بیشتر شود، باید سهم بیشتری از تحقیق را به آن قابلیت اختصاص داد؛ نام چارچوب بهتنهایی پاسخ را تعیین نمیکند.
- مسیر حیاتی: بازکردن اپ، ساخت یادداشت، بستن برنامه و پیداکردن دوباره همان متن.
- نیاز کیفی: تایپ روان فارسی و انگلیسی، حفظ جای نشانگر و کارکرد مناسب کیبورد.
- محدودیت تیم: تعداد توسعهدهندگان، مهارت فعلی و زمانی که برای نگهداری دو نسخه دارند.
- محدودیت انتشار: دسترسی به ابزار ساخت، دستگاه آزمون و حسابهای لازم هر پلتفرم.
اشتراک کد کجا واقعاً ارزش ایجاد میکند؟
در اپ یادداشت، مدل داده، بخشی از قواعد اعتبارسنجی و ارتباط با سرور میتوانند بین دو پلتفرم مشابه باشند. اشتراک این بخشها ممکن است دوبارهکاری را کمتر کند. اما درصد کد مشترک معیار کافی برای موفقیت نیست: اگر اصلاح رفتار انتخاب متن در هر انتشار چند روز زمان بگیرد، بالا بودن آن درصد کمک زیادی به کاربر نمیکند.
باید هزینه مسیر کامل را دید. پیادهسازی، آزمون روی دستگاه، رفع اشکال وابسته به سیستمعامل، ساخت نسخه و پاسخگویی به مشکلهای پس از انتشار همگی بخشی از کار هستند. حتی دو اپ با کد کاملاً مشترک، روی دو سیستمعامل به آزمون نیاز دارند. تفاوت مجوزها، کیبورد، رفتار بازگشت و چرخه عمر برنامه با مشترکبودن مخزن از بین نمیرود.
مهارت تیم بخشی از معماری است
فرض کنید تیمی تجربه جدی React دارد و باید یک محصول با فرم، فهرست و ارتباط معمول با API عرضه کند. بررسی React Native برای این تیم منطقی است، چون بخشی از دانستههای رابط و زبان را با خود میآورد. بااینحال تجربه وب جای شناخت چرخه عمر موبایل، انتشار و عیبیابی دستگاه را نمیگیرد.
در مقابل، اگر محصول در آغاز فقط اندروید است و تیم تجربه Kotlin دارد، ایجاد یک لایه چندسکویی صرفاً به امید نسخه احتمالی آینده ممکن است هزینه زودرس ایجاد کند. از طرف دیگر، تیمی که از ابتدا باید هر دو نسخه را با منابع محدود نگه دارد، باید هزینه دو پیادهسازی مستقل را جدی بگیرد. تصمیم درست با عوضشدن این فرضها تغییر میکند.
یک جدول تصمیم کوچک، با شاهد مشخص
امتیازدادن به ابزارها فقط وقتی مفید است که پشت هر امتیاز یک شاهد باشد. جمله «عملکرد این ابزار بهتر است» بدون ذکر دستگاه، سناریو و اندازه داده، برای تصمیم پروژه کافی نیست. بهتر است جدول به پرسشهایی وصل شود که میتوان در نمونه فنی پاسخشان را دید.
| معیار | پرسش برای اپ یادداشت | شاهد موردنیاز |
|---|---|---|
| تجربه نوشتن | متن دوزبانه و انتخاب متن درست کار میکند؟ | آزمون ویرایشگر روی دستگاه هدف |
| قابلیت دستگاه | اشتراکگذاری فایل و بازکردن لینک چه محدودیتی دارد؟ | یک مسیر کامل با مجوز واقعی |
| نگهداری | تیم خطای اختصاصی پلتفرم را تشخیص میدهد؟ | بررسی ابزار عیبیابی و مهارت موجود |
| انتشار | نسخه قابل نصب هر دو محیط ساخته میشود؟ | خروجی ساخت و نصب روی دستگاه |
ضروریها را با امکانات دلخواه جمع نزنید. اگر یک نیاز حیاتی اصلاً قابل پیادهسازی نیست، ده امتیاز خوب در بخشهای کماهمیت آن را جبران نمیکند. ابتدا شرطهای حذف را بررسی کنید؛ بعد سراغ وزندادن به هزینه و سهولت توسعه بروید.
نمونه فنی را دور سختترین فرض بسازیم
برای مقایسه، دو صفحه خوشرنگ و یک دکمه شمارنده اطلاعات زیادی نمیدهند. در اپ ما، بخش پرریسک میتواند ویرایش متن فارسی و حفظ داده باشد. نمونه باید همان را اجرا کند: یادداشت نسبتاً بلند، ترکیب عدد و متن انگلیسی، تغییر جهت دستگاه و بازگشت بعد از بستن برنامه. این سناریوها را قبل از شروع آزمایش بنویسید تا نتیجه تحت تأثیر ظاهر نمونه قرار نگیرد.
نمونه کوتاه قرار نیست معماری نهایی را ثابت کند. هدفش کمکردن یک عدم قطعیت است. مثلاً میخواهیم بدانیم ویرایشگر انتخابی رفتار قابل قبولی دارد یا نه و آیا برای اصلاح آن به کد بومی نیاز داریم. زمان ساخت نمونه، نسخه ابزارها، دستگاهها و مشکلهای مشاهدهشده را ثبت کنید. نتیجه این مقاله حاصل آزمایش اجراشده نیست؛ اینها برنامه پیشنهادی آزمایشاند.
آزمون روی شبیهساز کافی نیست
شبیهساز برای توسعه روزمره ارزشمند است، اما همه رفتارهای دستگاه را نشان نمیدهد. کیبورد، حافظه محدود، سرعت ذخیرهسازی و بازگشت از پسزمینه میتوانند روی گوشی واقعی تفاوت داشته باشند. حداقل یک دستگاه نماینده هر پلتفرم هدف لازم است و برای محصولی با کاربران متنوع، دامنه آزمون باید گستردهتر شود.
اپ یادداشت باید بتواند با بستهشدن فرایند هم دادهاش را حفظ کند. نگهداشتن متن فقط در وضعیت صفحه، ذخیره پایدار نیست. این مسئولیت حتی در انتخاب بومی هم خودبهخود حل نمیشود. راهنمای معماری اندروید بر جداکردن داده از اجزای کوتاهعمر رابط تأکید میکند؛ در چارچوب دیگر نیز باید همین مسئولیت را آگاهانه طراحی کنیم.
هزینه تغییر مسیر را کم کنیم
ممکن است پس از چند ماه معلوم شود بخشی از محصول به قابلیت بومی بیشتری نیاز دارد. برای چنین تغییری لازم نیست از روز اول همهچیز را پشت دهها رابط انتزاعی پنهان کنیم. کافی است قواعد داده و قرارداد سرور را بیدلیل به جزئیات صفحه گره نزنیم و استفاده از قابلیتهای دستگاه را در مرزهای قابل تشخیص نگه داریم.
یک نشانه خوب این است که بتوان قواعد اصلی یادداشت را بدون بالا آمدن کل رابط آزمود. نشانه دیگر، روشنبودن مالکیت ذخیرهسازی است: هر صفحه نباید به شیوه دلخواه خودش داده را ذخیره کند. این انتخابها از دعوای نام چارچوب مهمترند، چون روی هر دو مسیر توسعه اثر دارند.
تصمیم را با شرط بازبینی ثبت کنیم
سند تصمیم میتواند یک صفحه باشد: محصول و پلتفرمهای هدف، محدودیت تیم، گزینههای بررسیشده، شواهد نمونه و دلیل انتخاب. در پایان بنویسید چه چیزی باعث بازبینی میشود؛ مثلاً اضافهشدن ویرایشگر قلم، نیاز جدی به اجرای پسزمینه یا تغییر دامنه پشتیبانی. این شرطها به معنی بیاعتباری تصمیم امروز نیستند؛ محدوده اعتبار آن را روشن میکنند.
برای تمرین، اپ یادداشت را با دو فرض متفاوت بررسی کنید: در حالت اول فقط اندروید لازم است و تیم Kotlin میداند؛ در حالت دوم هر دو سیستمعامل لازماند و تیم تجربه React دارد. برای هر حالت، سه ریسک و یک آزمایش بنویسید. بخش بعد درباره ساخت اولین صفحه است: اینکه چطور نمایش، منطق و داده را از همان قابلیت کوچک بهدرستی جدا کنیم.
مراجع فنی
- معماری Flutter؛ سازوکار چارچوب و ارتباط با خدمات پلتفرم.
- کد اختصاصی پلتفرم در React Native؛ حدود اشتراک کد و تفکیک رفتارها.
- راهنمای معماری اپ اندروید؛ مسئولیت داده و چرخه عمر رابط.
