معماری مدرن و طراحی سیستم:
توسعه سیستمهای نرمافزاری همه از یک اپلیکیشن، چند API و یک دیتابیس ساده شروع میشود، با گذشت زمان، سیستم رشد میکند، کاربران بیشتر میشوند و قابلیت های جدید اضافه میشود و همینطور کم کم همه چیز پیچیده تر از قبل میشود. در این مرحله سیستم دیگر قابل مدیریت نیست. زمانی که تیمهای مختلف همزمان روی بخش های مختلف کار میکنند، سرویس ها زیاد شده و ارتباط میان آن ها به پیچیدگی میافزاید. اینجاست که هر تغییر کوچک میتواند روی بخش های دیگر اثر بگذارد.
در چنین شرایطی فقط نوشتن کد مطرح نیست، بلکه مسئله اصلی "مدیریت پیچیدگی" است. به همین دلیل در معماری نرمافزار، مفاهیم مختلفی شکل گرفته که هر یک تلاش میکند به نحوی این پیچیدگی را کنترل کند.
در ادامه چند مفهوم مهم در معماری نرمافزار را بررسی میکنیم که هرکدام پاسخی به یکی از این مشکلات در سیستمهای بزرگ هستند.
· Backend for Frontend (BFF):
در سیستم های مدرن کاربران از طریق پلتفرمهای مختلفی مثل وبسایت، اپلیکیشن موبایل یا پنل مدیریت به سیستم متصل میشوند و به عبارتی میتوان گفت: همه کاربران مثل هم نیستند و هر کدام از این Frontendها نیازهای متفاوتی دارند. اگر همه آنها مستقیما از یک Backend مشترک استفاده کنند به مرور سیستم پیچیده شده و مدیریت آن دشوار و دشوارتر. به همین دلیل مفهومی مثل Backend for Frontend یا به اختصار BFF مطرح میشود.
برای مثال در یک فروشگاه اینترنتی، اپلیکیشن موبایل به داده کمتر ولی پاسخ سریعتر نیاز دارد ولی در نسخه وب ممکن است اطلاعات کاملتر و جزئیات بیشتری نمایش دادهشود، اگر هردو از یک Backend استفاده کنند احتمالا داده های اضافی و غیرضروری دریافت میشود.
در این روش برای هر Frontend یک Backend اختصاصی طراحی میشود تا متناسب با نیاز همان بخش عمل کند. این کار باعث میشود هر پلتفرم دقیقا چیزی را دریافت کند که نیاز دارد، نه بیشتر و نه کمتر
· API Gateway & Service Mesh:
زمانی که سیستم بزرگ میشود و به چندین Microservice تقسیم میشود، یک چالش جدید ظاهر میشود: مدیریت ارتباط میان سرویسها. زمانی که سرویس زیادی وجود دارد مثل سرویس کاربران، سفارش، پرداخت و ارسال. اگر هر Frontend بخواهد مستقیم با این سرویسها ارتباط بگیرد هم امنیت دچار چالش شده هم مدیریت درخواست ها پیچیده میشود.
در چنین سیستمهاییAPI Gateway نقش یک درگاه مرکزی را خواهد داشت و تمام درخواست کاربران ابتدا به آن وارد شده و سپس Gateway تصمیم میگیرد هر درخواست باید به کدام سرویس ارسال شود.
فرض کنید در یک فروشگاه اینترنتی زمانی که کاربر وارد صفحه سفارش شده، اطلاعاتی از جمله اطلاعات کاربر، لیست کالاها، وضعیت موجودی، قیمت و تخفیف باید جمع آوری شوند. بدون API Gateway اپلیکیشن موبایل باید جداگانه با چندین سرویس مختلف درخواست ارسال کند اما با یک API Gateway فقط یک درخواست ارسال شده و API Gateway خودش با سرویس های مختلف در ارتباط است و نتیجه نهایی را برمیگرداند.
Kong ، NGINX ، Spring Cloud Gateway نمونه ابزار های معروف برای API Gateway هستند که استفاده از این ابزار ها باعث میشود مدیریت درخواست ها، امنیت و کنترل سرویس ها سادهتر انجام شود.
Service Mesh اما بیشتر برای مدیریت ارتباطات داخلی بین سرویس ها استفاده میشود. برای مثال اگر یکی از سرویس ها موقتا کار نکند Service Mesh میتواند درخواست را دوباره ارسال کند و یا درخواست را به نسخه سالم سرویس هدایت کند. یعنی به جای اینکه هر سرویس خودش کنترل ترافیک، امنیت، مانیتورینگ و... را پیادهسازی کند Service Mesh این کار را انجام میدهد. Istio و Linkerd دو نمونه ابزاری هستند که برای کنترل ارتباط داخلی میان سرویس ها میتوان از آنها استفاده کرد.
· API-first Approach
زمانی که در پروژه های نرمافزاری به ویژه در پروژه های بزرگ ، تیم ها قبل از طراحی API ها شروع به پیاده سازی سیستم میکنند پروژه با مشکلاتی همچون ناهماهنگی تیمها و تغییرات زیاد در API ها و دوباره کاری مواجه میشود.
در رویکرد API-first قبل از پیادهسازی بخش های مختلف سیستم، ابتدا API ها طراحی میشود. توسعه دهندگان از همان ابتدای کار Endpoint ها را تعیین میکنند، ورودی و خروجیها و اینکه داده ها با چه ساختاری بین بخشهای مختلف رد و بدل میشوند را مشخص میکنند.
برای مثال اگر در توسعه یک اپلیکیشن سفارش غذا ابتدا APIهای مربوط به ثبت سفارش، لیست رستوران ها یا پرداخت را طراحی شوند، تیمهای Backend و Frontend میتوانند به صورت همزمان توسعه را آغاز کنند، که باعث هماهنگی بهتر بین تیم ها شده و تغییرات ناگهانی در سیستم کم میشود، به طور خلاصه میتوان گفت توسعه نرمافزار منظم تر و سادهتر انجام میشود.
· Hexagonal Architecture
مشکلی که در بسیاری از سیستم ها دیده میشود این است که منطق اصلی برنامه به تکنولوژیهای بیرونی وابسته میشود. برای مثال تغییر دیتابیس یا فریمورک باعث میشود بخش های زیادی از سیستم نیاز به تغییر داشته باشند.
Hexagonal Architecture رویکردی است که تلاش میکند منطق اصلی برنامه(Business Logic) را از بخشهای خارجی جدا نگه دارد تا سیستم انعطافپذیرتر شود. در این معماری هسته اصلی برنامه فقط شامل منطق و قوانین اصلی سیستم است و ارتباط بخشهای خارجی از طریق بخش هایی به نام Port و Adapterها انجام میشود.
یک فروشگاه اینترنتی را در نظر داشته باشید که امروز از MySQL استفاده میکند اما در آینده شاید نیاز باشد Database آن به PostgreSQL تغییر کند. در معماری Hexagonal به دلیل جدابودن منطق اصلی از دیتابیس( و دیگر بخشها) این تغییر راحتتر انجام میشود. به طور خلاصه میتوان گفت این معماری باعث کاهش وابستگی بین بخشهای مختلف سیستم شده و تست و نگهداری نرمافزار را ساده تر میکند.

· Domain Driven Design(DDD)
مشکل دیگری که در بسیاری از پروژه های نرمافزاری دیده میشود، تمرکز صرفا روی کدنویسی و ساخت APIها است، نه روی درک مسئله واقعی کسب و کار
برای مثال در یک فروشگاه اینترنتی اینکه یک سفارش دقیقا چه مراحلی دارد، چه زمانی قابل لغو است، تخفیف ها چگونه اعمال میشوند یا سبد خرید باید دقیقا چه رفتاری داشته باشد... همه این ها جزو مسائل واقعی کسب وکار لحاظ میشوند.
Domain Driven Design یا DDD تلاش میکند این مشکل را حل کند. در این رویکرد خود مسئله واقعی بررسی و درک میشود بعد سیستم را بر اساس آن طراحی میکند. در روش DDD مفاهیم اصلی کسب و کار مثل سفارش، پرداخت، سبد خرید یا حتی خود کاربر به عنوان بخش اصلی سیستم لحاظ شده و مدلسازی میشوند.
یکی از نکات مهم در DDD استفاده از یک زبان مشترک بین تیم فنی و کسب وکار است تا همه یک مفهوم را با یک معنی واحد درک کنند. یعنی اگر گفته میشود "Order" همه یک برداشت واحد از آن داشته باشند.
در نهایت میتوان گفت همه این مفاهیم برای یک هدف مشترک پدید آمدند: کنترل پیچیدگی در سیستم های بزرگ. هر رویکرد از یک زاویه به مشکل نگاه میکند یکی روی نحوه ارتباط سرویسها تمرکز دارد، یکی روی طراحی APIها، دیگری روی ساختار داخلی سیستم و یکی دیگر روی درک بهتر مسئله واقعی