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

13

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

Un poco de fondo

Hace poco tuve que probar por unidad un método de generación de marca de tiempo automatizado básico para un modelo. Normalmente, la prueba creará una instancia del modelo y la guardará sin validación. Pero hay otros campos obligatorios que no se pueden anular 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 debo eliminar esas restricciones de la propia db y dejar que ORM las maneje?

Posibles ventajas si omito 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, sin embargo, la base de datos no verifica las restricciones.

¿Qué piensas?

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

    
pregunta Bojack 21.06.2012 - 07:30

5 respuestas

16

Su principio guía 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 varios niveles. El principio DRY se establece como "Todo conocimiento debe tener una representación autoritaria única e inequívoca dentro de un sistema".

El ORM es esencialmente una capa adicional (o nivel si lo prefiere), que se encuentra 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 mantendrá diferentes versiones de ellos. realmente no quieres 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 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 que necesariamente significa que debe tener todas sus restricciones en el mismo lugar. Algunas, como las restricciones de integridad referencial, pueden ser más adecuadas para el almacenamiento de datos (pero pueden perderse si se muda a otro almacenamiento de datos), y algunas, principalmente aquellas que tienen que ver con lógica de negocios compleja, son más adecuadas para su ORM. Sería preferible tener todas tus manzanas en la misma canasta, pero ...

Failures

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

Omisión del 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 compilaron antes de la introducción del ORM.

    Es una situación difícil, y exactamente la situación con la que estoy lidiando con ahora mismo , por lo tanto, repito constantemente el "infierno de mantenimiento". O mantienes el mantenimiento de las partes que no son ORM o las reescribes 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 hacen exactamente esas partes de su aplicación y en lo valioso que sería una reescritura completa a largo plazo.

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

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

    Aún más complicado. Los ORM son herramientas sofisticadas, y se ocupan de casi todo, pero a veces se interponen o incluso son absolutamente inútiles. La palabra de moda (buzzphrase realmente) es discrepancia de impedancia entre el objeto y la relación , simplemente no es técnicamente posible para su ORM todo lo hace su base de datos relacional, y para algunas de las cosas que hacen, hay una importante penalización en el rendimiento.

Comentarios

  

Desde el punto de integridad de los datos, las restricciones DEBEN estar en la base de datos, y DEBERÍAN estar en la aplicación. ¿Qué sucede si se accede a su aplicación desde una web y desde una aplicación de escritorio, 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:

  

El ORM se ubicaría entre la API y los almacenamientos de datos, y todo lo que se encuentra detrás de la API (incluida esta) se consideraría una entidad única de las distintas aplicaciones.

    
respondido por el yannis 21.06.2012 - 07:37
20

Esta es realmente una pregunta muy difícil de responder y me parece que es un tema muy controvertido.

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

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

  1. Actualizaciones manuales de DB (parecen ocurrir en todas las compañías)

  2. Actualizaciones de DB desde otro sistema que no siempre puede compartir el ORM lógica de restricción fácilmente (ex / un script Perl que realiza tareas rutinarias cuando la capa ORM se implementa en hibernación y es utilizada por un Java aplicación para la actividad del día a día)

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 infracción DRY. Sin embargo, esto puede llevar a casos en los que el código de la aplicación no pueda capturar con éxito el problema real y retransmitirlo al usuario (aunque como desarrollador que está depurando el problema, lo más probable es que pueda hacerlo). 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, realmente ... 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 las violaciones DRY. Por supuesto, no es tan simple porque, por ejemplo, cada cambio a una restricción de base de datos puede forzar una reconstrucción y un despliegue de todas las aplicaciones que lo utilizan (no es trivial para automatizar).

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

    
respondido por el smp7d 21.06.2012 - 15:24
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 importantes y la calidad de los datos es primordial. @Yannis Rizos trajo el principio DRY a la discusión. Bueno, otro principio es la defensa en profundidad. Para los datos yo usaría este principio.

He trabajado en empresas reales donde el DB tiene datos creados hace 30 años. Se accedió y aún se accede a él mediante la aplicación COBOL y ahora mediante 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 utilizando SQL. Ningún ORM puede hacer esto. La conclusión es que los datos permanecen, las aplicaciones cambian, la forma en que se generan los datos cambia. Entonces, ¿por qué no reducir la posibilidad de corrupción de datos?

    
respondido por el softveda 22.06.2012 - 11:37
2

Creo que haces ambas cosas hasta cierto punto.

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

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

respondido por el Wyatt Barnett 21.06.2012 - 19:42
1

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

    
respondido por el Wayne Molina 22.06.2012 - 04:50

Lea otras preguntas en las etiquetas