سلام دوستان - تو این مقاله نسبتا طولانی قراره یکم راجع به معماری Domain Event صحبت کنیم
اینکه چی هست - کجا به کارمون میاد - چه ارتباطی با DDD و Event Sourcing داره - چطور پیاده سازیش کنیم اصلا ! و چه چالش هایی رو واسمون حل میکنه
DDDچیست ؟
معماری Domain Driven Design یک معماری بسیار مستحکم و قدرمند نرم افزاری می باشد که برای پروژه هایی با پیچیدگی های فراوان طراحی شده است. در این معماری پایین ترین لایه دیتابیس یا داده نمی باشد. بلکه پایین ترین لایه منطق های اصلی پروژه می باشد.
به عنوان مثال فرض کنید قرار است یک بازی شطرنج را پیاده سازی کنید. در این بازی هر مهره چندین حرکت می تواند انجام دهد و از قواعد خاصی نیز پیروی می شود. ترکیب حرکت مهره ها میلیون ها حرکت را به وجود می آورد. قطعا پیاده سازی میلیون ها حرکت تست کد غیر ممکن است. بنابراین در اینجا بایستی هر مهره را به عنوان یک Value Object تعریف کرد و رفتار آن را مشخص کرد.
مثال دیگری که می توان برای استفاده از معماری DDD گفت پیاده سازی سیستم های پیش بینی آب و هوا می باشد. در این سیستم ها برای پیش بینی هوا هزاران عامل وجود دارد که هر عامل میتواند بر عامل یا عوامل دیگر تاثیر گذار باشد. بنابراین برای پیاده سازی چنین سیستم هایی معمولا از معماری DDD استفاده می شود. 1
مشکل:
بزارید اول مشکل رو بگم و بعد بریم سراغ مابقی ماجرا :
فرض کنید شما یک سامانه فروشگاه آنلاین دارید که از میکروسرویس های مختلفی تشکیل شده
یکی از این میکروسرویس ها مسئول مدیریت سفارشات هست و یکی دیگه مسئول مدیریت انبار-
حالا فرض میگیریم کاربر سفارش جدیدی ثبت میشه تو حالت عادی
حال فرض کنیم تمامی موارد بالا با استفاده از درخواست های همزمان (synchorouns )بخواد انجام بشه - تو این حالت باید با استفاده از Api های Restfull یا GRPC درخواست مستقیم به سایر میکروسرویس ها بزنیم و منتظر پاسخشون بمونیم
این کار یکسری مشکل داره
میکروسرویس سفارشات باید دقیقا بدونه با چه API های دیگه ای ارتباط برقرار کنه و میکروسرویس چه پارامتر هایی ارسال و چه پاسخ هایی دریافت کند این باعث محدود شدن مواردی مثل flexibilty - scabilty - maintaibilty میشه
میکروسرویس سفارشات وابسته به درست کار کردن مابقی میکروسرویس هاست و اگر یک میکروسرویس خطا داشته باشد یا قطع شود عملیات سفارش ناتموم و معلوم نیست چه اتفاقاتی دقیقا رخ داده این اتفاق باعث inconsistency و دشواری rollback در صورت خطای سامانه میشود
میکروسرویس سفارشات باید منتظر پاسخ سایر میکروسرویس ها باشه تا عملیات تکمیل بشه این کار باعث کندشدن پاسخگویی به درخواست های کاربر و ضعف تجربه کاربری هست
1- میکروسرویس سفارشات پس از ثبت سفارش یک رویداد دامنه تولید(OrderStartedDomainEvent) و منتشر میکند
2- میکروسرویس خریداران با استفاده از یک Domain Event Handler ( تو فصل طراحی توضیح میدم) عضو میشوند و پس از دریافت خودکار این رویداد چک میکنند عملیات ثبت سفارش موفق بوده یا خیر
3- میکروسرویس انبار هم با استفاده از یک Domain Event Handler به اسم updateStockWhenOrderStartedDomain() به این ایونت هندلر عضو میشوند و پس از دریافت آن خودکار موجودی کالا را کاهش میدن
4- همینطور میکروسرویس فاکتور و همین اتفاقات - دریافت رویداد - ایجاد فاکتور و ارسال ...
عملکرد بالا : میکروسرویس سفارشات نیازی ندارد که منتظر پاسخ سایر میکروسرویس ها باشد تا عملیات را تکمیل کند هر میکروسرویس بصورت غیرهمزمان (asynchoronus ) و مستقل Domain Event های خود را پردازش میکند - این باعث افزایش سرعت پاسخگویی به درخواست های کاربران و بهبود تجربه کاربری میشود
خطای پایین : میکروسرویس سفارشات وابسته به درست کار کردن میکروسرویس های دیگر نیست اگر یک میکروسرویس قطع یا خطا داشته باشد عملیات سفارش قطع نمیشود و تاثیری ندارد روی آن - این باعث کاهش ناسازگاری (inconsistency ) و اسانتر شدن عملیات رول بک میشود
خب Domain Event (رویداد دامنه )چیست ؟
طبق تعریف مایکروسافت رویداد چیزی هست که تو گذشته اتفاق افتاده و رویداد دامنه اتفاقی هست که تو یک دامنه افتاده و میخوایم سایر بخش های در حال پردازش همون دامنه بهش اطلاع بدیم !
دامنه : "حوزه دانش یا فعالیت". با کمی عمیق شدن، دامنه در حوزه مهندسی نرم افزار معمولاً به موضوع و هدفی که برنامه ی نرم افزاری در آن اعمال می شود، اشاره دارد
طبق تعریف مارتین فولر بزرگ !
Captures the memory of something interesting which affects the domain
ما هرچیزی که فکر میکنیم با دامنه سروکار داره رو باید ثبت کنیم (مثال معروف GIGO)
- ماهیت یک رویداد دامنه هم همین هست که از آن برای ثبت مواردی استفاده میکنیم که باعث تغییر در وضعیت برنامهای که در حال توسعه آن هستیم بشود.
رویداد های دامنه رو نباید با integration Event ها اشتباه گرفت - integration Event ها زمانی استفاده میشوند که شما نیاز دارید یک رویداد رو بصورت غیرهمزمان و خارج از پردازش فعلیتون منتشر کنیدبرای مثال بین چندتا microservice , Bounded Context یا حتی برنامه های مختلف
ویژگی های Domain Event :
مزایا :
به زبون ساده تر فرض کنید یک سایت فروشگاهی داریم و هرکدوم از فعالیت هایی که مستقل از هم هستند رو میتونیم دامنه در نظر بگیریم - دامنه کاربران - دامنه سفارشات - دامنه خرید - دامنه ارسال و ..
شکل بالا بهتون نشون میده که چطوری میشه consistency رو بین چند مجموعه تو یک دامنه بدست آورد
هرزمان که سفارش جدید کاربر ثبت بشه مجموعه Order Aggregate یک رویداد OrderStarted رو منتشر میکنه و متناوبا میتونیم بقیه رویداد ها رو هم کنترل کنیم مثال اگر تعداد کالای درخواستی زیاد بود رویداد مجزا تولید کنیم
چه زمانی استفاده کنیم ؟
هر زمانی که سامانه ای که در حال پیاده سازیش هستید
تو قسمت های بعدی میریم برای پیاده سازی یک نمونه نسبتا ساده - به همراه تست و نتیجه !
سعی کردم خلاصه و قابل فهم باشه - اگر مشکل یا ایرادی بود عذرخواهی میکنم ازتون و قسمت های بعدی اصلاح میشه - لطفا نظرتون رو حتما بگید خوشحال میشم
منابع :