سؤال

بافتراض مشكلة مجال تجاوز الفائض والتعريف التالي للأحداث:

UserRegistered(UserId, Name, Email)
UserNameChanged(UserId, Name)
QuestionAsked(UserId, QuestionId, Title, Question)

بافتراض الحالة التالية لمتجر الأحداث (بترتيب المظهر):

1) UserRegistered(1, "John", "john@gmail.com")
2) UserNameChanged(1, "SuperJohn")
3) UserNameChanged(1, "John007")
4) QuestionAsked(1, 1, "Help!", "Please!")

على افتراض نموذج قراءة القراءة التالي لإدراج أسئلة (للصفحة الأولى من SO):

QuestionItem(UserId, QuestionId, QuestionTitle, Question, UserName)

ومعالج الحدث التالي (الذي يبني نموذج قراءة غير طبيعي):

public class QuestionEventsHandler
{
    public void Handle(QuestionAsked question)
    {
        var item = new QuestionItem(
            question.UserId, 
            question.QuestionId, 
            question.Title, 
            question.Question, 
            ??? /* how should i get name of the user? */);
        ...
    }
}

سؤالي هو كيف يمكنني العثور على اسم المستخدم من طرح سؤال؟ أو أكثر شيوعًا: كيف يجب أن أتعامل مع الأحداث إذا كان نموذج القراءة غير الطبيعي يتطلب بيانات إضافية لا توجد في الحدث المعين؟

لقد درست العينات الحالية من CQRs بما في ذلك simplesqrs من جريج يونغ و fohjin عينة من Mark nijhof. ولكن يبدو لي أنهم يعملون فقط مع البيانات المدرجة في الأحداث.

هل كانت مفيدة؟

المحلول

ما عليك سوى إثراء الحدث بكل المعلومات اللازمة.

نهج جريج ، كما أتذكر ، - إثراء الحدث أثناء إنشاءه وتخزينه/ينشره بهذه الطريقة.

نصائح أخرى

أنا شخصياً أعتقد أنه لا حرج في البحث عن اسم المستخدم من داخل معالج الحدث. ولكن إذا كنت في وضع لا يمكنك فيه الاستعلام عن الاسم من نموذج قراءة المستخدم ، فسأقوم بتقديم معالج حدث إضافي إلى QuestionEventShandler ، للتعامل مع الحدث الذي تم تسجيله المستخدم.

وبهذه الطريقة ، يمكن لـ QuestionEventShandler الحفاظ على مستودعها الخاص لأسماء المستخدمين (لن تحتاج إلى تخزين بريد إلكتروني المستخدمين). يمكن للمعالج الذي تم تساؤله بعد ذلك الاستعلام عن اسم المستخدم مباشرة من مستودعه الخاص (كما قال Rinat Abdullin إن التخزين رخيص!).

بالإضافة إلى ذلك ، فإن نموذج قراءة QuestionItem الخاص بك يحمل اسم المستخدم ، ستحتاج إلى التعامل مع الحدث الذي تم استخدامه في UseRnameChanged ضمن سؤال QuestionEventShandler وكذلك لضمان تحديث حقل الاسم في QuestionItem.

بالنسبة لي ، يبدو هذا جهدًا أقل من "إثراء الأحداث" ولديه فائدة من ليس بناء التبعيات على أجزاء أخرى من النظام ونماذج القراءة.

سحب الأحداث من EventStore.

تذكر - تحتاج نماذج القراءة الخاصة بك إلى الوصول للقراءة فقط إلى EventStore بالفعل. قراءة النماذج يمكن التخلص منها. هم ببساطة وجهات النظر المخبأة. يجب أن تكون قادرًا على حذف / انتهاء صلاحية طرز القراءة في أي وقت - وإعادة بناء READModels تلقائيًا من EventStore. لذلك - يجب أن يكون لاعبون ReadModelBuilders الخاص بك قادرين بالفعل على الاستعلام عن الأحداث الماضية.

public class QuestionEventsHandler
{
    public void Handle(QuestionAsked question)
    {
        // Get Name of User
        var nameChangedEvent = eventRepository.GetLastEventByAggregateId<UserNameChanged>(question.UserId);

        var item = new QuestionItem(
            question.UserId, 
            question.QuestionId, 
            question.Title, 
            question.Question, 

            nameChangedEvent.Name
    }
}

أدرك أيضًا - لا يلزم أن يكون مستودع EventStore هو الحدث الحقيقي ، على الرغم من أنه قد يكون بالتأكيد. تتمثل ميزة الأنظمة الموزعة في أنه يمكنك بسهولة تكرار EventStore ، إذا كنت بحاجة ، أقرب إلى Reshodels.

واجهت هذا السيناريو نفسه بالضبط ... حيث كنت بحاجة إلى المزيد من البيانات مما كانت متوفرة في حدث واحد. وينطبق هذا بشكل خاص على أحداث إنشاء نوع تتطلب ملء عرض جديد مع الحالة الأولية.

من نماذج القراءة: يمكنك سحب من نماذج القراءة الأخرى. لكنني لا أوصي بهذا حقًا ، حيث ستقدم كرة كبيرة من الطين التبعي حيث تعتمد وجهات النظر على وجهات النظر على وجهات النظر.

بيانات إضافية في الأحداث: أنت لا ترغب حقًا في تفجير الأحداث الخاصة بك مع جميع البيانات الإضافية التي ستحتاجها للحصول على طرق عرض. سوف يؤذيك حقًا عندما يتغير مجالك وتحتاج إلى ترحيل الأحداث. أحداث المجال لها أغراض محددة - فهي تمثل تغييرات الدولة. عدم عرض البيانات.

أتمنى أن يساعدك هذا -

ريان

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top