database-design - caracteristicas - mongodb español
¿Debe hacer cumplir las restricciones a nivel de base de datos, así como el nivel de aplicación? (15)
A pesar de que a los DBA les encanta garantizar la validación en el nivel de la base de datos, no es práctico: debe validar datos en JavaScript y, a menudo, en el lado del cliente, para ser Web 2.0 o superior.
Incluso si valida todo al crear restricciones, ¿cómo va a mostrar al usuario sus errores de validación? Como respuestas del motor de DB subyacente? Incluso para dar soporte a las respuestas de la API, es una buena idea asignar esas respuestas a algo más significativo en términos de API. Devuelve "Acceso denegado" en lugar de "Registro no encontrado".
Asuma los 3 lados: Cliente, API y DB. Implementar Client porque es necesario para una gran UX y una carga decreciente en el servidor. Hizo que DB fuera segundo solo para mantener todos los datos limitados. Implementar la validación API (del lado del servidor) para hacer que todos los mensajes sean distinguibles por los usuarios de la API (Descargo de responsabilidad: No soy miembro de relaciones públicas de la comunidad, pero incluso es una buena idea usar el servidor Node.js, de esa forma puedes reutilizar tu lado del cliente código de validación).
He estado leyendo el libro "Enterprise Rails" de Dan Chak y me hizo pensar: ¿Sientes que deberías tener limitaciones de datos tanto a nivel de la base de datos como a nivel de aplicación? ¿O te sientes similar a los marcos obstinados como Ruby on Rails? La base de datos es solo un "depósito tonto" de datos, y todos los controles deben hacerse en tu aplicación (no estoy tratando de señalar a RoR aquí - Soy un gran fan de Rails, pero estoy en desacuerdo con su enfoque de la base de datos)?
Personalmente, creo que debe tenerlos a ambos para asegurarse de que su base de datos y su aplicación estén bien protegidos. Lo que quiero decir es que debe hacer uso de restricciones no nulas, dar a los campos una longitud si se conoce (en lugar de dejarlos todos en nvarchar (255) ), tener cosas como claves externas , verificar restricciones y desencadenantes en su base de datos , y luego también hacer cumplir esto a través de reglas de lógica de negocios en su aplicación. IMO esto hace que su aplicación sea robusta a través de su interfaz de usuario y también segura contra alguien que pueda tener acceso directo a la base de datos.
El contraargumento que más a menudo veo es que requiere lo que equivale a duplicar la lógica; una vez en el nivel de la base de datos, y una vez en el nivel de la aplicación, supongamos que tiene una restricción de verificación para verificar que se ingrese la SKU de un producto (es decir, su longitud es mayor que cero).
Ahora necesitaría incluir también métodos de validación en su lógica comercial para asegurarse de que el valor que el usuario ingresó tenga una longitud mayor que cero, y también posiblemente algún Javascript del lado del cliente para detectar el error a medida que el usuario escribe los datos.
Por mi parte, no veo esto como algo malo, sí, tienes cierta lógica duplicada, pero el resultado final es la mentalidad de "base de datos como fortaleza", ya que si lo piensas, tus datos son la parte más importante de tu aplicación; después de todo, ¿de qué sirve su nueva y brillante aplicación Web 2.0 si los datos se corrompen y ponen en peligro fácilmente?
¿Cuáles son sus pensamientos sobre esto? ¿Debería la base de datos ser una fortaleza impenetrable como Fort Knox, o una caja fuerte abierta que esté protegida por rayos láser? En otras palabras, ¿debería sacrificar alguna duplicación de la lógica para garantizar un modelo de datos seguro, o dejar todo a su aplicación y usar la base de datos simplemente para almacenar datos?
Creo que deberías tratar de proteger tus datos a toda costa. No hay nada peor que tratar de informar sobre una aplicación que tenía datos incorrectos porque la aplicación tenía un error. Ahora, que significa esto?
Debe hacer cumplir sus relaciones a través de FK, no hay ninguna razón para no hacerlo. Debería tratar de evitar los valores nulos y solo usarlos cuando los valores nulos sean apropiados. Sin embargo, creo que hay una línea muy fina.
¿Deberías analizar un número de teléfono para asegurarte de que está en el formato correcto? Probablemente no, pero de nuevo probablemente deba almacenar el número de teléfono en un esquema que no tenga un problema de formato.
Depende.
Si está creando una base de datos que se integrará en una única aplicación que también está creando, puede optar por poner la validación de datos en el DBMS o la aplicación, o en ambos. Casi todas las bases de datos que están construyendo los programadores experimentados que son novatos de bases de datos se ajustan a esta categoría. En este caso, algunas de las otras respuestas responden a su pregunta.
Sin embargo, si está creando una base de datos destinada a almacenar datos recibidos de múltiples aplicaciones, y la programación de algunas de esas aplicaciones está fuera de su control, entonces tiene que construir el DBMS para estar a la defensiva y no permitir que se ingresen datos incorrectos. una aplicación rota para infectar los datos que sirve a otras aplicaciones y usuarios interactivos. No puede detectar todos los errores, pero puede atrapar muchos de ellos.
Como mínimo, debe diseñar sus tablas para que tengan al menos una clave principal posible (las claves principales posibles se denominan claves candidatas). Debe elegir una clave principal de las claves candidatas y declararla como una restricción de clave principal. Esto refuerza la integridad de la entidad.
Además, debe declarar una restricción de "referencias" para cada clave externa. Esto impone la integridad referencial. Con un DBMS decente, debería poder imponer la integridad referencial incluso cuando la clave foránea sea opcional, en otras palabras, podría ser NULL. Los NULL por supuesto no se refieren a nada.
No tiene sentido mover estos dos tipos de validación a la aplicación. La aplicación tiene que realizar un viaje de ida y vuelta a la base de datos para detectar violaciones a la regla.
La idea de que la lógica de negocios no debería estar en la base de datos es, en mi opinión, un malentendido sobre de qué se tratan las bases de datos. De nuevo, si su base de datos está integrada en una sola aplicación, entonces se adecúe a usted mismo.
En cuanto a las reglas de validación que prohíben los valores perdidos (NULLS), no hay daño al implementarlas tanto en la aplicación como en la base de datos. En muchos casos, eso es lo correcto. De manera similar con controles de rango.
Para proyectos muy grandes, necesita un documento separado para delinear todas las reglas comerciales sobre datos. Este documento debe indicar dónde se aplican las reglas, en la base de datos, en la (s) aplicación (es) o en ambas.
Desde una perspectiva de OOP, la base de datos como en Object / Actor, dentro del sistema más grande y debería ser responsable de sí misma. Eso incluye la necesidad necesaria para validar la entrada.
En resumen: la base de datos debería imponer restricciones.
Por qué :
- Más fácil. Por ej. para tener un conjunto de restricciones en una columna de datos en particular, solo hay un lugar para establecerlo: la columna misma. Los datos pueden provenir de diversas fuentes, pero el control se coloca donde los datos finalmente se ponen a descansar.
- Integridad. La base de datos debe ser responsable de los datos que aloja. Una base de datos inconsistente es tan buena como ninguna base de datos.
- Flexibilidad. Nuevos entornos de desarrollo de interfaz de usuario vienen con demasiada frecuencia. Si la base de datos se levanta para decir que se ocupará de las limitaciones, el desarrollo del front-end y las pruebas funcionales son más fáciles.
Es mejor aplicar estas restricciones en el nivel de la base de datos, ya que son más eficientes (implementadas en C). Está bien duplicar la validación en otra capa, ya que proporciona mensajes de validación y error más fáciles de usar.
No es una proposición XOR, es mejor errar por el lado seguro, hacer cumplir estas restricciones en la base de datos haría que su sistema sea más duradero.
Estoy de acuerdo en que la respuesta a esta pregunta depende del entorno.
En mi entorno actual, solo hay dos desarrolladores y menos de mil usuarios de nuestra aplicación. Si puede asegurarse de que sus prácticas de programación incluyan requisitos para implementar la lógica empresarial en la capa de aplicación, entonces podrá manejar las restricciones fuera de la base de datos.
Si tiene una aplicación que necesita escalar bien y que eventualmente será mantenida por un gran grupo de desarrolladores y utilizada por un número incalculable de usuarios que posiblemente implementen restricciones de datos en la base de datos, puede mejorar la eficiencia así como eliminar posibles desastres por cambios en el capa de aplicación.
Mi preferencia personal es imponer la validación básica en la capa de la base de datos y luego usar técnicas de introspección para eliminar esas restricciones hasta la capa de la aplicación por defecto (convención sobre la configuración). Si tengo alguna interacción del usuario en un formulario o similar que es inusual, anularé los valores predeterminados que obtuve de la base de datos con el nuevo comportamiento que necesite. Esto me ayuda a mantener la mayoría de la validación básica principalmente DRY-ly en la capa de la base de datos, mientras hago una validación más compleja (es decir, el formato del número de teléfono) en la capa de la aplicación.
Podría verificar restricciones para cosas como números de teléfono, pero encuentro que las restricciones de verificación son una forma difícil y frustrante de aplicar formatos.
Si tuviera una aplicación que necesitaba recibir información de una segunda fuente (es decir, tenía tanto una interfaz web como un cliente de escritorio), o bien intentaría que la segunda interfaz funcionara con la primera (enviando datos de escritorio a través del servicio web para ejemplo) o al fallar eso, entonces recurriría a una restricción de verificación en la base de datos además de la validación en la capa de aplicación.
Antes que nada quiero mantener la integridad de los datos tanto como sea posible, porque los datos malos inevitablemente causarán estragos en la aplicación, y además (y realmente igualmente importantes) quiero que la aplicación pueda manejar la validación de la información proporcionada por el usuario. .
Para ofrecer una perspectiva ligeramente diferente, creo que depende del contexto.
En primer lugar, a lo largo de los años he pasado de estar 100% convencido de implementar restricciones en el DBMS a tratar de evitarlo del todo: quiero que toda mi lógica comercial esté en la misma capa.
En segundo lugar, estoy trabajando mucho con Rails y las migraciones de ActiveRecord no permiten mucha definición de restricción residente de db más allá del tamaño de campo y NULL_ness.
Si está construyendo una nueva aplicación que incluye una nueva base de datos que está completamente dedicada a su aplicación, entonces puede aplicar sus restricciones en el código de su aplicación como parte de su lógica comercial. Así es como a Rails le gusta trabajar y parece funcionar bastante bien.
Si está compilando una nueva aplicación con una base de datos heredada que implementa las reglas de negocio en las restricciones de base de datos, le sugiero que continúe con eso y acepte la duplicación de las reglas de validación en la capa de negocio. Es mejor verificar que los datos sean válidos antes de intentar aplicarlos a la base de datos.
Si está creando una nueva aplicación / base de datos con la expectativa de que otras aplicaciones tengan acceso a los datos, entonces el enfoque dependerá de cómo se construirán esas otras aplicaciones. De nuevo, en Rails, probablemente debería buscar maneras de compartir sus modelos, en cuyo caso esa capa debería ser suficiente. Si no puede negar a otros estilos de implementación el acceso directo a sus datos, entonces está de vuelta a la duplicación. Mi preferencia sería intentar, muy difícil, denegar el acceso directo a bases de datos a esas aplicaciones y esforzarme por brindarles servicios a través de un servicio web (con suerte RESTful), para que pueda administrar la integridad de los datos en el nivel lógico de la empresa.
Si una aplicación de terceros (interna o de otro tipo) tiene acceso DDL a tu esquema, entonces deja de preocuparte por el problema: ¡ya has perdido el control de tus datos y estás jodido!
Por lo general, siempre hay algo de duplicación, y las bases de datos no son solo depósitos mudos.
db
La base de datos garantiza la integridad en un nivel de datos. Las restricciones de clave externa, las restricciones no nulas y las restricciones de tamaño están cubiertas fundamentalmente por la base de datos.
No puedes hacer todo en el DB, pero puedes hacer mucho. Protege los datos.
capa de negocios
Al subir de nivel, tienes la lógica de negocios. Normalmente, este es su punto de integración con otras aplicaciones (servicio web, su propia interfaz de usuario, etc.). Aquí la lógica de negocio está codificada en la aplicación. Cosas como si un producto tiene una fecha de finalización de x, entonces tampoco puede ocurrir en y, si y tiene una fecha de finalización diferente.
Sería difícil describir ese tipo de regla en la base de datos, por lo que no es así. Pero su capa de lógica de negocios aún intercepta cosas que sabe que no son válidas. por ejemplo, si no se permite que el campo de descripción sea nulo, la lógica comercial nunca debe enviarlo a la base de datos. Error, independientemente, pero intenta interceptar las cosas en el punto en que se sabe que son malas.
también es difícil expresar en una base de datos otras ''reglas'' como ''los nuevos usuarios tienen una fecha de caducidad de 1 año si son de Arkensas, 2 años si no, a menos que tengan 3 hijos y uno de ellos se llame Barry''. Podemos reírnos de este ejemplo, pero un programador avezado le dirá que la lógica comercial es uno de los mayores oxímoros que existen.
ui
Al pasar a la interfaz de usuario, la interfaz de usuario también codifica regularmente la lógica empresarial en pantallas. Los formularios y otras páginas a menudo existen en un estado no válido, y el trabajo de la interfaz de usuario es conocer las reglas al menos la mayor parte del tiempo. Es de esperar que la UI difiera la lógica de la capa de negocios, pero la capa de negocios no tiene la menor idea de que el campo 1 es la fecha de vencimiento y el campo 2 es la descripción.
La IU sabe buscar productos con X si el usuario ya ha seleccionado el widget Y. La IU sabe que se requiere descripción, y que el recuento de elementos es> 0 y <100 (en estos ejemplos, una buena IU dependerá de la capa empresarial para dígale, por ejemplo, el mínimo y el máximo, pero la IU todavía está al tanto de la relación)
En la interfaz de usuario web también agregamos script de cliente que nuevamente duplica la lógica en el código del servidor. Usamos el script del cliente para tener una mejor experiencia de usuario, pero al final no confiamos en nada que provenga del cliente (el script se puede desactivar, los campos de formulario se pueden manipular manualmente, etc.)
Entonces puedes ver que la lógica se duplicará. Intenta reducir la duplicación tanto como sea posible, pero, en realidad, rara vez es posible dado un programa no trivial.
Sí para ambos. Encontré esto en mi último lugar. Teníamos sistemas delphi heredados con bases de datos de sybase. El nuevo sistema era .NET y servidor Sql. Un empleado en particular era el único responsable de traducir la base de datos de sybase a la base de datos del servidor sql para los clientes que querían actualizaciones al nuevo sistema .NET. Nunca trabajó con el código de la aplicación .NET y, por lo tanto, nunca vio restricciones de datos a nivel de aplicación.
Como consecuencia, tuvo que confiar en la información que se le pasó y las limitaciones de datos a nivel de base de datos. Si las restricciones eran incorrectas o faltantes a nivel de la base de datos, generaba datos deficientes y llamadas de soporte de los clientes. Esto sucedió más veces de las que nos gustaría porque las restricciones de datos no siempre se replicaron desde el nivel de la aplicación hasta el nivel de la base de datos.
Sí, si desea restringir lo que entra en la base de datos. Las capas deben ser distintas entre sí tanto como sea posible y su base de datos no debe depender de otra capa que garantice que siga las reglas.
No hay garantía de que una capa de "lógica de negocios" defectuosa (o maliciosa) no inserte datos tóxicos en sus tablas. Por supuesto, si puedes confiar en las otras capas, probablemente no lo necesites. Pero trabajo en una tienda de mainframes donde los DBA siempre tienen que solucionar los problemas causados por los jóvenes whippersnappers de Java que despliegan su código buggy a producción sin pruebas adecuadas (¿alguna?) :-).
Las tablas de base de datos que se comparten entre diferentes áreas de desarrollo (y eso es todo para nosotros) siempre deben protegerse contra datos errantes. Cuando la aplicación A coloca datos dudosos en la tabla utilizada por la aplicación B, no son los desarrolladores de la aplicación A los que toman el control, sino los DBA.
Si está seguro de que nunca tendrá otra aplicación cliente, puede tratar la base de datos como un simple almacenamiento. Sin embargo, si alguna vez tiene más de una aplicación cliente, obviamente tendrá que replicar las restricciones en todas las aplicaciones cliente, lo cual es una mala idea. Recuerde que otros clientes incluyen herramientas de desarrollador.
Además, al usar la base de datos como un "repositorio tonto", lo más probable es que termine con una aplicación menos eficiente. La base de datos puede hacer muchas cosas mucho más eficientemente de lo que tu aplicación puede hacerlo. POr qué no tomar ventaja de eso?
Si no aplica al menos la integridad básica en la base de datos, en algún momento entrarán datos no válidos. Tal vez desde una aplicación. error, tal vez de alguien que tira de la consola SQL, lo que sea. Y luego descubres que tu aplicación tiene modos de falla interesantes cuando ocurre lo imposible ("todos los registros B deben tener un registro A, ¿qué quieres decir con que no existe?").
La aplicación de la integridad en la aplicación solo funciona si la aplicación es lo único que tocará esa base de datos. Aun así, será mejor que tenga cuidado con los errores de la aplicación, que son más fáciles, ya que la aplicación es mucho más grande que el esquema.
Si sigues la escuela Jeff Atwood de una base de datos es solo un tonto sistema de almacenamiento y recuperación de datos, entonces pondrías toda la validación en la capa de aplicación.
Sin embargo, encuentro que las aplicaciones son como niños pequeños. Si no se controlan, arrojarán todo por la habitación. Dependerá de los padres limpiar el desorden. En este caso, serán los DBA quienes realicen la limpieza.
Sin embargo, creo que debe tener cuidado con el uso de cada característica de integridad de datos de la base de datos, simplemente porque está allí. La sobrecarga de su base de datos con restricciones de clave externa y disparadores puede crear más problemas de los que cree. Tiendo a usar claves externas solo en tablas que están muy relacionadas, como un par de encabezado / tabla de detalles. Si comienza a agregar claves externas en cualquier lugar, puede terminar con una base de datos no interactiva.
Raramente uso disparadores. Creo que hacen una base de datos muy opaca. Usted emite un simple comando update / insert / delete y pueden ocurrir cosas extrañas. Supongo que hay dos lugares donde los factores desencadenantes son inevitables:
Cuando no tiene un código fuente para la aplicación que escribe en la base de datos y necesita modificar el comportamiento. Los desencadenantes son su única opción.
Si está realizando operaciones CRUD en una vista. Los disparadores son obligatorios para las operaciones de inserción / actualización / eliminación.
Tiendo a realizar una validación básica en la aplicación. De esta forma, el usuario recibe retroalimentación inmediata de que algo está mal. La validación compleja que requiere buscar tablas relacionadas probablemente se realice mejor en la base de datos (así como la validación simple que hace la aplicación). Yo argumentaría que algunas formas de validación son casi imposibles de garantizar a nivel de aplicación, sin usar complicadas estrategias de bloqueo.
Si tiene varias aplicaciones, posiblemente escritas en diferentes idiomas en diferentes plataformas, entonces se fortalece el caso para poner más de la validación en la capa de la base de datos. La probabilidad de que dos o más aplicaciones, escritas por diferentes programadores, realicen validación idéntica es bastante remota. Mejor hazlo en un solo lugar.
Jeff Atwoods de este mundo sugeriría que escribas un servicio web con el que todas las aplicaciones se comuniquen. El servicio web realiza la validación de datos. Hacer esto permite que la base de datos siga siendo un contenedor de almacenamiento tonto, lo que le permite cambiar los motores de base de datos. En realidad, rara vez cambias los motores de base de datos (¡a menos que hayas comenzado con Microsoft Access!). Si está escribiendo servicios web exclusivamente para centralizar su validación de datos, entonces creo que se está excediendo.