2011-08-23 11 views
12

Tengo algunas clases de entidades en mi aplicación. Quiero guardar todos los cambios en estas entidades y algunos eventos sucedidos en una tabla de historial. El problema es que las clases de entidades son diferentes, se construyen con diferentes primitivas y diferentes relaciones entre ellas.¿Patrón de diseño bueno para la historia de muchas entidades?

Por ejemplo, en una aplicación de compras puede haber: Usuario, Artículo, Transacción, Mirar. Quiero ser capaz de mostrar un poco de registro de actividades para el usuario así:

  • 16:00 Usted ha comprado "Señor de los Anillos" en una transacción de 2468,
  • 15:30 Ha añadido " Hobbit "a tu lista de observación,
  • 15:00 El elemento observado" Silmarillion "ha bajado de 15 a 12,50 euros,
  • 14:30 Has cambiado tu nombre de" Tomasz "a" Tom ".

Hay muchas cosas involucradas en este registro:

  • nueva entidad Transacción de 2468 con el artículo "Señor de los Anillos",
  • nueva entidad reloj vinculado con el punto "Hobbit" y mi cuenta,
  • precio actualizado del artículo (pero se almacenan tanto los precios antiguos como los nuevos),
  • actualizado Nombre de usuario (tanto antiguo como nuevo almacenado).

Mi pregunta principal es ¿cómo hacer un seguimiento de estos datos?

  1. ¿Debo tener tantas tablas como muchas tablas de entidades para mantener sus cambios? UserVersions, ItemVersions, etc.
  2. ¿Debo consultar todas las tablas de versiones, unirme y ordenar los resultados para generar este registro?
  3. O tal vez debería haber una tabla Versiones con columnas "Entity", "OldValue", "NewValue": ¿qué pasa con las restricciones y las claves externas? ¿No es una solución demasiado sucia?
  4. ¿Hay un patrón de diseño para esto?
  5. Finalmente, si lo sabe, ¿cómo lo hace Facebook? :)

Respuesta

6

Puede que le interese el patrón de diseño llamado Event Sourcing.

Event Sourcing garantiza que todos los cambios en el estado de la aplicación sean almacenados como una secuencia de eventos. No solo podemos consultar estos eventos, también podemos usar el registro de eventos para reconstruir estados pasados, y como una base para ajustar automáticamente el estado para hacer frente a los cambios retroactivos de .

En cuanto a cómo almacenar dichos eventos, realmente depende de los requisitos. Algunas veces es suficiente simplemente serializarlo a JSON.

Event Sourcing está incluido en la mayoría de las implementaciones de CQRS, por lo que puede encontrar información adicional en casi cualquier recurso relacionado con ella.

+0

Gracias, creo que su respuesta es la más completa y enlaza con muchas fuentes relacionadas con más explicaciones. –

+0

Vea también http://cqrsinfo.com/documents/ –

0

Tal vez podría utilizar un enfoque que toman Drupal y algunos otros CMS, es decir, mantener las versiones actuales y anteriores de los mismos datos en una sola tabla. Descrito en más detalle por ejemplo aquí: CMS versioning strategies for content

No sé realmente cuál es el nombre para este patrón, pero estoy seguro de que se ganó uno.

Esto tiene una ventaja obvia de la velocidad. En términos de mantener un registro de las operaciones que introdujeron cada uno de esos cambios, podría usar una tabla separada, posiblemente con algunos enlaces a los registros antes y después del cambio.

+0

Tendría que contaminar todas las tablas que tengo con versiones anteriores - Usuario, Artículo, Transacción, Reloj, etc. Y no resuelve mi problema de cómo mostrar al usuario un buen registro como un ejemplo. –

2

Puede usar el patrón de comando. Si los agregas a una pila, tienes tu historial.

Cada comando tiene toda la información necesaria para llevar a cabo su tarea. Esto fuera de curso significa que cada comando está disctinct y es bastante difícil almacenarlos y consultarlos para una vista de usuarios específicos (porque el usuario necesita ver información de comandos invocados por otros (como 15:00 El elemento observado "Silmarillion" se ha caído) . precio de 15 a 12,50 euros)

puede representar el comando de la siguiente en la base de datos:

Command 
------- 
id 
name 
timestamp 
user 

CommandParameters 
----------------- 
commandId 
name 
value 

Ahora usted puede construir una consulta que muestra todos los comandos relevantes para un usuario o un artículo específico el usuario tiene en su lista de vigilancia (puede agregar una tabla que contiene todos los comandos relevantes para un usuario y artículo)

HistoryBuilder 
-------------- 
viewName 
commandName 
filterField 

Cuando el usuario para obtener todos los comandos que pueden ser ejecutados por los usuarios finales y para los productos que se obtiene todos los comandos que están relacionados con elementos como cambios actualizaciones de precios de acciones, etc.

Ahora se puede proporcionar adaptadores para hacer mensajes más amigables para el usuario de esos comandos. De esta forma, puede usar los mismos comandos en otros contextos con otro adaptador encima.

Espero que esto te lleve más lejos.

+0

Eso es cierto en general, esa es mi tercera proposición. Pero es difícil mantener claves externas a diferentes entidades. ¿Logró implementar el patrón de comando en un contexto similar? –

+0

He actualizado mi respuesta – Glenner003

+0

El patrón de comando se ajusta bien Me gustan sus ideas sobre JSON y CommandParameters. Gracias por la actualización! –