Para un ORM que respalde la validación de datos, ¿deberían imponerse también restricciones en la base de datos?

13

Siempre he aplicado restricciones a nivel de base de datos además de mis modelos (ActiveRecord). Pero me he estado preguntando si esto es realmente necesario.

Un poco de historia

Recientemente tuve que probar un método básico de generación automática de marca de tiempo para un modelo. Normalmente, la prueba crearía una instancia del modelo y la guardaría sin validación. Pero hay otros campos obligatorios que no son anulables en la definición de la tabla, lo que significa que no puedo guardar la instancia incluso si omito la validación de ActiveRecord. Entonces, ¿estoy pensando si debería eliminar tales restricciones del db en sí mismo y dejar que el ORM las maneje?

Posibles ventajas si omito las restricciones en db, imo -

  • Puede modificar una regla de validación en el modelo, sin tener que migrar la base de datos.
  • Puede omitir la validación en las pruebas.

Posible desventaja?

Si es posible que la validación de ORM falle o se omita, la base de datos no verifica las restricciones.

¿Qué piensas?

EDITAR En este caso, estoy usando el Marco Yii , que genera el modelo de la base de datos, por lo tanto, las reglas de la base de datos también se generan (aunque siempre podría escribirlas también después de la generación).

n / A
fuente
3
Si los datos en su base de datos pueden modificarse rutinariamente sin usar su ORM (otras aplicaciones sin su ORM, o, peor aún, el acceso directo a la base de datos por parte de los usuarios), la validación realmente debe estar en la base de datos.
Marjan Venema

Respuestas:

16

Su principio rector debe ser No se repita :

En ingeniería de software, Don't Repeat Yourself (DRY) es un principio de desarrollo de software destinado a reducir la repetición de información de todo tipo, especialmente útil en arquitecturas de niveles múltiples. El principio DRY se establece como "Todo conocimiento debe tener una representación autoritaria, inequívoca y única dentro de un sistema".

El ORM es esencialmente una capa adicional (o nivel, si lo prefiere), que se sienta cómodamente entre su aplicación y su (s) almacenamiento (s) de datos. Sus restricciones deben estar en un solo lugar, y solo en un lugar, ya sea el ORM o el almacenamiento de datos, de lo contrario, pronto terminará manteniendo diferentes versiones de ellos. Usted realmente no quiere hacer eso.

Sin embargo, en la práctica, la mayoría de los ORM medio decentes generan automáticamente una gran cantidad de sus modelos a partir de su esquema de datos. Aunque todavía hay duplicación, las posibilidades de infierno de mantenimiento son mínimas ya que el código ORM duplicado se genera siguiendo el mismo patrón cada vez. Sería ideal no tener código duplicado, pero las restricciones generadas automáticamente son la mejor opción.

Además, tener sus restricciones en un lugar no significa necesariamente que deba tener todas sus restricciones en el mismo lugar. Algunos, como las restricciones de integridad referencial, pueden ser más adecuados para el almacenamiento de datos (pero pueden perderse si se muda a otro almacenamiento de datos), y algunos, principalmente aquellos relacionados con la lógica empresarial compleja, son más adecuados para su ORM. Sería preferible tener todas las manzanas en la misma canasta, pero ...

Fallas

Mencionas la falla de ORM. Eso es absolutamente irrelevante para su pregunta, su aplicación debe pensar en el ORM y el almacenamiento de datos como una entidad única. Si falla, falla, omitir el ORM para hablar directamente con el almacenamiento de datos no es una buena idea.

Omitir el ORM para cualquier otra cosa

Tampoco es una buena idea. Sin embargo, puede suceder por una variedad de razones:

  1. Partes heredadas de la aplicación que se crearon antes de que se introdujera el ORM.

    Esa es una pregunta difícil, y exactamente la situación con la que estoy lidiando en este momento , de ahí mi constante repetición de "infierno de mantenimiento". O sigue manteniendo las partes que no son ORM, o las reescribe para usar el ORM. La segunda opción podría tener más sentido inicialmente, pero es una decisión que se basa únicamente en lo que están haciendo exactamente esas partes de su aplicación y qué tan valiosa sería una reescritura completa a largo plazo.

    Intente cambiar una clave en una tabla MySQL de 2 * 10 ^ 8 filas mal diseñada (sin tiempo de inactividad) y comprenderá de dónde vengo.

  2. Partes no heredadas de la aplicación que deben comunicarse directamente con el almacenamiento de datos:

    Aún más complicado. Los ORM son herramientas sofisticadas y se encargan de casi todo, pero a veces se interponen o incluso son absolutamente inútiles. La palabra de moda (frase de moda en realidad) es la falta de coincidencia de impedancia relacional del objeto , simplemente no es técnicamente posible que su ORM haga todo lo que hace su base de datos relacional, y para algunas de las cosas que hacen, hay una penalización de rendimiento significativa.

Comentarios

Desde el punto de vista de la integridad de los datos, las restricciones DEBEN estar en la base de datos y DEBEN estar en la aplicación. ¿Qué sucede si se accede a su aplicación desde una aplicación web y de escritorio, o desde una aplicación móvil o un servicio web? - Luiz Damim

Aquí es donde agregar una capa adicional sería extremadamente útil, y si estamos hablando de una aplicación web, iría con una API REST. Un diseño demasiado simplista para esto sería:

ingrese la descripción de la imagen aquí

El ORM se ubicaría entre la API y el almacenamiento de datos, y todo lo que esté detrás de la API (incluida) se consideraría una entidad única de las diversas aplicaciones.

Yannis
fuente
Normalmente, definiría un esquema en su ORM que luego se reflejaría en la base de datos para tener un segundo nivel de seguridad.
Josh K
2
@JoshK Dices segundo nivel de seguridad, digo mantenimiento infierno. Sin embargo, no digo que no estés en lo cierto ...
Yannis
Tiene sentido. Estoy siguiendo esta ruta ahora. ¡Gracias!
na
1
Una vez que pasa el punto donde uno o dos desarrolladores están haciendo código y trabajo en la base de datos, se convierte en un mal necesario. Si usa un buen ORM, también generará migraciones para usted. Cuando creces hasta tener un DBA dedicado, no hay forma de evitarlo, no permitirán que las tablas floten sin restricciones. Una forma sencilla de evitar que las personas se registren sin un correo electrónico es imponer una restricción de nivel de almacenamiento.
Josh K
1
Desde el punto de vista de la integridad de los datos, las restricciones DEBEN estar en la base de datos y DEBEN estar en la aplicación. ¿Qué sucede si se accede a su aplicación desde una aplicación web y de escritorio, o desde una aplicación móvil o un servicio web?
Luiz Damim
20

En realidad, esta es una pregunta muy difícil de responder y he encontrado que es un tema muy controvertido.

Como Yannis Rizos señaló en su respuesta, tener la lógica de restricción tanto en la base de datos como en la capa ORM parecería violar DRY, lo que "puede conducir a pesadillas de mantenimiento, factoring pobre y contradicciones lógicas".

Sin embargo, eliminar la lógica de restricción de la base de datos y mantenerla solo en la capa ORM no funcionaría si tiene alguna de las siguientes condiciones:

  1. Actualizaciones manuales de la base de datos (parecen suceder en todas las empresas)

  2. Actualizaciones de bases de datos de otro sistema que no siempre puede compartir fácilmente la lógica de restricción de ORM (por ejemplo, un script de Perl que realiza tareas de rutina cuando la capa de ORM se implementa en Hibernate y la utiliza una aplicación Java para la actividad diaria)

Esto sugeriría que solo agregue la lógica de restricción a la base de datos y la elimine de su capa ORM para evitar una violación de DRY. Sin embargo, esto puede conducir a casos en los que el código de la aplicación no puede capturar con éxito el problema real y retransmitirlo al usuario (aunque como desarrollador puede depurar el problema, lo más probable es que pueda). Esto puede no ser aceptable para algunos proyectos.

Su última opción es automatizar la creación de las restricciones en el ORM (y en cualquier otro sistema) a partir de las restricciones de la base de datos (o, en realidad ... viceversa). Aunque eventualmente terminará con dos o más implementaciones de las restricciones, no será una violación del principio DRY como se describe en "El programador pragmático", ya que recomiendan la utilización de la generación de código para evitar violaciones DRY. Por supuesto, no es tan simple porque, por ejemplo, cada cambio en una restricción de DB puede forzar una reconstrucción y una implementación de todas las aplicaciones que la usan (no es trivial para automatizar).

Realmente, tendría que ser evaluado caso por caso . Puedo decirle que, hasta este punto, me he encontrado con miradas en blanco cuando sugiero que la lógica de restricción no se repita.

smp7d
fuente
2
Acabo de salir del trabajo y estaba pensando en expandir mi respuesta para que sea más o menos lo que acabas de publicar. ¡Buena respuesta!
Yannis
3

Definitivamente agregaría restricciones a la base de datos como mi opción predeterminada. Esto se debe a que para una empresa los datos son lo más importante y la calidad de los datos es fundamental. @Yannis Rizos trajo el principio DRY a la discusión. Bueno, otro principio es la defensa en profundidad. Para los datos, usaría este principio.

He trabajado en empresas reales donde el DB tiene datos creados hace 30 años. Se accedió y se sigue accediendo por la aplicación COBOL y ahora por una aplicación .Net. En 10 años puede ser una aplicación de proveedor, quién sabe. Hubo una fusión y millones de filas de datos se convirtieron y migraron de la otra compañía a esta base de datos usando SQL. Ningún ORM puede hacer esto. La conclusión es que los datos permanecen, las aplicaciones cambian, la forma en que los datos se generan cambia. Entonces, ¿por qué no reducir la posibilidad de corrupción de datos?

softveda
fuente
2

Creo que haces las dos cosas hasta cierto punto.

  • Las restricciones principales deben vivir en el ORM: los lenguajes de programación son mucho más flexibles, es más fácil de probar y ajustar cuando los requisitos cambian; No hay que preocuparse por las correcciones DDL al menos. Y generalmente evita problemas de regresión de datos difíciles de probar.

  • Algunas restricciones muy duras y rápidas también deberían vivir en la base de datos. No estoy hablando de nombres no anulables, por ejemplo. Estoy hablando de cosas como la integridad referencial o que requieren algunos identificadores absolutamente cruciales. Requisitos estructurales para que su código no tenga que tratar con "qué pasa si el Pedido tiene un producto inexistente".

Wyatt Barnett
fuente
1

La base de datos es IMO, el único lugar donde se puede violar DRY, porque si algo pasa por alto su ORM y tiene datos incorrectos, eso es todo. Juego terminado. Tener datos corruptos es el golpe mortal.

Wayne Molina
fuente
Solo base de datos? Puedo pensar en muchos casos en los que el comportamiento asociado con los datos debería existir en varias capas (lógicas o físicas) incluso si los datos no persisten en absoluto. A veces es posible tener un único código fuente y reducir la "duplicación" a los dll implementados.
mike30