اپیزود دو - به دنبال یک راه حل

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

اما مساله زمانی وخیم می شود که ساختار و معماری پروژه به سختی امکان ایجاد تغییرات اساسی را در پروژه را میدهد و معمولا توسعه دهنده ها مجبور می‌شوند مشکلات را به‌ صورت سطحی و بدون اینکه تغییر اساسی در طراحی کلی سیستم داشته باشند حل می کنند که این موضوع یکی دلایل اصلی افزایش پیچیدگی در یک سیستم نرم افزاری است!

الگوی (BFF (Backends for Front Ends یک رویکرد معماری نرم افزار است که می‌تواند این دست چالش ها را مدیریت کند!

اما این الگو برای تمام شرایط بهترین انتخاب است! توی این اپیزود بررسی می‌کنم :

۱ - الگوی نرم افزاری BFF چطور به بهبود و نگهداری بهتر سیستم کمک می‌کند!

۲- این الگو چه چالش‌هایی دارد ؟

۳- در چه شرایطی گزینه‌ی مناسبی برای یک پروژه نرم افزاری نیست!


متن اپیزود :

شرکت SoundCloud در سال ۲۰۱۲ با رشد فزاینده‌ی استفاده از اسمارت‌فون‌ها و اپلیکیشن‌های هوشمند، با چالشی در بخش بک‌اند پروژه مواجه شد. در آن زمان، تمام درخواست‌ها از طریق یک API واحد مدیریت می‌شد؛ به این معنا که هم اپلیکیشن‌ها و هم APIهای مربوط به third-party باید از همان API استفاده می‌کردند. اما از آن‌جا که نیازهای اپلیکیشن موبایل با نیازهای دیگر سرویس‌ها—مانند public API—متفاوت بود، وجود یک API مشترک، توسعه و نگهداری سیستم را پیچیده‌تر می‌کرد.

از سوی دیگر، با رشد پروژه و افزایش تعداد کاربران، نگهداری و ارتقای بخش‌های مختلف سیستم دیگر نه از نظر فنی و نه از نظر مقیاس‌پذیری پاسخ‌گو نبود. به همین دلیل، SoundCloud تصمیم گرفت معماری نرم‌افزار خود را از مدل مونولیتیک به معماری میکروسرویس تغییر دهد.

اما این تغییر، چالش جدیدی ایجاد کرد: حالا اپلیکیشن‌ها باید با چندین سرویس مستقل ارتباط برقرار می‌کردند، که این خود منجر به افزایش پیچیدگی شد. SoundCloud به دنبال راهی بود تا این ارتباطات را ساده کند، نیازهای متنوع کلاینت‌هایی چون اپلیکیشن‌های Android، iOS و وب را پوشش دهد، و مهم‌تر از همه، پیچیدگی سیستم را کاهش دهد.

در همین نقطه بود که ایده‌ی یک الگوی نرم‌افزاری به نام Backends for Front Ends (BFF) شکل گرفت.

سلام، من محمدم و این دومین اپیزود پادکست «کدشناسی» است. در این اپیزود می‌خواهم درباره‌ی بررسی یک راه‌حل یا الگوی معماری نرم‌افزار به نام Backends for Front Ends یا BFF صحبت کنم.

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

مشکل زمانی جدی‌تر می‌شود که ساختار و پیاده‌سازی پروژه، امکان تغییرات اساسی را نمی‌دهد. معمولاً توسعه‌دهندگان مجبور می‌شوند مشکلات را به‌صورت سطحی، بدون ایجاد تغییرات بنیادی در طراحی کلی سیستم، حل کنند؛ موضوعی که یکی از دلایل اصلی افزایش پیچیدگی سیستم‌های نرم‌افزاری است.

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

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

اما این پایان ماجرا نبود. سرویس جدید باید بر اساس یک‌سری قابلیت‌های خاص—مانند موقعیت جغرافیایی، تعامل با چند سرویس third-party دیگر، و نیز ارتباط با سرویس لگسی—هر صفحه را تولید می‌کرد.

در اینجا بود که ایده‌ی پیاده‌سازی یک لایه‌ی BFF مطرح شد. ما با انتخاب BFF قصد داشتیم چند مشکل را حل کنیم:

  • اول اینکه باید برای نسخه‌ی وب، یک API سفارشی‌سازی‌شده ایجاد می‌کردیم. این قابلیت، امکان بهبود عملکرد رندرینگ سمت سرور را فراهم می‌کرد.

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

همچنین داشتن یک سرویس مجزا برای هر پلتفرم این مزیت را داشت که تغییرات بر اساس نیازهای جدید خیلی سریع‌تر اعمال شوند؛ بدون اینکه نیاز باشد چندین سرویس دیگر را درگیر کرد.

و از همه مهم‌تر، الگوی BFF به‌عنوان یک لایه می‌تواند کارهای زیادی برای بهبود عملکرد انجام دهد، مانند کش‌کردن پاسخ‌ها، که تأخیر در زمان پاسخ‌گویی را به حداقل می‌رساند. این نوع مکانیزم‌ها به‌طور چشم‌گیری عملکرد سیستم را بهبود می‌بخشند.

آیا استفاده از یک معماری خاص، در همه جا مشکل را حل می‌کند؟

الگوی BFF با وجود مزایای فراوان، بدون چالش نیست:

  • اگر کلاینت‌هایی که قرار است از سرویس BFF استفاده کنند، نیازهای مشابهی داشته باشند و نیازی به سفارشی‌سازی خروجی در فرانت‌های مختلف نباشد، و همچنین قرار نباشد این سرویس پیچیدگی خاصی را کاهش دهد، استفاده از روش‌های ساده‌تری مثل GraphQL می‌تواند پاسخ‌گوی نیازها باشد.

  • در حالاتی که سیستم باید کمترین زمان تأخیر (Latency) را در پاسخ‌گویی داشته باشد—مانند برنامه‌های استریم ویدیو، بازی‌های آنلاین، یا سیستم‌هایی که پاسخ‌گویی لحظه‌ای اهمیت حیاتی دارد—اگر BFF بهینه‌سازی نشده باشد، می‌تواند خودش به یک گلوگاه تبدیل شود.

  • در نهایت، اضافه‌کردن یک لایه‌ی جدید (BFF) پیچیدگی‌های خاص خود را دارد. این لایه می‌تواند باعث افزایش نیازمندی‌ها به زمان، نیرو و زیرساخت شود، که برای پروژه‌های کوچک یا نسخه‌های MVP، به معنی افزایش هزینه خواهد بود.

واقعیت این است که پیاده‌سازی BFF برای ما آسان نبود، اما فکر می‌کنم تصمیم درستی بود. توانستیم سیستم را طوری تغییر دهیم که هم کارایی بهتری داشته باشد، هم نگهداری آن در آینده آسان‌تر شود. و از همه مهم‌تر، این تغییرات بدون آنکه کاربران متوجه شوند انجام شد—و به‌نظرم این از نشانه‌های یک راه‌حل خوب است.

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

کم‌کم به پایان این اپیزود رسیدیم. اگر سؤال، نظر یا تجربه‌ای در مورد این موضوع دارید، خوشحال می‌شوم با من به اشتراک بگذارید. تا اپیزود بعد، خداحافظ!