مقیاس پذیر ساختن توسعه موبایل | راهنمای کاربردی
مدت چندانی از زمانی که تعداد کاربران اپلیکیشنهای موبایل از تعداد کاربران وب بیشتر شد، نگذشته است. اکنون بسیاری از شرکتهای وب این واقعیت را درک کردهاند و شروع به پشتیبانی از اپلیکیشنها نمودهاند. اما سؤال مهم این است که بهترین تدبیر برای مقیاس پذیر ساختن توسعه موبایل چیست؟
بکاندهای خاص برای کلاینت موبایل
به طور سنتی بسیاری از شرکتها کار خود را به عنوان شرکتهای طراحی وب آغاز کردهاند. این شرکتها کسبوکارشان را رشد دادهاند و گروهی از توسعهدهندگان برای کارهای فرانتاند و بکاند استخدام کرده و آموزش دادهاند.
زمانی که اپلیکیشنها وارد بازار شدند، همانند هر حوزه تجاری دیگر، مدیریت شرکتهای طراحی وب نیز مراقب بودند که روی این موضوع بیش از حد سرمایهگذاری نکنند تا در صورت عدم رشد آتی متضرر نشوند. آنها کارهای این حوزه را یا به صورت پیمانکاری اجرا میکردند و یا افراد معدودی را به این منظور استخدام کردند. در آن زمان توسعه کلاینت موبایل یک پروژه جنبی محسوب میشد. از این رو کلاینتهای موبایل به طور عمده از بکاند وب برای سرویسهای خود استفاده میکردند.
چنان که میدانیم حوزه موبایل از وب متفاوت است و از این رو به طراحی و منطق متفاوتی نسبت به وب نیاز دارد. برای ایجاد این تفاوت، کلاینت موبایل باید منطق زیادی را پیادهسازی کند تا payload را پیش از استفاده از سرویس بکاند وب تبدیل کند.
با توجه به افراد معدودی که در حوزه کلاینت موبایل کار میکنند و همه این منطق اضافی که لازم است، کارها در حوزه موبایل به خوبی پیش نمیرفت. نکته دیگری که موجب افزودن پیچیدگی این مسئله غامض گشت، این بود که مجموعه مهارتهای دانشی برای وب و موبایل متفاوت بودند و از این رو امکان انتقال یک نفر از یکی از این تیمها به تیم دیگر وجود نداشت.
بکاند برای فرانتاند (BFF)
چنان که در بخش قبل توضیح دادیم، رفتهرفته توسعه اپلیکیشنها اهمیتی حیاتی یافته است و باید سرویسهای خاص بکاند وب را صرفاً برای کلاینتهای موبایل بسازیم.
این مدل چند مزیت به شرح زیر دارد:
- ما میتوانیم از توسعهدهندگان ماهر کنونی در حوزه بکاند وب برای کار روی بکاند موبایل استفاده کنیم.
- میتوانیم مقداری از منطق و تصمیمهای مورد نیاز در سمت کلاینت موبایل را به بکاند موبایل انتقال دهیم و کار لازم در سمت کلاینت موبایل را کاهش دهیم.
- در صورتی که کلاینت موبایل به طرز دقیقی تقسیمبندی و ساخته شده باشد، میتوانیم تغییرهای بخش کلاینت موبایل از طریق بکاند تأمین کنیم و دیگر نیازی به انتشار نسخه جدید وجود نخواهد داشت.
این مدل به نام «بکاند برای فرانتاند» (back end for front end) یا به اختصار BFF نامیده میشود.
قرار داد بین بکاند و کلاینت
روش دیگر برای تسریع توسعه این است که قرار داد مشترکی بین سرور و کلاینت داشته باشیم. در اغلب موارد در این زمینه از JSON استفاده میشود. با این حال JSON به عنوان یک رشته قابل سریالسازی باید در مدلی قرار گیرد که هم کلاینت و هم سرور آن را به صورت مستقل از هم پیادهسازی کنند.
برای کاهش سربار باید از یک مولد مدل مشترک مانند «آپاچی ثریفت» (Apache Thrift)، «بافرهای پروتکل» (Protocol Buffers) و غیره استفاده کنیم. مولدهای مدل به ما امکان میدهند که کدهای مدل را برای پلتفرمهای مختلف مانند جاوا اسکریپت سمت سرور، جاوای اندروید یا سوئیفت اپل تولید کرده و آنها را بین این پلتفرمها به اشترک گذاشته و منتقل کنیم.
بدین ترتیب کارکردهای زیر در اختیار ما قرار میگیرند:
- کاهش نیاز به تولید کدهای مدل مجزا برای پلتفرمهای مختلف
- کاهش ریسک خطای ناشی از تفاوتها در تفسیر مدل
- در صورتی که مدل با دقت تهیه شده باشد، میتوان مستقیماً آن را روی نمای کلاینت نگاشت کرد و بدین ترتیب دیگر نیازی به ترجمه مدل به نمای کلاینت نیز وجود ندارد.
همه این موارد موجب میشوند که توسعه اپلیکیشن موبایل در بلندمدت بسیار مقیاسپذیر باشد.
توسعه اپلیکیشن ماژولار
با این که داشتن یک سرویس خاص کلاینت موبایل کمک زیادی به ما میکند، اما از طرف دیگر باید زمان زیادی را نیز صرف توسعه در سمت کلاینت موبایل بکنیم، زیرا فیچرهای بیشتری عرضه میشوند، UI بیشتر تغییر مییابد و مواردی از این دست زیاد میشوند.
به طور سنتی اپلیکیشنهای موبایل تنها یک ماژول واحد دارند و هر کس روی آن کار کرده و مشارکت میکند. اما با اضافه شدن توسعهدهندگان بیشتر به تیم این مدل مقیاسپذیر نخواهد بود.
چنین مدلی موجب بروز مشکلات زیر میشود:
- تغییرهای متعارض موجب چالشبرانگیز شدن مرور کدها میشوند.
- زمان زیادی صرف خواندن کدهای افراد دیگر میشود، زیرا همه کدها در یک ماژول قرار دارند و ممکن است با هم مرتبط باشند.
- وجود یک معماری بالقوه بد موجب تخطی از قواعد کرانی میشود، چون هیچ کران قوی بین کدها وجود ندارد و هر کس میتواند به کد همه افراد دسترسی داشته باشد.
- زمان Build کردن افزایش مییابد، چون تغییرهایی که در ماژول اعمال میشود، باید دوباره روی یک ماژول حجیم کامپایل شود.
ماژولهسازی و تقسیم مسئولیت
توسعه اپلیکیشنها هم برای اندروید و هم iOS میتواند ماژولهسازی شود. در ادامه یک روش رایج برای افراز مسئولیت عرضه شده است که اپلیکیشن را به سه لایه تقسیم میکند.
نکته: مدل زیر از پروپوزال اصلی گوگل برای اپلیکیشنهای آنی (+) اخذ شده است.
- ماژول هماهنگکننده
- ماژولهای فیچر
- ماژول مبنا
نکته: اگر کنجکاو هستید که وابستگیها در اندروید چگونه متصل میشوند، میتوانید به این منبع (+) مراجعه کنید.
ماژول هماهنگکننده
این ماژول یک هماهنگکننده در سطح اپلیکیشن است. در این سطح، کار شامل هماهنگسازی گردش منطق در سطح اپلیکیشن در میان قابلیتهای مختلف است. این ماژول میتواند اینترفیس یا نمای (View) خاص خود یعنی اکتیویتی، فرگمان، ویوکنترلر و غیره را نیز داشته باشد.
این گروه میتواند مسئول کار یکپارچهسازی پیوسته (CI) نیز باشد. این احتمال وجود دارد که ابزار کلی را بهبود بخشید، همه ماژولهای دیگر را به همدیگر به صورت زنجیرهای گروهبندی کرد تا یک اپلیکیشن کامل ساخته شود و همچنین کل فرایند انتشار نیز به هم زنجیروار متصل شود.
اگر یک باگ یا مشکل وجود داشته باشد، این گروه ممکن است نخستین جایی باشد که بررسی میشود و به افراد ذیربط جهت بررسی ارجاع داده میشود. این گروه میتواند مسئول بررسی سلامت کلی اپلیکیشن از طریق نظارت بر نرخ کرش، عملکرد و غیره باشد.
ماژول مبنا
این ماژولی است که همه الگوهای معماری سازگار مورد نیاز را برای رعایت از سوی هر گروه تعریف میکند. این ماژول شامل موارد زیر است:
- اینترفیس/پروتکل مرتبط برای گروههای فیچر (Feature) جهت پیادهسازی و پیروی کردن. این ماژول میتواند یک ارجاع مبنا به آیتم مرتبط با طراحی مانند رنگ مشترک، نماها، متن و غیره داشته باشد.
- API مورد نیاز برای دسترسی به سیستمهای مختلف یا الزامات در سطح اپلیکیشن روی همه فیچرها مانند کلاینت شبکه، ریپازیتوری، آنالیتیک، احراز هویت و غیره قابل اعمال است.
- ابزارهای مشترک که هر گروه قابلیت نیاز خواهند داشت و استفاده میکنند شامل تابعهای اکستنشن مختلف، کلاسهای تست و غیره.
- اشتراک کتابخانههای خارجی مشترک که از سوی همه فیچرها مورد استفاده قرار میگیرند.
- این گروه مسئول ارتباط و آموزش همه گروههای فیچر در رابطه با مواردی است که باید از سوی گروه رعایت و اتخاذ شوند.
در نمودار فوق تنها یک ماژول مبنا نمایش یافته است. با این حال در صورت نیاز میتوانید آن را به چند ماژول مبنای دیگر با مجموعه مسئولیتهای مختلف افراز کنید.
ماژولهای فیچر
در نمودار فوق سه فیچر از یک ماژول تکلایه نمایش یافته است. این حالت را میتوان در صورت نیاز و بسته به مقیاس توسعه اپلیکیشن به فیچرهای بیشتر و چندلایه نیز افراز کرد. برخی افراد ممکن است از ماژولهای مبتنی بر فیچر استفاده کنند که تنها میتوانند بین برخی ماژولها به اشتراک گذاشته شوند.
هر گروه به طور کامل مسئول کد درون خودش است و در مورد گروه دیگر دغدغه کمتری وجود دارد. ضرورتی وجود ندارد که همه گروههای فیچر از الگوی توسعه یکسانی پیروی کنند، چون ممکن است هر گروه نیازهای متفاوتی داشته باشد علاوه بر آن استفاده از روشهای مختلف موجب ایجاد همافزایی مناسب و یادگیری بهتری در میان گروههای مختلف میشود. همه چیز باید استاندارد و منسجم بر اساس تعاریف در سطح مبنا باشد و همه اینترفیسها از آن پیروی کنند.
داشتن چنین تنظیماتی به گروهها امکان میدهد که در زمان کار روی ماژولها انعطاف داشته باشند و همچنین مجموعه قواعد الگوهایی از ماژول مبنا استنتاج شود که باید مورد پیروی قرار گیرد. یک چنین انعطافپذیری درون کرانهای تعریف شده، امکان مقیاسپذیری بهتری برای کار فراهم میسازد.
بدین ترتیب توسعهدهندگان میتوانند روی ماژولهای مختلف کار کنند. اما مالک ماژول باید تغییرهای صورت گرفته روی کد را مورد بازبینی قرار دهد. و اگر تغییرها روی ماژول مبنا صورت گرفته باشد، یک فرایند ارتباطی برای انتشار دانش در مورد چیزی که تغییر یافته و تأثیری که بر روی گروههای فیچر دیگر میگذارد مورد نیاز خواهد بود.
نکته: در زمان استفاده از ماژولهای تقسیم شده ممکن است وسوسه شویم که آنها را به کتابخانههایی تبدیل کنیم که از ریپازیتوریهای مختلف گیتهاب تولید میشوند. پیشنهاد ما این است که این کار انجام نشود، چون این کار موجب پیچیده شدن CI به دلیل کنترل نسخهبندی میشود. جمع کردن همه این موارد در یک ریپازیتوری گیتهاب که صرفاً بر مبنای ماژول افراز شده است به یکپارچگی بهتر و شناسایی سریعتر مشکلات و جهتگیریهای نادرست کمک میکند.