TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 550 subscribers
Post #440 136
⚖️ Domain Events در مقابل Integration Events

ممکن است قبلاً دربارهٔ Integration Events شنیده باشید و اکنون این سؤال برایتان پیش آمده باشد که تفاوت آن‌ها با Domain Events در چیست.

از نظر معنایی (Semantically)، هر دو یکی هستند:
نمایانگر چیزی‌اند که در گذشته اتفاق افتاده است.
اما هدف (Intent) آن‌ها متفاوت است — و درک این تفاوت اهمیت زیادی دارد.

🧩 Domain Events:

• درون یک Domain واحد منتشر و مصرف (Consume) می‌شوند.
• از طریق یک in-memory message bus ارسال می‌شوند.
• می‌توانند به‌صورت synchronous یا asynchronous پردازش شوند.

🔗 Integration Events:

• توسط زیرسیستم‌ها (مانند microservices یا Bounded Contexts) مصرف می‌شوند.
• از طریق message broker و روی queue ارسال می‌شوند.
• به‌صورت کاملاً asynchronous پردازش می‌شوند.

💡 بنابراین، اگر نمی‌دانید چه نوع Eventی باید منتشر کنید، به هدف (Intent) و اینکه چه کسی باید آن را مدیریت کند فکر کنید.

در واقع، Domain Events می‌توانند برای تولید Integration Events نیز مورد استفاده قرار گیرند - رویدادهایی که از مرز (boundary) Domain خارج می‌شوند.

🏗 پیاده‌سازی Domain Events

روشی که من برای پیاده‌سازی Domain Events ترجیح می‌دهم، ایجاد یک abstraction به نام IDomainEvent و پیاده‌سازی آن از MediatR.INotification است.

مزیت این کار این است که می‌توان از قابلیت publish-subscribe در MediatR برای انتشار یک Notification به یک یا چند Handler استفاده کرد.
using MediatR;

public interface IDomainEvent : INotification
{
}

اکنون می‌توانید یک Domain Event مشخص (Concrete) را پیاده‌سازی کنید.

در هنگام طراحی Domain Events، چند نکتهٔ مهم را باید در نظر بگیرید 👇

⚙️ نکات کلیدی طراحی Domain Events:

🔹️Immutability (تغییرناپذیری) :
چون Domain Event یک واقعیت (Fact) است، باید غیرقابل‌تغییر باشد.

🔹️Fat vs Thin Domain Events :
چقدر اطلاعات لازم دارید؟ (Eventها را بیش از حد سنگین یا بیش از حد سبک طراحی نکنید.)

🔹️نام‌گذاری با زمان گذشته :
برای نام Event از past tense استفاده کنید.

🔸 مثال:
public class CourseCompletedDomainEvent : IDomainEvent
{
public Guid CourseId { get; init; }
}


🚀 Raising Domain Events

پس از اینکه Domain Event‌های خود را ایجاد کردید، باید بتوانید آن‌ها را از درون Domain فراخوانی (raise) کنید.

روش پیشنهادی من این است که یک کلاس پایه به نام Entity بسازید،
چون فقط Entityها مجازند Domain Event ایجاد کنند.

برای کپسوله‌سازی (Encapsulation) بهتر، متد RaiseDomainEvent را می‌توان protected تعریف کرد تا فقط از داخل کلاس یا زیرکلاس‌ها قابل فراخوانی باشد.

در این پیاده‌سازی، ما Domain Eventها را در یک لیست داخلی (internal collection) نگهداری می‌کنیم تا هیچ بخش دیگری از سیستم نتواند مستقیماً به آن دسترسی داشته باشد.

متد GetDomainEvents یک snapshot از لیست داخلی برمی‌گرداند،
و متد ClearDomainEvents برای پاک‌سازی لیست داخلی استفاده می‌شود.
public abstract class Entity : IEntity
{
private readonly List<IDomainEvent> _domainEvents = new();

public IReadOnlyList<IDomainEvent> GetDomainEvents()
{
return _domainEvents.ToList();
}

public void ClearDomainEvents()
{
_domainEvents.Clear();
}

protected void RaiseDomainEvent(IDomainEvent domainEvent)
{
_domainEvents.Add(domainEvent);
}
}

اکنون Entity‌های شما می‌توانند از این کلاس پایه ارث‌بری کرده و Domain Event‌ها را raise کنند 👇
public class Course : Entity
{
public Guid Id { get; private set; }

public CourseStatus Status { get; private set; }

public DateTime? CompletedOnUtc { get; private set; }

public void Complete()
{
Status = CourseStatus.Completed;
CompletedOnUtc = DateTime.UtcNow;

RaiseDomainEvent(new CourseCompletedDomainEvent { CourseId = this.Id });
}
}

✅ حالا تنها کاری که باقی مانده، انتشار (Publish) کردن Domain Eventها است.
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →