متدولوژی Domain Driven Design
بسم الله الرحمن الرحیم
این مطلب را برای دوستان طراح قرار دادم انشالله مفید واقع شود
متدولوژی Domain Driven Design
قبل از پرداختن به متدولوژی مربوطه می بایست با چند مبحث آشنا شویم.
Domain Model نمایی کلی از هر آنچه در سیستم می گذرد که قلب یک برنامه MVC است که قسمت های دیگر مثل View,Controller فقط وظیفه ایجاد ارتباط با این قسمت را دارند.
یک Domain Model شامل موارد زیر است:
اجزای سی شارپ مانند کلاس ها، Structها و همانند آنکه در مجموع به آن Domain type گفته می شود.
عملیاتی که در Domain Model انجام می شوند به وسیله متدهایی که در Domain Type تعریف شده اند انجام می پذیرند.
زمانی که نمونه ای از یک Domain Type را که نمایانگر موجودیتی است ایجاد می کنید، در حقیقت در حال ایجاد یک Domain Object هستید.
یک روش خوب برای ایجاد Domain Model ایجاد یک پروژه از نوع Class Library تنها برای Domain Model است بدین ترتیب می توان از قسمت های دیگر پروژه به پروژه ی Domain Model ارجاع داشت.
در Asp.Net MVC سه قابلیت برای کار با Domain Model وجود دارد:
Model Binding: همان ویژگی که در View از آن استفاده می کنید. (ارسال و دریافت پراپرتی ها به صورت یک مدل)
Model Metadata:روشهایی مانند [Display] که در مدل از آن استفاده می کنید.
Validation: اعتبارسنجی که در مدل انجام می دهید.
مدل کردن یک Domain
مدل کردن یک Domain یا Domain Modeling، فرایندی است که در طی آن اهداف و نیازمندی های پروژه شناسایی می شود.
ایجاد یک Domain Modeling
برای تفهیم بهتر به یک مثال می پردازیم مثلا سیستم ثبت گزارش را در نظر بگیرید (همانند سیستم داخلی خودمان که در مجموعه از آن استفاده می کنیم) در این سیستم ما با سه موجودیت را تعریف می کنیم تا مثال بسیار ساده باشد:
- کاربران
- حساب کاربری
- گزارش
برای هر کدام فقط چند فیلد بیشتر در نظر نمی گیرم تا از بحث اصلی دو نشویم
- کاربران
- کلید اصلی
- نام و نام خانوادگی
- کدملی
- حساب کاربری
- کلید اصلی
- نام کاربری
- کلمه عبور
- گزارش
- کلید اصلی
- متن گزارش
- تاریخ ثبت
البته خود من هیچ وقت با مثال های ناقص موافق نیستم اما اگر به فیلدها بپردازیم از مبحث دور می شویم به همین دلیل فقط مواردی را ذکر کردم که همه دوستان با موافق باشند چون انتخاب فیلد وابسته تحلیل پروژه است و هدف ما ساخت پروژه نیست!
از آنجایی که همه دوستان تیم طراحی از Visual Paradigm استفاده می کنند من نیز در این مثال از همین نرم افزار استفاده کرده ام، در تصویر زیر طراحی انجام شده را مشاهده می کنید.
نحوه ارتباطات را نیز مشخص است البته می بایست من بجای کلاس از مدل استفاده می کردم اما چون دوستان دیگر خارج از مجموعه ما از مطالب استفاده می کنند خواستیم مطالب کاملا گویا باشد.
به مبحث خودمان باز می گردیم حتما متوجه عبارت Aggregate و حاشیه ایجاد شده دور دو کلاس People , Account شده اید.
Aggregate چیست؟
یک Aggregate شامل چند موجودیت خواهد بود در هر Aggregate، یک موجودیت ریشه وجود دارد که به آن به اصطلاح Root Entity یا Aggregate Root گفته می شود که در این جا People است که از آن برای مشخص کردن کل Aggregate و اعمالی مانند تعیین اعتبار مقادیر موجودیت ها و عملیاتی که بر روی داده انجام می شود استفاده می شود.
یکی از قوانین کلیدی متدولوژی DDD این است که موجودیت های خارج از یک Aggregate تنها می توانند با Root Entity آن Aggregate ارتباط داشته باشند و نه دیگر موجودیت های موجود در آن Aggregate و موجودیت های موجود در Aggregate تنها می توانند با Root Entity یک Aggregate ارتباط داشته باشند. این طور می توان گفت که دسترسی به موجودیت های موجود در یک Aggregate، تنها از طریق Root Entity آن Aggregate امکان پذیر است.
نحوه انتخاب یک Aggregate؟
انتخاب به این صورت مشخص می شود که موجودیتهای مرتبط با یکدیگر را باید در Aggregate قرار دهید، برای مثال وقتی یک موجودیت را حذف می کنید چه موجودیت های دیگری باید حذف شوند؟
در مثال ما وقتی یک گزارش حذف می شود هیچ اطلاعات دیگری حذف نمی شود پس آن را یک موجودیت جدا در نظر می گیریم یعنی خودش به تنهایی یک Aggregate است و خودش نیز Root Entity است اما وقتی Account را حذف می کنیم اطلاعاتی مانند گزارش نیز حذف نمی شود اما یک تفاوت وجود دارد آن هم اینکه وقتی یک People یا همان کاربر را حذف می کنیم می بایست Account آن هم نیز حذف شود پس هر دو را در یک Aggregate قرار می دهیم و از آنجایی که در این مثال من شخصا رابطه را بر اساس People گذاشتم پس Root Entity ما نیز همین People است.
یک نکته وقتی People حذف می شود گزارش را هم باید حذف کنیم پس چرا گزارش را هم در Aggregate قرار ندادیم؟
خوب قبل از اینکه جواب سوال خودم را بدهم بگذارید قسمت Account و People را بیشتر توضیح دهم وقتی کسی را حذف کنیم اطلاعات Account آن هیچ ارزشی برای ما ندارد، چه ارزشی دارد بدانید یک روزی فردی درسیستم شما با این نام کاربری و کلمه عبور در سیستم فعالیت می کرده اما نمی دانید چه کسی بوده پس درست است که هر دو موجودیت در یک Aggregate باشند و People در این Aggregate یکRoot Entity باشد.حال اگر فردی را بخواهیم حذف کنیم گزارشات آن نیز مانند مثال Account می شود! اما یک نکته موجو دارد همین رابطه را برعکس بررسی کنیم مثلا اگر گزارش را حذف کنیم هیچ مشکلی نیست اگر Account راحذف کنیم هیچ مشکلی نیست زیرا مشخص است که هر گزارش مربوط به چه کسی بوده است و فقط کاربر دیگر نمی تواند وارد سیستم شود. پس اینکه چرا ما گزارش را خارج از Aggregate قرار دادیم تا حدی روشن است اما شاید قانع نشوید ولی این نکته را در نظر بگیرید که ما یک مثال کوچک مطرح کردیم بهتر است این مثال را خودتان گسترش دهید مطما هستم بهتر متوجه مسائل خواهید شد.
Aggregate ها پایه و اساس Domain Modelرا تشکیل می دهند و برای مدیریت تراکنش ها و حذف رکوردهای فرزند یک پدر بسیار مناسب هستند و از آنجا که Aggregate ها مفهومی هستند که نه در SQL و نه در هیچ ابزار ORM دیگر شناخته شده نیستند باید در پیاده سازی آنها دقت کنیم و این دقت تنها با رعایت نظم و ارتباط موثر بین تیم تحلیل و توسعه به وجود خواهد آمد.
برای تکمیل مثال کد مربوطه را به صورت مختصر تولید و در زیر قرار داده ام، انشالله که توانسته باشم مطلب را حداقل معرفی کنم
public class Account
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}
public class People
{
public Account account { get; set; }
public int Id { get; set; }
public string FullName { get; set; }
public string NationalCode { get; set; }
}
public class Report
{
public People people { get; set; }
public int Id { get; set; }
public string Text { get; set; }
public DateTime RegisterDate{ get; set; }
}