Modular Monolith چیست؟
یک اپلیکیشن Monolith که در یک فرایند و یک دیپلوی واحد اجرا میشود، اما داخلش به ماژولهای مستقل با مرز مشخص تقسیم شده است.
چرا مهم است؟
بیشتر مزیت مرزبندی تمیز Microservices (کد قابل نگهداری، جلوگیری از وابستگی درهمتنیده) را میدهد، بدون هزینههای عملیاتی سیستمهای توزیعشده — دیپلوی، Debug و تست همچنان سادهاند.
ایده اصلی
برنامه در یک Solution/فرایند واحد دیپلوی میشود، اما هر ماژول کسبوکاری (مثل Orders، Payments، Notifications) یک مرز مشخص با یک Public API (Interface/Contract) دارد؛ ماژولهای دیگر فقط از طریق همان مرز به آن دسترسی دارند، نه به جزئیات داخلیاش.
مثال ساختار
src/
Modules/
Orders/ (Public: IOrderService — بقیه فقط همین را میبینند)
Payments/
Notifications/
Host/ (پروژه اجراییِ واحد که همه ماژولها را در خودش دارد)
نکات مهم
- ارتباط بین ماژولها معمولاً از طریق Interface یا رویداد داخلفرایندی انجام میشود، نه دسترسی مستقیم به کلاسهای داخلی ماژول دیگر.
- چون همه ماژولها در یک فراینداند، اگر مرزها بعداً نیاز شد، مهاجرت هرکدام به یک Microservice جدا با کمترین تغییر ممکن است.
- معمولاً هر ماژول دیتابیس/Schema مستقل خودش را دارد (یا حداقل جدولهای مجزا)، حتی اگر روی یک سرور دیتابیس مشترک باشند.
اشتباه رایج
❌ عدم رعایت مرز ماژولها — مثلاً یک کلاس در ماژول Notifications مستقیماً به Entity داخلی ماژول Orders رفرنس بگیرد. این کار بهمرور همه ماژولها را به هم قفل میکند و پروژه به یک «Big Ball of Mud» تبدیل میشود که دیگر نه مزیت Monolith ساده را دارد و نه مزیت مرزبندی Microservices را.
خلاصه
Modular Monolith اپلیکیشن را در یک فرایند و دیپلوی واحد نگه میدارد اما داخلش به ماژولهای مستقل با مرز و Public API مشخص تقسیم میکند. این حالت میانه، بیشتر مزیت مرزبندی تمیز Microservices را بدون هزینههای عملیاتی سیستم توزیعشده میدهد. رعایتنکردن مرز ماژولها پروژه را به یک Big Ball of Mud تبدیل میکند.
