آموزش Domain Driven Design (DDD) + EF Core (قسمت سوم)

توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم.با کمال تشکرداریوش تصدیقیکانال تلگرام: IranianExperts@شماره تلفن همراه: ۰۹۱۲۱۰۸۷۴۶۱نشانی پست الکترونیکی: DariushT@GMail.comفیلم‌های آموزشی https://www.aparat.com/DariushTآدرس سایت‌ها:https://WebsiteAnalytics.ir - http://IranianExperts.ir - http://Date2Date.ir - https://DTApp.irنسخه مقاله: ۱.۰ - تاریخ بروزرسانی: ۱۴۰۰/۰۳/۰۴آموزش Value Object یا ValueObjectبه طور سنتی در #C، متغیرها به دو دسته تقسیم می‌شوند:Value (Primitive) TypeReference Typeکه اکثر ما با آن‌ها آشنا هستیم. ولی برای تولید سامانه‌ها با متدلوژی DDD، ما نیاز به مفهومی داریم که به آن Value Object می‌گویند. به طور کلی Value Object ها، کلاس‌هایی هستند که دارای یک سری خصوصیت و ویژگی می‌باشند:دارای مشخصه یا Identity نمی‌باشند. این یعنی فیلد یا Property‌ ای به نام Id ندارند! پس به طور خلاصه‌تر برای این کلاس‌ها، جدولی در بانک‌اطلاعاتی ایجاد نمی‌شود.باید Immutable باشد. یعنی باید تمام Property های این کلاس‌ها صرفا Get داشته باشند! و مطلقا برای هیچ Property ای، نباید از کلیدواژه Set استفاده نماییم! این بدان معنا است که تمام Property های این کلاس، صرفا از طریق Constructor مقادیرشان را دریافت می‌کنند و پس از ایجاد شیء، امکان تغییر مقادیر Property ها (از هیچ طریقی) نباید وجود داشته باشد! اگر بخواهیم تاکید بیشتری در این خصوص داشته باشیم، باید بگوییم که اگر در داخل کلاس Value Object، یک Property به نام Age وجود داشته باشد و بخواهیم از طریق تابعی مقدار Age را تغییر دهیم، باید در داخل تابع، یک شیء جدید، با مقدار جدید Age، ایجاد کرده و شیء جدید را Return نماییم. لذا بدیهی است که خروجی این تابع باید از جنس همان Value Object باشد. نکته: اگر در فیلم یا مقاله‌ای (داخلی یا خارجی)، کلاس Value Object ای ملاحظه کردیم که در Property های آن Set نوشته باشد، حتی اگر Access Modifier آن Private نیز نوشته شده باشد، قطعا غلط می‌باشد!در صورتی دو متغیر از جنس Value Object، با هم یکسان می‌باشند که مقادیر Property های آن‌ها، نظیر به نظیر دقیقا یکسان باشد.نمونه‌ای از Value Object در #C، کلاس string می‌باشد! اگر مثلا رشته‌ای به نام S داشته باشیم و مقدار آن‌را برابر "ABC" قرار داده باشیم، اگر بخواهیم همه حروف آن‌را به حروف کوچک تبدیل کنیم، احتمالا می‌دانید که دقیقا مقادیری که در HEAP قرار داشته و به صورت آرایه‌ای از کاراکترها بوده و کاراکترهای A, B, C در داخل آن قرار دارد، تبدیل به کاراکترهای a, b, c نمی‌شوند! بلکه یک فضای دیگری در داخل HEAP، ایجاد می‌شود و کاراکترهای a, b, c‌ در داخل آن قرار می‌گیرد و یا اگر بخواهیم یک کاراکتر D‌ را به رشته مذکور (S) اضافه کنیم، واقعا این کاراکتر از سمت راست (در داخل حافظه HEAP)، به رشته اضافه نمی‌شود، بلکه فضای دیگری در حافظه تخصیص داده شده (ایجاد می‌شود) و در فضای جدید کاراکتر D در ادامه کاراکترهای A, B, C قرار خواهد گرفت.این‌که یک کلاس را به گونه‌ای طراحی کنیم که وقتی یک شیء از آن ایجاد می‌کنیم، نتوانیم ویژگی‌های آن‌را تغییر دهیم، کاربردهای زیادی دارد. یکی از مهم‌ترین کاربردها، آن است که وقتی این متغیر Reference Type‌ را به توابع مختلفی ارسال می‌کنیم، اطمینان خواهیم داشت که هیچ تابعی، مقادیر این‌گونه اشیاء را نمی‌تواند تغییر دهد. اصولا Immutable بودن، تست‌پذیری سامانه و خصوصا لایه Domain را نیز راحت‌تر می‌کند.چه زمانی از Value Type استفاده می‌کنیم؟ما به طور سنتی، زمانی که می‌خواهیم برای یک کلاس User، یک Property از جنس Username تعریف نماییم جنس آن‌را string در نظر می‌گیریم و یا زمانی که می‌خواهیم برای کلاس Person، یک Property‌ به نام Age تعریف نماییم، جنس آن‌را int در نظر می‌گیریم. ولی واقعیت آن است که جنس‌هایی مانند string‌ و int‌ برای Property هایی مانند Username و Age بسیار سطحی و غیرقابل کنترل می‌باشد! مثلا در خصوص Username، الزامی بودن، حداقل طول رشته، حداکثر طول رشته، Regular Express آن و غیره بسیار اهمیت دارد. و یا در خصوص Age نیز الزامی بودن، منفی نبودن، در یک بازه‌ای (مثلا بین ۲۰ تا ۴۰ سال) بودن و غیره نیز در یک سامانه بسیار اهمیت دارد. در این حالات، به جای استفاده از Value Type‌ ها و string‌ و غیره، برای یکایک این موارد یک کلاس به نام‌های Age‌ و Username تعریف کرده و Property‌ های خود را از همین جنس تعریف می‌کنیم. به عنوان مثال در کلاس Entity‌ مانند Customer (در مقالات بعدی، در خصوص کلاس‌های Entity‌ و نحوه پیاده‌سازی آن‌ها بحث خواهیم کرد) به جای شکل ذیل:تصویر شماره یکاز این شکل استفاده می‌کنیم:تصویر شماره دوویژگی دیگری که در خصوص طراحی کلاس‌های Value Object وجود دارد آن است که باید در زمان خلق شیء عملیات Validation صورت گیرد و اگر مشکلی در خصوص Validation پارامتر و یا پارامترهای ورودی سازنده کلاس وجود دارد، عملیات خلق شیء‌ متوقف شده و Exception پرتاب (Throw) گردد.این مقاله هنوز تکمیل نشده است!