شما اینجا هستید: خانه / مقالات آموزشی / آشنایی با مفاهیم Domain-Driven Design – بخش سوم

آشنایی با مفاهیم Domain-Driven Design – بخش سوم

این مطلب سومین بخش از سری مقالات آموزشی 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 :

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

Supporting و یا Generic بودن یک Subdomain به معنای “بی اهمیت” بودن آن نیست. این Subdomain ها برای موفقیت Business مهم و الزامی هستند. اما تمرکز توسعه باید بر روی Core Domain و کیفیت آن باشد.

  • Bounded Context

Subdomain های موجود در فضای مساله (Problem Space)، در فضای راه حل (Solution Space) به Bounded Context تبدیل می شوند. در حالت ایده آل هر Subdomain در پیاده سازی به یک BC تبدیل می شود. هر BC یک واحد مستقل شناخته می شود و Domain Model مخصوص به خود را دارد. الگوهای طراحی و معماری در هر BC میتواند (بسته به ماهیت آن) متفاوت باشد. برای مثال ممکن است در پیاده سازی یک BC از معماری لایه ای معمول و در دیگری از الگوی CQRS استفاده کنیم :

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

الزامی در وجود دیتابیس متفاوت به ازای هر BC وجود ندارد، بلکه BC ها می توانند همه از یک دیتابیس استفاده نمایند. BC ها در پیاده سازی در قالب بخش های جدا و مستقل (برای مثال DLL های جدا در NET.) توسعه می یابند :

sepid-sale

 

  • Context Map

یک سیستم بزرگ می تواند BC های زیادی داشته باشد که این BC ها به شکل های مختلفی با هم در ارتباط هستند. Context Map مستندی است که روابط بین BC ها را مشخص می کند. Context Map به شما کمک می کند تا مرز های BC ها و نحوه ی تبادل و اشتراک داده بین آنها را به وضوح مشخص کنید. مثالی از یک Context Map و یکپارچه سازی فنی در آن :

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

 

نحوه ارتباط BC ها با یکدیگر

همانطور که در پاراگراف قبل مطرح شد، BC ها برای تکمیل فرآیند های Business باید با یکدیگر در ارتباط باشند. DDD تعدادی الگو و روش برای برقراری ارتباط بین BC ها و یکپارچه سازی آنها دارد که در این مقاله به طور مختصر به بررسی برخی از آنها میپردازیم.

  • Anti-Corruption Layer (به اختصار ACL )

هنگام برقراری ارتباط Bounded Context ها با یکدیگر باید مطمئن شوید که مفاهیم یک Domain با دیگری درآمیخته نشود. به همین دلیل لایه ای جداگانه جهت برقراری ارتباط بین دو BC ایجاد می شود تا از بهم ریختگی مدل جلوگیری شود. لازم به ذکر است که این لایه تنها مسئول ترجمه کردن مفاهیم و مدل بین دو BC است و شامل هیچ فرآیندی از Business نمی باشد. ساختار یک ACL :

تصویر از کتاب Domain-Driven Design نوشته Eric Evans

تصویر از کتاب Domain-Driven Design نوشته Eric Evans

 

  • Shared Kernel

هنگامی که دو تیم توسعه بر روی دو BC مختلف کار میکنند که از نظر منطق و فرآیندهای Domain همگذری زیادی دارند، جداسازی کار این دو تیم و نوشتن لایه های ارتباطی (مانند ACL) برای ترجمه ی مفاهیم بین این دو میتواند هزینه ی زیادی را در بر داشته باشد. در مواقع این چنینی بهترین کار به اشتراک گذاشتن قسمتی از مدل جهت آسان کردن فرآیند یکپارچه سازی و ارتباط بین دو BC است. این روش اغلب زمانی به کار می آید که یک Subdomain در قالب چند Bounded Context پیاده سازی می شود.

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

باید توجه داشت هنگام استفاده از این روش، تغییرات نمی توانند آزادانه بر روی مدل مشترک اعمال شوند. زیرا هر تغییری ممکن است باعث به وجود آمدن مشکل در BC تیم دیگر شود. به همان دلیل تغییرات پس از مشاوره و پاس شدن تست های هر دو تیم در مدل مشترک اعمال می شوند.

  • Open Host Service

هنگامی که تعداد روابط یک BC با بقیه زیاد باشد و هر کدام از این روابط نیازمند نوشتن یک لایه ی جدا برای برقراری ارتباط باشد، میتوان یک دسته از سرویس های مشخص را تولید و در اختیار بقیه ی BC ها قرار داد. این سرویس ها می توانند در قالب سرویس های SOAP و یا سرویس های RESTful باشند :

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

 

  • Publish-Subscribe

در این روش BC ها با ارسال Event به دیگران، آنها را از رخداد یک اتفاق در مدل خود آگاه میکنند. دیگران نیز با توجه به Event ارسال شده، تصمیمی اتخاذ کرده و فرآیندی را اجرا می کنند. باید توجه داشت ارسال کننده ی Event از وجود Subscriber ها و فرآیند های آنها اطلاعی ندارد. این روش ارتباط شما را قادر می سازد تا سیستم های مستقل از هم و در عین حال مرتبط با هم طراحی کنید. این مزیت باعث شده است که Domain Event ها تبدیل به یکی از اجزاء اصلی مدل شوند. استفاده از این الگو نیازمند پیاده سازی زیر ساختی جهت ارسال Event ها و همچنین Subscribe کردن به آنها است.

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

تصویر از کتاب Practicing Domain-Driven Design نوشته Scott Millett

درباره هادی احمدی

هادی احمدی
برنامه نویس، تحلیلگر و طراح نرم افزار که به فعالیت بر روی بسترهای نرم افزاری مایکروسافت مشغول هستم. علاقه مند به مباحث طراحی و معماری نرم افزار و همچنین پیاده سازی سیستم های اطلاعاتی پیچیده می باشم.

10 نظر

  1. سلام
    فوق العاده روان و مهندسی
    ممنونم ازت مهندس.

  2. نیما حمیدان

    جناب احمدی سلام
    ۱٫ توضیحات شما در بخش زیر دامنه ها و در ارتباط با نحوه جداسازی جنریک دامین ها از ساپورتینگ دامین ها شفاف نمی باشد لطفا در صورت امکان و چنانچه برایتان مقدور هست توضیح دهید که نحوه تشخیص و تفکیک ساپورتینگ دامین ها از جنریک دامین ها بر اساس چه المان ها و پارمتر هایی می باشد
    ۲٫ چنانچه امکان دارد در بخش ارتباط 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 ها می باشد.

  3. نیما حمیدان

    جناب احمدی فکر می کنید قسمت بعدی از آموزش که از سمت شما منتشر می شود؟

    • هادی احمدی

      مطلب بعدی در مورد DDD اواسط هفته ی بعد منتشر خواهد شد و در حوزه ی معماری و لایه بندی با توجه به رویکرد DDD می باشد.

  4. با تشکر از مطالب کاربردیتون در مورد DDD. میخواستم ببینم امکانش هست نمونه پروژه ای هم از DDD در ساییتون قرار بدین و با این نمونه مطالبتون رو ادامه بدین؟

    • هادی احمدی

      سلام، خواهش میکنم
      مطالب فعلی سری آموزش مفاهیم DDD هستند. به همین دلیل سعی میکنم بیشتر از پرداختن به جزئیات پیاده سازی، به بررسی خود مفاهیم بپردازم. به نظرم برای کسی که با مفاهیم آشنایی ندارد، توضیح از روی یک پروژه ی عملیاتی که جزئیاتی زیادی در پیاده سازی آن لحاظ شده، مفید نخواهد بود. بعد از بررسی مفاهیم به سراغ پیاده سازی یک پروژه ی عملیاتی میروم. سورس رو هم روی Github میذارم تا دوستان بتونند همیشه اخرین تغییرات رو دانلود کنند.

  5. با عرض سلام ، با توجه به این که بیشتر تیم های نرم افزاری تو ایران با EF دارن کار می کنن، به نظرتون پیاده سازی مفاهیم DDD رو EF امکان پذیر هست؟ ممنون می شم اگه پروژه یا نمونه مثالی کامل در این زمینه (DDD in EF )معرفی کنید.
    با تشکر

    • هادی احمدی

      سلام محمد جان

      امکان پذیر هست اما نهایتا ممکن هست از بعضی موارد چشم پوشی کنید (مثل Encapsulation کامل و …) و یا به شکل نه چندان استانداردی اون ها رو پیاده کنید. میتونید مقاله ی زیر از آقای Vernon رو مطالعه بکنید :

      https://vaughnvernon.co/?p=879

نظر بدهید

آدرس ایمیلتان منتشر نمیشودگزینه های الزامی ستاره دار شده اند *

*

شما می‌توانید از این دستورات HTML استفاده کنید: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

رفتن به بالا