این مطلب سومین بخش از سری مقالات آموزشی Domain Driven Design می باشد. برای مطالعه ی بخش های قبل میتوانید از لینک های زیر استفاده نمایید :
پیش گفتار : مقدمه ای بر Domain-Driven Design
بخش اول : آشنایی با مفاهیم Entity، Value Object و Service
بخش دوم : آشنایی با مفاهیم Invariant، Aggregate و Aggregate Root
- پیش گفتار
مطالبی که در دو بخش قبل مطرح شد، عموما در رابطه با نحوه ی ساخت و ایجاد Domain Model و همچنین قوانین طراحی آن بود. در یک سیستم بزرگ و پیچیده پیاده سازی یک مدل برای پاسخگویی به تمام نیازها، در عمل امکان پذیر نمی باشد. شرکتی را در نظر بگیرید که قصد راه اندازی سیستم e-commerce آنلاین دارد. از جمله بخش هایی که برای این سیستم در نظر گرفته شده است، بخش مدیریت کالاها در انبار، نمایش کاتالوگ محصولات، مدیریت سفارشات خرید، مدیریت تراکنش های مالی و مدیریت ارسال و رساندن محصولات به دست مشتری می باشد. سیستم فوق از چند Subdomain (ترجمه فارسی : زیر دامنه) تشکیل شده است که هر کدام یک جنبه از سیستم کلی را تشکیل می دهند. هر Subdomain زبان و مفاهیم مخصوص به خود را دارد. برای مثال یک “کالا” در انبار ممکن است در واقعیت با یک “محصول” در سیستم فروش یکی باشد، اما هرکدام در سیستم خود تعریف جداگانه و رفتارهای جداگانه ای دارند. هر Subdomain (در حالت ایده آل) در قالب یک Bounded Context (به اختصار BC) پیاده سازی می شود.
- Subdomain
تقریبا Domain تمامی نرم افزارهای Enterprise از چندین Subdomain تشکیل شده است. شناخت Subdomain های سیستم شما را قادر می سازد تا Problem Space (در فارسی : فضای مساله) را به بخش های کوچک تر تقسیم کنید. بخش مشخصی از Domain که هدف اصلی توسعه ی سیستم و محصول اصلی می باشد با عنوان Core Domain شناخته می شود. تمرکز اصلی در رویکرد DDD بر توسعه ی Core Domain می باشد. Subdomain هایی نیز در سیستم هستند که وجود آنها الزامی است و بخشی از Business مخصوص به مشتری را پیاده سازی می کنند، اما بخشی از Core Domain نیستند. این Subdomain ها هدف اصلی ساخت سیستم نیستند اما به Core Domain در رسیدن به اهداف و کامل کردن سیستم کمک میکنند. Subdomain های فوق با نام Supporting Subdomains (به فارسی: زیر دامنه های حامی) شناخته می شوند. Subdomain هایی که هیچ پیاده سازی خاص منظوره ای از فرآیند های Business ندارند، اما وجود آن برای فعالیت سیستم الزامی است، با عنوان Generic Subdomains (به فارسی : زیردامنه های عمومی) شناخته می شوند.
مثالی از تحلیل Domain سیستم e-commerce :
Supporting و یا Generic بودن یک Subdomain به معنای “بی اهمیت” بودن آن نیست. این Subdomain ها برای موفقیت Business مهم و الزامی هستند. اما تمرکز توسعه باید بر روی Core Domain و کیفیت آن باشد.
- Bounded Context
Subdomain های موجود در فضای مساله (Problem Space)، در فضای راه حل (Solution Space) به Bounded Context تبدیل می شوند. در حالت ایده آل هر Subdomain در پیاده سازی به یک BC تبدیل می شود. هر BC یک واحد مستقل شناخته می شود و Domain Model مخصوص به خود را دارد. الگوهای طراحی و معماری در هر BC میتواند (بسته به ماهیت آن) متفاوت باشد. برای مثال ممکن است در پیاده سازی یک BC از معماری لایه ای معمول و در دیگری از الگوی CQRS استفاده کنیم :
الزامی در وجود دیتابیس متفاوت به ازای هر BC وجود ندارد، بلکه BC ها می توانند همه از یک دیتابیس استفاده نمایند. BC ها در پیاده سازی در قالب بخش های جدا و مستقل (برای مثال DLL های جدا در NET.) توسعه می یابند :
- Context Map
یک سیستم بزرگ می تواند BC های زیادی داشته باشد که این BC ها به شکل های مختلفی با هم در ارتباط هستند. Context Map مستندی است که روابط بین BC ها را مشخص می کند. Context Map به شما کمک می کند تا مرز های BC ها و نحوه ی تبادل و اشتراک داده بین آنها را به وضوح مشخص کنید. مثالی از یک Context Map و یکپارچه سازی فنی در آن :
نحوه ارتباط BC ها با یکدیگر
همانطور که در پاراگراف قبل مطرح شد، BC ها برای تکمیل فرآیند های Business باید با یکدیگر در ارتباط باشند. DDD تعدادی الگو و روش برای برقراری ارتباط بین BC ها و یکپارچه سازی آنها دارد که در این مقاله به طور مختصر به بررسی برخی از آنها میپردازیم.
- Anti-Corruption Layer (به اختصار ACL )
هنگام برقراری ارتباط Bounded Context ها با یکدیگر باید مطمئن شوید که مفاهیم یک Domain با دیگری درآمیخته نشود. به همین دلیل لایه ای جداگانه جهت برقراری ارتباط بین دو BC ایجاد می شود تا از بهم ریختگی مدل جلوگیری شود. لازم به ذکر است که این لایه تنها مسئول ترجمه کردن مفاهیم و مدل بین دو BC است و شامل هیچ فرآیندی از Business نمی باشد. ساختار یک ACL :
- Shared Kernel
هنگامی که دو تیم توسعه بر روی دو BC مختلف کار میکنند که از نظر منطق و فرآیندهای Domain همگذری زیادی دارند، جداسازی کار این دو تیم و نوشتن لایه های ارتباطی (مانند ACL) برای ترجمه ی مفاهیم بین این دو میتواند هزینه ی زیادی را در بر داشته باشد. در مواقع این چنینی بهترین کار به اشتراک گذاشتن قسمتی از مدل جهت آسان کردن فرآیند یکپارچه سازی و ارتباط بین دو BC است. این روش اغلب زمانی به کار می آید که یک Subdomain در قالب چند Bounded Context پیاده سازی می شود.
باید توجه داشت هنگام استفاده از این روش، تغییرات نمی توانند آزادانه بر روی مدل مشترک اعمال شوند. زیرا هر تغییری ممکن است باعث به وجود آمدن مشکل در BC تیم دیگر شود. به همان دلیل تغییرات پس از مشاوره و پاس شدن تست های هر دو تیم در مدل مشترک اعمال می شوند.
- Open Host Service
هنگامی که تعداد روابط یک BC با بقیه زیاد باشد و هر کدام از این روابط نیازمند نوشتن یک لایه ی جدا برای برقراری ارتباط باشد، میتوان یک دسته از سرویس های مشخص را تولید و در اختیار بقیه ی BC ها قرار داد. این سرویس ها می توانند در قالب سرویس های SOAP و یا سرویس های RESTful باشند :
- Publish-Subscribe
در این روش BC ها با ارسال Event به دیگران، آنها را از رخداد یک اتفاق در مدل خود آگاه میکنند. دیگران نیز با توجه به Event ارسال شده، تصمیمی اتخاذ کرده و فرآیندی را اجرا می کنند. باید توجه داشت ارسال کننده ی Event از وجود Subscriber ها و فرآیند های آنها اطلاعی ندارد. این روش ارتباط شما را قادر می سازد تا سیستم های مستقل از هم و در عین حال مرتبط با هم طراحی کنید. این مزیت باعث شده است که Domain Event ها تبدیل به یکی از اجزاء اصلی مدل شوند. استفاده از این الگو نیازمند پیاده سازی زیر ساختی جهت ارسال Event ها و همچنین Subscribe کردن به آنها است.
سلام
فوق العاده روان و مهندسی
ممنونم ازت مهندس.
خواهش میکنم مصطفی جان
جناب احمدی سلام
۱٫ توضیحات شما در بخش زیر دامنه ها و در ارتباط با نحوه جداسازی جنریک دامین ها از ساپورتینگ دامین ها شفاف نمی باشد لطفا در صورت امکان و چنانچه برایتان مقدور هست توضیح دهید که نحوه تشخیص و تفکیک ساپورتینگ دامین ها از جنریک دامین ها بر اساس چه المان ها و پارمتر هایی می باشد
۲٫ چنانچه امکان دارد در بخش ارتباط BC ها با یکدیگر قسمت Anti-Corruption Layer را باز نموده و توضیحات شفاف تری در این زمینه جهت روشن شدن نحوه استفاده از این لایه بیان نمایید .
ممنون
سلام
۱٫ برای تفکیک Supporting Subdomain ها از Generic Subdomain ها باید به نقش آنها در Business دقت کنید. Supporting Subdomain ها جنبه و بخشی از Business مشتری را پیاده ساز ی میکنند که مخصوص به خود اوست و نیازهای مخصوص به خود را در آن قسمت دارد. اما این Business جزئی از Core Domain نبوده و هدف اصلی توسعه ی سیستم نیست. اما Generic Subdomain ها در پیاده سازی Business مخصوص به مشتری سهمی ندارند و یک سیستم کلی و General نیز می تواند جوابگوی نیازهای وی باشد. دومین های Supporting و Generic می توانند به صورت پکیج خریداری و یا به تیم های بیرونی جهت پیاده سازی واگذار شوند.
باید توجه داشته باشید که شناخت Subdomain ها کاملا به فضای مساله بستگی دارد. یک Supporting Subdomain یا Generic Subdomain می تواند در سیستم دیگری به عنوان Core Domain شناخته شود.
۲٫ آشنایی کامل با نحوه ی کار کردن با ACL ها جهت ارتباط بین BC ها نیازمند پیاده سازی سیستم به صورت عملی و در قالب کد می باشد. که در مقاله های بعدی به جزئیات به آنها می پردازم. این مقاله صرفا جهت آشنایی خواننده با روش های ارتباطی بین BC ها می باشد.
جناب احمدی فکر می کنید قسمت بعدی از آموزش که از سمت شما منتشر می شود؟
مطلب بعدی در مورد DDD اواسط هفته ی بعد منتشر خواهد شد و در حوزه ی معماری و لایه بندی با توجه به رویکرد DDD می باشد.
با تشکر از مطالب کاربردیتون در مورد DDD. میخواستم ببینم امکانش هست نمونه پروژه ای هم از DDD در ساییتون قرار بدین و با این نمونه مطالبتون رو ادامه بدین؟
سلام، خواهش میکنم
مطالب فعلی سری آموزش مفاهیم DDD هستند. به همین دلیل سعی میکنم بیشتر از پرداختن به جزئیات پیاده سازی، به بررسی خود مفاهیم بپردازم. به نظرم برای کسی که با مفاهیم آشنایی ندارد، توضیح از روی یک پروژه ی عملیاتی که جزئیاتی زیادی در پیاده سازی آن لحاظ شده، مفید نخواهد بود. بعد از بررسی مفاهیم به سراغ پیاده سازی یک پروژه ی عملیاتی میروم. سورس رو هم روی Github میذارم تا دوستان بتونند همیشه اخرین تغییرات رو دانلود کنند.
با عرض سلام ، با توجه به این که بیشتر تیم های نرم افزاری تو ایران با EF دارن کار می کنن، به نظرتون پیاده سازی مفاهیم DDD رو EF امکان پذیر هست؟ ممنون می شم اگه پروژه یا نمونه مثالی کامل در این زمینه (DDD in EF )معرفی کنید.
با تشکر
سلام محمد جان
امکان پذیر هست اما نهایتا ممکن هست از بعضی موارد چشم پوشی کنید (مثل Encapsulation کامل و …) و یا به شکل نه چندان استانداردی اون ها رو پیاده کنید. میتونید مقاله ی زیر از آقای Vernon رو مطالعه بکنید :
https://vaughnvernon.co/?p=879