خانه / OOP / DDD / Entity in DDD

Entity in DDD

Entity Base Class

اگر اصول DDD رو دنبال کرده باشید احتمالا شما هم یه base entity رو برای تمام domain entity ها ایجاد کردید. این یه ایده ی خوبیه که همچین کلاسی داشته باشیم که Common logic های Entity ها رو یکجا قرار دادیم. وقتی که تصمیم به همچین تصمیمی گرفتید حتما با این سوال مواجه شدید که چه مواردی باید دقیقا توی Base Entity قرار بگیرند.

Interface as a base entity

معمولا مشاهده میشه که Developerها یه interface رو به عنوان base entity در نظر می گیرند, و کد اونها چیزی شبیه زیر است:

public interface IEntity

{

int Id { get; }

}

با این رویکرد مطمئن خواهیم شد که تمام Domain Entity ها حداقل functionality مورد نظر رو دارند-از جمله Id

در اکثر مواقع داشتن یک Interfacce به عنوان base entity ایده ی بدی است. Bad idea

اول از همه Interface نمی تونه هیچگونه logic رو درون خودش داشته باشه, و شما مجبورید که logic های مشترک رو توی domain entity ها پیاده کنید, که منجر به massive code duplication خواهد شد. حتی توی مثال بالا هم منجر به افزودن property مربوط به id در هر single entity خواهد شد؛ که همین منجر به violation شدن DRY خواهد شد.

دوما؛ داشتن یک interface  ریلیشن مناسبی بین domain entity ها نشون نمیده. وقتی که کلاسی interfaceی رو implement می کنه معنیش فقط همینه که نسبت به فیلدها و پروپرتی هایی که توی interface هست تعهد داره. دو کلاسی که interface مشابهی رو implement می کنه؛ هیچ تعهدی نسبت به relation بین آنها ندارن آنها متعلق به یک unconnected hierarchy هستند. به عبارت دیگه IEntity منجر به رابطه ی can do میشه؛ در حالی که domain entity باید با base entity رابطه ی is a  داشته باشند. هر Domain class نه تنها باید id داشته باشند بلکه باید دارای رابطه ی is a هم باشند.

How you shouldn’t implement base classes

چه logicی باید در domain base class باشد؟ طبیعتا باید دارای یک id باشه؛ که به table مپ خواهد شد. تمام tableهای دیتابیس باید دارای id باشد

 

public class Entity<T>

{

public T Id { get; protected set; }

}

 

انگیزه همچین طراحی بوضوح روشن است. این می تواند بین چندین پروژه reuse شود؛ به عنوان مثال اگر در برنامه وبی نیاز به GUID داشته باشید این id می تونه GUID تعریف شه. و برای برنامه ی دستکتاپی دیگر می تونه integer باشه.

 

Entity base class: the code

public abstract class Entity

{

public virtual long Id { get; protected set; }

 

public override bool Equals(object obj)

{

var compareTo = obj as Entity;

 

if (ReferenceEquals(compareTo, null))

return false;

 

if (ReferenceEquals(this, compareTo))

return true;

 

if (GetRealType() != compareTo.GetRealType())

return false;

 

if (!IsTransient() && !compareTo.IsTransient() && Id == compareTo.Id)

return true;

 

return false;

}

 

public static bool operator ==(Entity a, Entity b)

{

if (ReferenceEquals(a, null) && ReferenceEquals(b, null))

return true;

 

if (ReferenceEquals(a, null) || ReferenceEquals(b, null))

return false;

 

return a.Equals(b);

}

 

public static bool operator !=(Entity a, Entity b)

{

return !(a == b);

}

 

public override int GetHashCode()

{

return (GetRealType().ToString() + Id).GetHashCode();

}

 

public virtual bool IsTransient()

{

return Id == 0;

}

 

public virtual Type GetRealType()

{

return NHibernateUtil.GetClass(this);

}

}

مهمترین بخش این کلاس قسمت equality هست. ابتدا دو object از نظر reference equal یا identifier equal با هم مقایسه می شوند.

درباره ی masoud@admin

همچنین ببینید

ValueObject in DDD

بر طبق تعریف آقای Evans: “An object that represents a descriptive aspect of the domain with …

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

در تلگرام هم همراه شما هستم

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

پیوستن بستن