منظور از Domain Driven Design چیست؟منظور از Domain Driven Design چیست؟

منظور از Domain Driven Design چیست؟

نویسنده: الناز بکتاش

دسته بندی: توسعه نرم افزار
12 دقیقه زمان مطالعه
۱۴۰۰/۰۵/۲۷
0 نظر
امتیاز 4.4 از 5

مدتی است که تفکر Domain Driven Design در صنعت تولید نرم‌افزار به شدت مورد توجه قرار گرفته است. رویکردی که به اختصار DDD نامیده می‌شود. در این مقاله قصد دارم که در مورد تفکر و رویکرد DDD، آشنایی با مفاهیم Subdomain، Domain ، Bounded Context و Context Map صحبت کنم.

منظور از Domain Driven Design چیست؟

Domain Driven Design برای اولین بار در سال ۲۰۰۳ در کتابی به همین نام و توسط اریک ایوانز (Eric Evans) مطرح شد و توجه جامعه نرم‌افزاری را به خود جلب کرد. در اصل DDD یک نوع تفکر یا رویکردی برای تولید و توسعه نرم‌افزارهای بزرگ با فرآیندها و قوانین زیاد و پیچیده است که از مرحله تحلیل تا کدنویسی یک محصول همراه ما است و در دو قسمت استراتژیک و تکنیکال به ما ایده می‌دهد. البته اریک ایوانز در کتاب خود بیشتر به مفاهیم استراتژیک می‌پردازد و تمرکز اصلی را بر بیزینس اصلی نرم‌افزاری که می‌خواهیم بنویسیم می‌گذارد؛ یعنی Domain. در واقع کار DDD از یک خواسته یا مشکل بیزینسی (Problem Domain) شروع می‌شود.

او Domain را این گونه شرح می‌دهد: «محدوده‌ای که کاربر برای برنامه اعمال می‌کند.»

DDD برای محصولاتی که بیزینس پیچیده‌ای دارند، بسیار مفید است لذا استفاده از آن در پروژه‌های کوچک و ساده یا پروژه‌هایی که صرفا نیاز به ذخیره و خواندن اطلاعات دارند و بیزنس خاصی ندارند، ممکن است تنها زمان و هزینه پروژه را افزایش دهد و مزیتی خاصی هم به همراه نداشته باشد.

DDD روی تعامل سازنده و بهینه میان برنامه‌نویسان و افراد متخصص دامنه یا Business Experts تاکید دارد. به همین دلیل ایجاد یک زبان مشترک به نام Ubiquitous Language در مورد مفاهیم دامنه، امری الزامی است. این زبان مشترک هم در مستندات تحلیل و هم در کد، دیده می‌شود. در اصل یکی از قدرت‌های DDD استفاده از زبان مشترک است. برای مثال به دو تصویر زیر دقت کنید، تصویر اول یک سناریو برای ارسال و تحویل پیتزا و تصویر دوم پیاده‌سازی متد همین سناریو است. همان طور که می‌بینیم در هر دو تصویر سعی بر این است که از زبان مشترک استفاده شود. 

مستند سناریو تحویل پیتزا:

مستند سناریو تحویل پیتزا

پیاده‌سازی سناریو تحویل پیتزا:

پیاده‌سازی سناریو تحویل پیتزا

در واقع DDD همه چیز را می‌شکند و به بخش‌های کوچک‌تر تقسیم می‌کند تا برخورد با آن‌ها ساده‌تر باشد؛ مثل Knowledge Crunching (شکستن دانش) یا شکستن دامنه به چند SubDomain یا ارائه راهکارهایی برای تقسیم نرم‌افزار به بخش‌های جدا و مستقل از هم و تبیین ارتباط این بخش‌ها با یکدیگر.

این امر باعث می‌شود فرآیند توسعه نرم‌افزار به صورت موازی بین چند تیم انجام شود و همچنین معماران سیستم را قادر می‌سازد تا از معماری‌ها و تکنولوژی‌های مختلف در بخش‌های مختلف استفاده کنند. 

انواع Subdomain 

Subdomain ها به 2 دسته تقسیم می‌شوند:

  • دامنه اصلی (Core Domain)

محدوده اصلی دانش و مسئله را دامنه اصلی می‌نامند. بیشترین تلاش و هزینه هر شرکتی صرف دامنه اصلی می‌شود. بسیاری از شرکت‌ها نیروی‌های ماهر خود را به این بخش اختصاص می‌دهند و در اصل، Core Domain کلید موفقیت هر پروژه است. 

  • دامنه پشتیبان و دامنه عمومی (Supporting Domain و Generic Domain)

در طول یک پروژه ممکن است با بخش‌هایی مواجه شویم که اصل کسب و کار را تشکیل نمی‌دهند ولی وجودشان برای این که کار اصلی دامنه انجام شود، ضرورت دارد. ممکن است

حتی این بخش‌ها را از شرکت‌های دیگر خریداری کنیم؛ مثل ارسال ایمیل یا اس ام اس و ... . 

در واقع انتخاب  sub domain ها یک موضوع کاملا نسبی است، به تیم بستگی دارد و هیچ قاعده و قانون ثابتی ندارد.

مفهوم Bounded Context 

همان طور که اشاره کردیم، DDD همه چیز را می‌شکند. برای درک بهتر موضوع، به مکانیزم مغز انسان دقت کنید. وقتی مغز انسان با یک مسئله پیچیده روبه‌رو می‌شود، آن قدر مسئله را به بخش‌های کوچک تقسیم می‌کند تا راه حل آن قسمت‌های کوچکتر را در حافظه‌اش پیدا کند. بعد همه قسمت‌ها را با هم ادغام می‌کند تا به جواب مسئله اصلی برسد. به عنوان مثال جمع دو عدد 100 + 100 را در نظر بگیرید. حاصل این مقدار برای خیلی از انسان‌ها بدون استفاده از ماشین حساب بدیهی است چون به عنوان یک مسئله بدون پیچیدگی برای مغز ثبت شده است. حال حاصل جمع 1578 + 1376 را در نظر بگیرید. بسیاری از افراد این جمع را یک مسئله پیچیده می‌دانند و در نگاه اول نمی‌توانند به آن پاسخ دهند. در این حالت، مغز انسان برای حل این مسئله آن را به مسئله‌های کوچک‌تر خرد می‌کند و در نهایت با ادغام مسئله‌های کوچک، پاسخ را می‌یابد.

منظور از مسئله پیچیده چیست؟ در واقع هر چیزی که درک آن در حوزه مسئله (Problem Space) برای مغز سخت باشد، یک مسئله پیچیده است.

با توجه به تئوری پیچیدگی (Complexity Systems Theory) به سیستمی پیچیده می‌گویند که از اجزای زیادی تشکیل شده باشد و این اجزا به هم وابستگی داشته باشند.

به طور کل Sub Domain ها در فضای مسئله (Problem Space) وجود دارند. در فضای راه حل (Solution Space) یعنی زمانی که می‌خواهیم این Sub Domain ها را به کد تبدیل کنیم، تبدیل به Bounded Context می‌شوند.

تفکر DDD با استفاده از الگوهای استراتژیک و اصل خرد کردن، تلاش می‌کند که Domain پیچیده را به یک سری Sub Domain با پیچیدگی کمتر تبدیل و وابستگی بین آن‌ها را با شیوه‌ای صحیح، مدیریت کند. در حالت ایده‌آل، به ازای هر Sub Domain یک Bounded Context وجود دارد ولی ممکن است در عمل این گونه نباشد.

اریک ایوانز Bounded Context  را به غشای سلول بدن تشبیه کرده است. در اصل این مرز برای این وجود دارد که پیچیدگی‌های هر Sub Domain به بیرون از آن نشت نکند؛ همان طور که اگر غشای سلول از بین برود، دیگر سلولی وجود نخواهد داشت. او همچنین در کتاب خود مثال فرش کردن یک واحد ساختمان را مطرح می‌کند. اتاق‌ها و سالن این ساختمان همان SubDomain ها هستند و فرشی که برای آن‌ها استفاده می‌شود همان Bounded Context است. در این مثال، می‌توان برای هر اتاق یک فرش جداگانه در نظر گرفت (مورد ایده‌آل) یا از یک فرش برای دو اتاقی که رو‌به‌روی هم قرار گرفته‌اند، استفاده کرد (یک Bounded Context برای دو Sub Domain) و این کاملا به فضای Domain بستگی دارد.

یک موجودیت در BC های مختلف معناهای مختلفی می‌دهد و طبق این معنای متفاوت، رفتارها و خصیصه‌های متفاوتی را هم به همراه خواهد داشت. برای مثال یک شرکت را در نظر بگیرید که از یک بیمه خاص استفاده می‌کند. یک فرد د�� حوزه شرکت به عنوان کارمند شناخته می‌شود و ویژگی‌های خاص خود را دارد و همین فرد در حوزه شرکت بیمه به عنوان بیمه‌شده تلقی می‌شود و ویژگی‌های متفاوتی از حوزه شرکت را به همراه دارد.

هر BC معماری خاص خود را دارد؛ حتی می‌تواند دیتابیس مستقل داشته باشد و بسته به تصمیم شرکت، می‌توان توسعه و پابلیش هر BC را به عهده تیم‌های مختلف گذاشت. 

مفهوم Bounded Context

ارتباط بین Bounded Context ها

Bounded Context ها با روش‌های متفاوتی با هم در ارتباط هستند و از هم سرویس می‌گیرند. BC  سرویس‌دهنده به عنوان UpStream شناخته می‌شود و BC سرویس‌گیرنده‌ای که به رفتار یا دیتای UpStream وابسته است، به عنوان DownStream شناخته می‌شود. نوع ارتباط‌های بین BC ها به موارد مختلفی تقسیم می‌شود که در ادامه به چند مورد از آن‌ها اشاره می‌کنیم: 

Seprate Ways

در واقع این همان ایده دوری و دوستی است! یعنی گاهی اوقات به دلیل هزینه بالای ارتباط بین تیم‌ها یا همان Bounded context ها، شرکت تصمیم می‌گیرد که هر تیم راه خود را برود و روی هدف خود تمرکز کند.

Customer-Supplier

در این نوع ارتباط BC سرویس‌دهنده، به دنبال رفع نیازمندی‌های BC سرویس گیرنده است و به نوعی آن را مشتری خود می‌بیند. به همین دلیل، نیازمندی‌های BC سرویس‌گیرنده روی اولویت‌ها و برنامه‌ریزی‌های تیم سرویس‌دهنده تاثیر می‌گذارد.

Conformist

در این نوع ارتباط، نیازمندی‌های تیم سرویس‌گیرنده دغدغه‌ای برای تیم سرویس‌دهنده ایجاد نمی‌کند، در واقع تیم سرویس‌گیرنده باید خودش را با تیم سرویس‌دهنده وفق دهد.

Partnership

در این نوع ارتباط، همکاری زیادی بین تیم سرویس‌دهنده و سرویس‌گیرنده وجود دارد و تفاوت آن با ارتباط Customer-Supplier در این است که تیم سرویس‌دهنده و سرویس‌گیرنده روی BC هایی کار می‌کنند که به دنبال یک هدف مشترک هستند؛ در حدی که حتی گاهی اوقات پابلیش آن دو باید با هماهنگی هم صورت گیرد.

Anticorruption Layer

در واقع یک لایه مترجم سمت سرویس‌گیرنده است که از رخنه کردن مفاهیم و زبان BC سرویس‌دهنده به داخل BC خود جلوگیری می‌کند و در اصل، به عنوان نوعی فیلتر برای BC مطرح می‌شود (به نوعی الگوی Adapter است).

Shared Kernel

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

Shared Kernel

Published language

در اصل BC ارائه‌دهنده سرویس، یک مستندی از سرویس‌های خود را در اختیار سرویس‌گیرنده قرار دهد.

Open Host Service

در این نوع ارتباط، سرویس‌دهنده سرویس مورد نظر خود را در جایی  Host می‌کند  و در قالب API به همراه یک مستند (Published language) در اختیار سرویس‌گیرنده‌ها قرار می‌دهد.

با توجه به مواردی که مطرح شد، وقتی از ارتباط بین BC ها یک مدل تصویری غیر رسمی ایجاد می‌کنیم که نحوه ارتباط آن‌ها را برای ما شفاف‌تر کند، اصطلاحا Context Map ایجاد کرده‌ایم.

Context Map

جمع‌بندی:

برای نوشتن این مقاله از منابع مختلفی استفاده شده است از جمله کتب رسمی، مطالب موجود در وبلاگ‌های مختلف و ... عمده منابع مورد استفاده به شرح زیر است:

[1] Eric Evens., Domain Driven Design: Tackling Complexity in the Heart of Software. 2003.

[2] Scott Millett., Patterns, Principles, and Practices of Domain-Driven Design
. 2003.

[3] Vaughn Vernon , Implementing Domain – Driven Design