primaria para modelos modelo lectora interactivo gough descendente comprension cassany bottom ascendente domain-driven-design cqrs event-sourcing

domain driven design - para - Generación de eventos y generación de modelos de lectura.



modelos de comprension lectora para primaria (3)

Suponiendo un problema de dominio de desbordamiento de pila y la siguiente definición de eventos:

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

Suponiendo el siguiente estado de almacenamiento de eventos (en el orden de aparición):

1) UserRegistered(1, "John", "[email protected]") 2) UserNameChanged(1, "SuperJohn") 3) UserNameChanged(1, "John007") 4) QuestionAsked(1, 1, "Help!", "Please!")

Suponiendo el siguiente modelo de lectura desnormalizada para el listado de preguntas (para la primera página de SO):

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

Y el siguiente controlador de eventos (que construye el modelo de lectura desnormalizado):

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? */); ... } }

Mi pregunta es ¿cómo puedo encontrar el nombre del usuario que hizo una pregunta? O más común: ¿cómo debo manejar los eventos si mi modelo de lectura desnormalizada requiere datos adicionales que no existen en el evento en particular?

He examinado muestras existentes de CQRS incluyendo SimpleSQRS de Greg Young y Fohjin muestra de Mark Nijhof. Pero me parece que operan solo con datos que se incluyen en eventos.


Personalmente creo que no hay nada de malo en buscar el nombre del usuario desde el controlador de eventos. Pero si está en una posición en la que no puede consultar el nombre del modelo de lectura del Usuario, entonces le presentaré un controlador de eventos adicional a QuestionEventsHandler, para controlar el evento registrado por el usuario.

De esa manera, QuestionEventsHandler podría mantener su propio repositorio de nombres de usuarios (no necesitaría almacenar el correo electrónico de los usuarios). El controlador QuestionAsked puede consultar el nombre del usuario directamente desde su propio repositorio (¡como Rinat Abdullin dijo que el almacenamiento es barato!).

Además, dado que su modelo de lectura de QuestionItem contiene el nombre del usuario, también deberá manejar el evento UserNameChanged dentro de QuestionEventsHandler para asegurarse de que el campo de nombre dentro del QuestionItem esté actualizado.

Para mí, esto parece menos esfuerzo que ''enriquecer los eventos'' y tiene la ventaja de no crear dependencias en otras partes del sistema y sus modelos de lectura.


Solo enriquece el evento con toda la información necesaria.

El enfoque de Greg, como recuerdo, enriquece el evento al crearlo y almacenarlo / publicarlo de esta manera.


Tire eventos del EventStore.

Recuerde: sus modelos de lectura ya deben tener acceso de solo lectura a EventStore. Los modelos de lectura son desechables. Son simplemente vistas en caché. Debería poder eliminar / caducar sus modelos de lectura en cualquier momento, y reconstruir automáticamente sus modelos de lectura desde el almacén de eventos. Por lo tanto, sus ReadModelBuilders ya deben poder consultar eventos pasados.

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 } }

Además, tenga en cuenta que el repositorio de EventStore no necesita ser el verdadero EventStore, aunque ciertamente podría serlo. La ventaja de los sistemas distribuidos es que puede replicar fácilmente el EventStore, si lo necesita, más cerca de sus ReadModels.

Encontré este mismo escenario exacto ... donde necesitaba más datos de los que estaba disponible en un solo evento. Esto es especialmente cierto para los eventos de tipo Crear que requieren llenar un nuevo ReadModel con el estado inicial.

Desde modelos de lectura: puede extraer de otros modelos de lectura. Pero realmente no lo recomiendo, ya que introduciría una gran bola de barro de dependencia donde las vistas dependen de las vistas dependen de las vistas.

Datos adicionales en eventos: realmente no desea inflar sus eventos con todos los datos adicionales que necesitará para las vistas. Realmente te hará daño cuando tu dominio cambie y necesitas migrar eventos. Los eventos de dominio tienen propósitos específicos: representan cambios de estado. No ver los datos.

Espero que esto ayude -

Ryan