اگر در پروژه های کسب و کار محور کار کرده باشید، حتما در مورد Domain Driven Design یا به اختصار DDD اطلاعات کافی دارید و میدونید که یک تفکری هست که در حوالی سال 2003 توسط آقای Eric Evans نوشته شده است (ایشون الان حدود 65 سال سن دارند) و در حالت کلی داره میگه که در یک پروژه، چگونه میتوانیم جداسازی ها و تفکیک ها رو بر اساس دامنه های کاری بیزینس انجام بدیم و روش های درستش چی هست. اگر میخواهید اطلاعات کافی داشته باشید، کتاب مرجع Domain-Driven Design: Tackling Complexity in the Heart of Software رو بررسی کنید ولی اگر زمان کافی برای مطالعه رو ندارید، بریم سراغ بررسی کلید واژه ها و موضوعات اساسی که در این مقاله میخوام در موردشون صحبت کنم. این مقاله برای معماران و تحلیل گران نرم افزار، برنامه نویس ها و علاقه مندان به این حوزه مفید خواهد بود.

روی صحبت مقاله با کسانی هست که میخواهند قبل از پیاده سازی DDD در پروژه های نرم افزاری که دارای لایه بندی و معماری Clean یا Onion یا Hexagonal یا هر معماری و پترن دیگریست، مفاهیم پایه DDD رو از نگاهی با جنس نرم افزار و کد تجربه کنند.
در گام اول بیایید دو مبحث Strategic Design و Tactical Design رو بحث کنیم و نگاهشون رو بدونیم.
نگاه Strategic Design
Strategic Design در DDD به لایهای از طراحی اشاره داره که تمرکز اون بر درک کلان دامنه کسبوکار و تعیین مرزهای مفهومی سیستم است. در این سطح، هدف اصلی پاسخ به این پرسشهاست که «سیستم ما از چه بخشهایی تشکیل شده است؟»، «هر بخش چه مسئولیتی دارد؟» و «کدام مفاهیم نباید با یکدیگر درهمآمیخته شوند؟». Strategic Design به معماران نرمافزار و تحلیلگران کمک میکنه تا پیش از ورود به جزئیات فنی و پیادهسازی، ساختاری شفاف و همراستا با واقعیتهای بیزینسی ایجاد کنند. مفاهیمی مانند مرزبندی دامنهها، جلوگیری از وابستگیهای ناخواسته و همراستاسازی تیم فنی و بیزینس، همگی در این سطح مورد توجه قرار میگیره و نقش حیاتی در کاهش پیچیدگی و افزایش پایداری سیستم در بلندمدت دارد.
نگاه Tactical Design
Tactical Design بخش اجرایی و پیادهسازیمحور DDD هست که تمرکز آن بر مدلسازی دقیق مفاهیم دامنه در قالب کد میباشد. در این سطح، تلاش میشه ساختار کلاسها، اشیاء و سرویسها بهگونهای طراحی شوند که بازتابی مستقیم از منطق بیزینسی باشند. Tactical Design به برنامهنویس ها و قبل از اون معمار ها، کمک میکند تا منطق دامنه را از لایههای زیرساختی و فنی جدا کرده و کدی بنویسند که خوانا، قابل نگهداری و منطبق بر زبان مشترک تیم باشد. مفاهیمی مانند Entity، Value Object، Aggregate و Serviceها در این لایه تعریف میشوند و هسته اصلی مدل دامنه را شکل میدهند.
حالا بریم سراغ کلید واژه هایی که داخل این مفاهیم وجود دارند:
Entity
Entity در DDD به مفهومی اطلاق میشود که دارای هویت یکتاست و این هویت، مستقل از وضعیت یا ویژگیهای فعلی آن، عامل تمایز آن محسوب میشود. یک Entity ممکن است در طول چرخه عمر خود تغییرات متعددی را تجربه کند، اما تا زمانی که هویت آن ثابت است، همچنان همان موجودیت تلقی میشود. از دیدگاه بیزینسی، Entity معمولاً نماینده مفاهیمی است که پیگیری، ردیابی و تاریخچه آنها اهمیت دارد، مانند کاربر، سفارش یا قرارداد. در طراحی دامنه، تمرکز اصلی Entity نه بر دادههای آن، بلکه بر رفتارها و قوانین بیزینسی مرتبط با آن است.
Value Object
Value Object نمایانگر مفاهیمی در دامنه است که هویت مستقل ندارند و تنها بر اساس مقدارشان تعریف میشوند. این اشیاء معمولاً immutable هستند؛ به این معنا که پس از ایجاد، تغییر نمیکنند و هرگونه تغییر منجر به ایجاد یک نمونه جدید میشود. Value Objectها به سادهسازی مدل دامنه کمک میکنند و باعث میشوند منطق بیزینسی بهصورت شفافتر و دقیقتر بیان شود. مفاهیمی مانند آدرس، مبلغ پول یا بازه زمانی نمونههایی رایج از Value Object هستند که در آنها برابری مفهومی اهمیت دارد، نه هویت.
Aggregate
Aggregate مفهومی است که برای گروهبندی چند Entity و Value Object مرتبط با یکدیگر تحت یک مرز مشخص استفاده میشود. هدف اصلی Aggregate حفظ یکپارچگی و سازگاری قوانین بیزینسی درون این مرز است. در DDD، هر Aggregate بهعنوان یک واحد تراکنشی در نظر گرفته میشود و تغییرات باید بهگونهای اعمال شوند که قوانین دامنه در هر لحظه نقض نشوند. تعریف صحیح Aggregate نقش مهمی در کنترل پیچیدگی سیستم و جلوگیری از وابستگیهای بیش از حد بین بخشهای مختلف مدل دامنه دارد.
Aggregate Root
Aggregate Root موجودیتی است که بهعنوان نقطه ورود و کنترلکننده یک Aggregate عمل میکند. تمام تعاملات خارجی با اجزای داخلی Aggregate باید از طریق Aggregate Root انجام شوند. این مفهوم تضمین میکند که قوانین بیزینسی و قیود دامنه بهدرستی اعمال شده و از دسترسی مستقیم و ناامن به اجزای داخلی جلوگیری شود. Aggregate Root مسئول حفظ انسجام و صحت دادهها در محدوده Aggregate است و نقش کلیدی در طراحی مدل دامنه ایفا میکند.
Domain
Domain در DDD به حوزه مسئلهای اشاره دارد که نرمافزار برای حل آن طراحی میشود. Domain در واقع بازتابی از واقعیتهای کسبوکار، قوانین، محدودیتها و فرآیندهایی است که سازمان با آنها سروکار دارد. درک صحیح Domain پیشنیاز اصلی موفقیت در DDD است، زیرا تمام تصمیمات معماری و طراحی باید بر اساس آن اتخاذ شوند. Domain نه یک مفهوم فنی، بلکه یک مفهوم بیزینسی است و باید از طریق تعامل مستمر با متخصصان کسبوکار (Domain Experts) بهدرستی شناسایی و مدلسازی شود. حالا در ادامه این بحث، موضوعات Subdomain ، موضوع Core Subdomain ، موضوع Supporting Subdomain و چیز های دیگری وجود داره که من در این مقاله نمیخوام واردش بشم و اگر کسی خیلی نیاز داره عمیق بشه، کتابی که در اول مقاله گذاشتم رو بخونه.
Ubiquitous Language
Ubiquitous Language زبان مشترکی است که میان تیم فنی و بیزینس برای توصیف Domain استفاده میشود. این زبان باید در مکالمات روزمره، مستندات و حتی در کد منبع بهصورت یکسان به کار رود. هدف Ubiquitous Language حذف سوءتفاهمها و ایجاد همراستایی ذهنی بین همه ذینفعان سیستم است. زمانی که کد نرمافزار با همان مفاهیمی نوشته میشود که بیزینس با آن صحبت میکند، فاصله بین تحلیل و پیادهسازی به حداقل میرسد.
Bounded Context
Bounded Context محدودهای مشخص است که در آن یک مدل دامنه خاص و Ubiquitous Language مربوط به آن معتبر است. این مفهوم یکی از کلیدیترین مفاهیم Strategic DDD محسوب میشود، زیرا از تداخل مفاهیم و مدلها جلوگیری میکند. هر Bounded Context میتواند تعاریف متفاوتی از یک مفهوم مشابه داشته باشد و این تفاوتها کاملاً قابل قبول هستند، به شرط آنکه مرزها شفاف باشند. Bounded Context مبنای طراحی معماری ماژولار و سیستمهای توزیعشده است.
Context Map
Context Map ابزاری مفهومی برای نمایش ارتباط بین Bounded Contextها است. این نقشه نشان میدهد که Contextهای مختلف چگونه با یکدیگر تعامل دارند و چه نوع وابستگیهایی میان آنها وجود دارد. Context Map به معماران کمک میکند تا روابط پیچیده بین تیمها و سیستمها را مدیریت کرده و از ایجاد coupling ناخواسته جلوگیری کنند. این مفهوم نقش مهمی در طراحی سیستمهای بزرگ و سازمانی ایفا میکند.
Repository
Repository یک الگوی طراحی در Tactical DDD است که مسئول مدیریت چرخه حیات Aggregateها میباشد. Repository بهعنوان یک واسط بین Domain Model و لایه ذخیرهسازی عمل میکند و جزئیات فنی مربوط به پایگاه داده را از منطق دامنه پنهان میسازد. استفاده از Repository باعث میشود Domain Model مستقل از فناوری ذخیرهسازی باقی بماند و تمرکز آن بر منطق بیزینسی حفظ شود.
Domain Event
Domain Event بیانگر رخدادی معنادار در دامنه کسبوکار است که وقوع آن برای سایر بخشهای سیستم اهمیت دارد. این رویدادها معمولاً نشاندهنده تغییر وضعیت یا انجام یک عمل مهم بیزینسی هستند و به سیستم اجازه میدهند بهصورت واکنشمحور طراحی شود. استفاده از Domain Eventها به کاهش coupling بین اجزای مختلف سیستم کمک کرده و امکان توسعهپذیری و انعطافپذیری بالاتری را فراهم میکند. این مفهوم پلی میان منطق دامنه و نیازهای ارتباطی سیستم ایجاد میکند.
Domain Service
Domain Service زمانی مورد استفاده قرار میگیرد که منطق بیزینسی مشخصی وجود دارد که بهطور طبیعی متعلق به هیچ Entity یا Value Object خاصی نیست. این سرویسها بخشی از لایه دامنه هستند و شامل منطق بیزینسی خالص میشوند، نه منطق فنی یا زیرساختی. Domain Serviceها به مدل دامنه کمک میکنند تا از شلوغ شدن Entityها جلوگیری شود و مسئولیتها بهصورت شفاف و منطقی توزیع شوند.
Application Service
Application Service نقش هماهنگکننده بین لایههای بیرونی سیستم و مدل دامنه را بر عهده دارد. این سرویسها مسئول اجرای Use Caseها هستند و معمولاً شامل منطق بیزینسی پیچیده نمیشوند. وظایفی مانند مدیریت تراکنشها، فراخوانی سرویسهای دامنه، ارسال و دریافت داده از لایه ارائه و کنترل جریان اجرای عملیات، در این لایه انجام میشود. Application Service مرزی شفاف بین دنیای فنی و منطق دامنه ایجاد میکند و به حفظ تمیزی معماری کمک مینماید.
خب، حالا که این ها رو بررسی کردیم، میخوام بگم در عالم فنی و کد نویسی، ما بیشتر با مفاهیمی که میگم سر و کار خواهیم داشت:
Entity ها
Value Object ها
Aggregate ها
Aggregate Root ها
Domain Event ها
Domain Service ها
Application Service ها
در مقاله های بعدی، میریم به سراغ اینکه، در معماری های میکروسرویس و حتی معماری های غیر میکروسرویسی، چطور میتونیم مفاهیم DDD رو وارد پروژه کرده و ازش استفاده کنیم.