¿Hay ejemplos de enfoques no CRUD?

14

Soy programador pero también he trabajado como archivero. Como archivero, se trata mucho de mantener los datos.

A menudo me pongo en discusiones con colegas cuando se trata de operaciones sobre datos. No me gusta demasiado la U y la D en CRUD. En lugar de actualizar un registro, prefiero agregar uno nuevo y tener una referencia al registro anterior. De esa manera construyes un historial de cambios. Tampoco me gusta eliminar registros, sino marcarlos como inactivos.

¿Hay un término para esto? ¿Básicamente solo creando y leyendo datos? ¿Hay ejemplos de este enfoque?

Pieter B
fuente
1
Is there a term for this? Basically only creating and reading data?Claro que sí: CR; P
yannis
77
Desde el punto de vista del usuario, eso sigue siendo CRUDO. No conozco ninguna etiqueta específica para ese estilo de implementación, pero creo que es común en MUCHAS aplicaciones. (Stack Exchange es un buen ejemplo ...)
Mark E. Haase
Es posible que desee ver una charla llamada The Impedance Mismatch is Our Fault .
Anton Barkovsky
+1 En algún momento, alguien querrá informes y es muy difícil crear informes sobre datos que no existen porque se "actualizaron" fuera de existencia. Encuentro su enfoque muy avanzado.
Chuck Conway el
2
También es posible que desee ver una charla sobre Datomic: infoq.com/presentations/The-Design-of-Datomic
Marjan Venema

Respuestas:

16

Marcar un registro como eliminado se conoce como eliminación suave . Nunca escuché una frase alternativa para actualizar, pero supongo que es porque eliminas el registro antiguo y creas uno nuevo.

Cabe señalar, esta es una técnica controvertida. Ver enlaces: Con vs Pro .

pdr
fuente
11

Uno de los problemas para retener un historial de cambios es que satura la base de datos y puede aumentar drásticamente su tamaño (dependiendo de los patrones de uso). Por lo tanto, una buena idea sería almacenar la pista de auditoría en un lugar separado y mantener las tablas de aplicaciones reales pobladas solo con datos relevantes. Por lo tanto, cada vez que la aplicación realiza una operación CRUD, el cambio se registra en las tablas de auditoría y la operación CRUD se realiza en las tablas de la aplicación (sin eliminaciones suaves).

Al mantener la pista de auditoría separada, le brinda un almacenamiento de datos prístino para que su aplicación interactúe, mientras conserva el historial de cambios en caso de que lo necesite. Ahora también puede archivar el registro de auditoría por separado o incluso destruirlo, según los requisitos de su negocio.

Se cayó el sistema
fuente
3
Esta. Además, la integridad referencial se convierte en una pesadilla; no puede especificar una clave externa para "el único registro en esta tabla con esta clave no única que no está marcada como eliminada". Puede solucionarlo persistiendo los datos para la copia de un registro que está a punto de actualizarse en una tabla diferente, antes de actualizar esta "copia de trabajo" con los nuevos datos, pero aún tiene que lidiar con una gran cantidad de datos.
KeithS
5

EventSourcing suena como el patrón que puede estar buscando.

Tomemos un ejemplo usando un simple objeto "auto" del que nos gustaría hacer un seguimiento del color (pseudo código C # sigue).

public class Car {
  public string Color { get; set; }
  public Car() { this.Color = "Blue"; }
}

Con una implementación CRUD cuando actualizamos el color del automóvil, el color anterior se perdería.

MyCar.Color = "Red";
MyCar.Save();  // Persist the update to the database and lose the previous data

Esta pérdida de información me parece lo que más le gustaría evitar (de ahí la aversión por la actualización y eliminación de parte del patrón CRUD).

Si tuviéramos que reescribir la clase de automóvil para responder a los eventos al actualizar su cambio, podría verse así:

public class Car {
    public string Color { get; private set; } // Cannot be set from outside the class

    public void ApplyEvent(CarColorChangedEvent e) {
      this.Color = e.Color;
    }
}

Ahora, ¿cómo actualizaríamos el color de este objeto? ¡Podríamos crear un evento CarColorChanged !

var evnt = new CarColorChangedEvent("Red");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

¿Notó la falta de un guardado en el objeto modelo real? Esto se debe a que en lugar de persistir directamente en el modelo, persistimos los eventos que ponen el modelo en el estado actual. Estos eventos deberían ser inmutables .

Ahora avancemos y cambiemos el color varias veces más:

var evnt = new CarColorChangedEvent("Green");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

var evnt = new CarColorChangedEvent("Purple");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

Si tuviéramos que mirar nuestro almacenamiento de eventos (podría ser una base de datos de relaciones, basada en archivos, etc.) veríamos una serie de eventos relacionados con el objeto de nuestro automóvil:

CarColorChangedEvent => Red
CarColorChangedEvent => Green
CarColorChangedEvent => Purple

Si quisiéramos reconstruir ese objeto de automóvil, podríamos hacerlo simplemente creando un nuevo objeto de automóvil y aplicando los eventos de nuestro almacén de eventos a dicho objeto.

var MyCar = new Car();
var events = MyDatabase.SelectEventsForCar("CarIdentifierHere");
foreach(var e in events) {
  MyCar.ApplyEvent(e);
}
Console.WriteLine(MyCar.Color); // Purple

Con la secuencia de eventos, podemos retroceder el estado del automóvil a un período de tiempo anterior simplemente creando un nuevo objeto de automóvil y solo aplicamos los eventos que deseamos:

var MyCar = new Car();
var event = MyDatabase.GetFirstEventForCar("CarIdentifierHere");
MyCar.ApplyEvent(e);
Console.WriteLine(MyCar.Color); // Red
Miguel
fuente
5

Event Sourcing es el camino a seguir, y debe echar un vistazo a lo que Greg Young tiene que decir al respecto.

http://goodenoughsoftware.net/

También eche un vistazo a esta presentación en su Base de datos (Event Store). También puedes encontrar otros videos.

http://oredev.org/2012/sessions/a-deep-look-into-the-event-store

No elegiría la respuesta "eliminaciones suaves" a menos que necesite específicamente buscar elementos eliminados, pero no debería pensar en ellos como eliminados sino archivados. Creo que la terminología es bastante importante aquí.

Tampoco me gustaría mantener una "tabla de versiones". Todas las "tablas de versiones" que he visto (incluida la que estoy tratando de limpiar en este momento: 7 años de datos dañados debido a errores ... y no hay forma de recuperarlos a pesar de que tenemos datos históricos ... . porque eso es igual de corrupto) terminan corrompidos debido a errores en el código y al final todavía pierden datos porque nunca pueden volver y recrear los datos que la corrupción arruinó.

Con el modelo de abastecimiento de eventos, este no es el caso. Siempre puede reproducir exactamente lo que hizo el usuario. Esta es la diferencia muy importante entre CRUD y Event Sourcing. La arquitectura Event Sourcing guarda eventos en un almacén de eventos y no objetos de datos u objetos de modelo de dominio. Un evento podría impactar fácilmente en múltiples objetos. Solo piense en una solución de carrito de compras en la que convierta cada artículo del carrito de compras en un pedido real. Un evento afecta a todos los objetos del artículo, así como a los objetos del carrito de compras, que se transforma en un objeto de pedido.

Si mantuvo una copia versionada de cada fila en cada tabla de la base de datos, imagine el horror de tener que retroceder a una marca de tiempo específica, sin mencionar la increíble cantidad de espacio y la sobrecarga de rendimiento para mantener esa tabla de versiones.

Con Event Sourcing, puede rebobinar fácilmente, simplemente reproduciendo eventos hasta cierto punto en el tiempo. Se pueden implementar avances rápidos mediante el uso de instantáneas, pero todo es cuestión de implementación.

Pero la verdadera ventaja que creo que le gustará, ya que considera que está particularmente interesado en no perder datos, es que si descubre un error en el código que guarda estos datos, no necesita volver y limpiar los datos. (que a menudo es imposible porque los datos casi nunca están completos). En cambio, solo arregle el error y reproduzca todos los eventos. Entonces tendrá una base de datos con buenos datos correctos.

En caso de depuración, ¿con qué frecuencia le ha pedido al usuario que le diga qué hicieron ... por qué no simplemente reproducir lo que hicieron y luego pasar por el código! Bastante ingenioso eh.

Espero que esto ayude.

Jay Pete
fuente
2

No es precisamente su ejemplo, pero en sistemas financieros más antiguos tenía almacenamiento WORM . Si necesita "actualizar", escribió un nuevo registro y siempre se refirió al último registro como actual, pero ningún dato confirmado podría sobrescribirse.

Mucha gente llevó esa idea a sistemas posteriores. He escuchado lo que usted describe como tablas WORM, pero solo en esos círculos.

Cuenta
fuente
2

Sí, es bastante común en los sistemas empresariales, básicamente hay dos enfoques:

  • "bitemporal" en el que cada registro tiene una marca de tiempo válida y válida (el registro "actual" tiene una fecha válida de "para siempre" - nulo, "9999-12-31" o algún valor tan alto). Los registros nunca se eliminan, en cambio, la fecha "válido hasta" se establece en la hora actual y, en el caso de una actualización, se inserta un nuevo registro con una fecha válida desde la hora actual y una fecha válida para siempre.
  • "tabla de historial": cada vez que se modifica un registro, se arroja una copia del registro anterior en una tabla de historial / registro con una marca de tiempo para el evento.

Existen grandes variaciones en la granularidad para ambos enfoques. por ejemplo, si se cambia la cantidad de widgets en un artículo de pedido, ¿mantiene el historial de todo el pedido o solo ese artículo?

En general, "bitemporal" es mucho trabajo adicional y solo vale la pena si tiene muchos casos de uso como "el auditor obtiene el estado de la orden al 31 de diciembre".

James Anderson
fuente
-2

Básicamente, la basura no se puede completar sin estas 4 cosas. Crud significa crear, leer, actualizar y eliminar, por lo que cuando solo está tratando de leer datos, puede usar una consulta simple para eso, pero estas tres cosas están unidas a uno y otros conceptos simples de base de datos

Tayyab Vohra
fuente