¿La mejor manera de hacer referencia a datos de bases de datos estáticas en código?

24

Muchas aplicaciones incluyen 'datos estáticos': datos que realmente no cambian durante la vida útil de la aplicación. Por ejemplo, es posible que tenga una lista de Áreas de ventas que probablemente sea una lista fija en el futuro previsible.

No es raro encontrar estos datos estáticos en una tabla de base de datos (a menudo porque desea hacer referencia a ellos en las claves externas de otras tablas). Una tabla de ejemplo simple tendrá un Id para usar como clave principal y una Descripción. Por ejemplo, su tabla SalesArea tendrá (al menos) una columna SalesAreaId y una columna SalesAreaDescription.

Ahora, en el código, es posible que no desee tratar cada fila de la tabla de la misma manera. Por ejemplo, es posible que desee establecer un área de ventas predeterminada en algunas pantallas, proporcionar cifras diferentes para algunas áreas o restringir lo que los usuarios pueden hacer en otras áreas.

¿Cuál es la mejor manera de referirse a estos datos estáticos en el código? ¿Por qué?

  1. Codifique las descripciones en su código. Use esto para buscar el SalesAreaId de la base de datos cuando lo necesite.
  2. Codifique las identificaciones en su código. Use esto para buscar SalesAreaDescription cuando lo necesite.
  3. Agregue una columna a la tabla para cada propósito, por ejemplo, una columna "IsDefaultOnProductLaunchScreen" y así sucesivamente (podría haber muchos de estos).
  4. Algo más.

¿Hay alguna otra consideración especial que deba hacer al tratar con datos de base de datos estáticos? Por ejemplo, ¿darle a estas tablas un nombre especial?

Kramii reinstala a Monica
fuente
1
Posible duplicado: programmers.stackexchange.com/questions/304169/… Creo que las respuestas en ese (vinculado) llegan al corazón del problema un poco mejor IMO
JoeCool

Respuestas:

14

¿Qué tal cargarlos en un caché (generalmente implementado como una tabla hash) cuando se inicia la aplicación? Si lo hace, entonces ni siquiera tiene que consultar la base de datos (bueno, no más de una vez).

También sugeriría evitar codificar cualquier cosa. Agregue indicadores predeterminados (inicialmente en la tabla DB y también en la estructura de caché) para pantallas que necesitan valores predeterminados. Para realizar búsquedas en valores no predeterminados, intente almacenar las claves que se buscarán en un archivo de configuración o propiedades, si puede.

FrustratedWithFormsDesigner
fuente
El almacenamiento en caché es bueno, por supuesto, pero ¿cómo se actualizan estos valores? ¿Presumiblemente un reinicio de la aplicación, o algún tipo de estrategia de invalidación de caché?
Steve
1
@ Steve Sí, exactamente. Depende de la aplicación. Reiniciar es bueno para algo que comienza con frecuencia. Para una aplicación de larga ejecución, quizás recargue el caché una vez al día durante tiempos lentos. Mi pregunta sería, ¿qué pasa con un escenario donde la aplicación ejecuta muchos tiempos de vida muy cortos? Como, quizás un script PHP o algo similar.
tylermac
La base de datos ejecutará su propio caché para los datos a los que se accede con frecuencia, por lo que volverá a implementar algo que ya está implementado (¡y probablemente no tan bien!)
James Anderson
@JamesAnderson: El almacenamiento en caché en el medio de aplicación no sólo se tendrá siempre ser una llamada a la base de datos. Sí, las bases de datos tendrán sus propias memorias caché, pero éstas pueden ser invalidadas / actualizadas por eventos fuera del control de su aplicación, y aún debe tener una conexión a la base de datos y realizar una consulta para obtener esos datos (y esperar que estén en el caché de db). Realmente no es tan difícil implementar un simple caché en la aplicación.
FrustratedWithFormsDesigner
7

Una alternativa a la DB o la codificación rígida es usar un archivo de configuración leído en el momento del inicio. Luego puede almacenar estos datos en una estructura de solo lectura dentro de su código.

En el caso raro (pero no imposible) de editar estos datos, deberá reiniciar la aplicación. Si esto no es posible, puede escribir un administrador de configuración más complejo que verifique los cambios en el archivo de configuración cada vez que se acceda a los datos, esto en realidad es bastante eficiente, ya que solo necesita verificar una marca de tiempo en el archivo y luego invalidar todos los datos si el archivo se actualiza

Steve
fuente
1
Buena idea para algunos tipos de datos estáticos, pero no tan buena si desea imponer relaciones FK como se describe en la pregunta.
Kramii reinstala a Mónica
La pregunta no decía que esto era un requisito, solo un escenario. Si no es necesario, el enfoque del archivo de configuración funciona bien.
Steve
Tienes razón, no estaba lo suficientemente claro. Pero estoy contento ... porque he aprendido algo de tu respuesta. Nunca me he encontrado con este enfoque antes.
Kramii reinstala a Mónica
3

Si los datos se relacionan con datos existentes en su base de datos, probablemente sea tan eficiente agregarlos a la base de datos como agregarlos al código. Si no es así, generalmente estoy tentado a "tomar esa bala una vez" y ponerla en código hasta la primera vez que cambie.

A menudo, lo que creemos que será estático resulta que no lo es, y cuando eso suceda, no querrá tener que esperar a que se libere un código para que se realice un cambio. Tan pronto como eso suceda una vez, colóquelo en la base de datos y escriba una página de administrador para realizar más actualizaciones.

Para tomar su ejemplo, si ya tiene áreas de ventas en la base de datos, agregue una descripción allí, no cree una tabla hash para relacionar los datos de la base de datos con listas codificadas. Pero si no crea una tabla hash de áreas de ventas por todos los medios, pero esté listo, la primera vez que alguien cambie una descripción o agregue una nueva área de ventas, muévala a la base de datos.

pdr
fuente
"A menudo, lo que pensamos que será estático resulta no serlo", es cierto.
Kramii reinstala a Mónica
3

¿Por qué no simplemente codificar todo? El principal problema que siempre he tenido es hacer referencia a valores estáticos de la base de datos en el código de la aplicación. Una cosa es si está construyendo directamente una lista desplegable o algo fuera de los valores estáticos, pero ¿qué pasa si alguna lógica de la aplicación depende de los valores de la base de datos?

En una aplicación simple, actualmente tengo una lista de estados de edición para piezas de contenido: Borrador, Publicado, Archivado.

Los elementos de contenido deben tratarse de manera diferente según el estado en el que se encuentren. Si tuviera que mantener estos datos de estado en la base de datos, con los valores 1, 2, 3, respectivamente, ¿cómo haría para verificar si algo está en Borrador? ¿estado?

if (content.State == 1)
o
if (content.State == "Draft")?

¡Acabo de codificar los valores!
Lo mismo si usa una tabla de caché / hash: todavía tiene que usar algún valor escrito en su código como clave para buscar sus datos.

¿Cuáles son las desventajas del enfoque de codificación dura?

Dave
fuente
La desventaja es que, como dijo pdr, "a menudo lo que pensamos que será estático resulta que no lo es".
tylermac
2
Pero si realmente hace referencia a los valores de datos estáticos en el código, no puede cambiarlo en la base de datos sin romper la aplicación. Por supuesto, depende de para qué se usen los datos: como mencioné anteriormente, si solo está completando un elemento de la interfaz de usuario para que un usuario pueda seleccionar un valor y que se canalice directamente a la base de datos como parte de un registro en otra tabla , los datos estáticos en la base de datos pueden cambiar independientemente del código de la aplicación. Estoy bastante seguro de que esa es la situación de la que habla @pdr: la aplicación maneja el conjunto de datos estáticos como un solo elemento.
Dave
2

Similar a lo que dijo FrustratedWithFormsDesigner, esto generalmente se hace con un caché, ya que significa que solo tiene que cargar los datos estáticos una vez, pero sigue el patrón OAOO, lo que significa que no estamos definiendo los datos en dos lugares (base de datos y en tu codigo).

Sé que el NHibernate ORM ofrece esta funcionalidad a través de un caché de segundo nivel . Puede indicarle que guarde en caché los datos de una determinada tabla y decir que es de solo lectura. Se cargará la primera vez que sea necesario, y no volverá a acceder a la base de datos después de eso, incluso si accede a los datos de varias sesiones.

Scott Whitlock
fuente
+1 por una vez y solo una vez. Pero, ¿qué hay de tratar las diferentes filas de manera diferente?
Kramii reinstala a Mónica
1
@Kramii: puede usar algo como clases de enumeración . Si los metadatos solo se relacionan con su programa, entonces pondría la lógica de negocios ( IsDefaultOn...) en una propiedad de la entidad. Haga que devuelva verdadero para la única entidad. Eso le permitiría encontrar esa entidad, dada la colección completa. O podría usar una clase de controlador que le proporcionará la entidad apropiada con una llamada al método.
Scott Whitlock
2

Esta es la optimización prematura en su peor momento.

En primer lugar, cualquier DBMS moderno recuperará datos de pequeñas tablas a la velocidad del rayo y todos tienen algoritmos de almacenamiento en caché que van de buenos a excelentes (¡cuanto más pague por el DBMS, mejor será el almacenamiento en caché!). Entonces está optimizando algo que consume recursos mínimos.

En segundo lugar, tiene muy poca experiencia en aplicaciones empresariales del mundo real si imagina que algo así como un "área de ventas" son datos estáticos. Estos pueden cambiar con cada cambio de Director de Marketing o CEO. Entonces te diriges a un mundo de dolor dos años después.

Solo hay dos formas de llegar aquí:

Almacénelo en una base de datos y acceda a los datos con sql "normal".

Almacénelo en un elegante archivo de configuración XML (posiblemente accedido a través de REST o SOAP) que se puede editar fácilmente siempre que haya "un cambio estratégico de política".

James Anderson
fuente
1

Depende de lo que esté haciendo con los datos. Si se trata de una lista de algo, generalmente lo incluiré en una matriz. Si la lista necesita crecer en otra versión, es fácil agregarla a la base de datos y cambiar el código para manejar los datos adicionales en la matriz (lo que puede no ser necesario dependiendo del código, por ejemplo, enumerar los datos con un for loop usando el límite superior de la matriz). Si se trata de una lista de configuraciones, normalmente codificaré esas, ya que generalmente no hay muchas y es más fácil y rápido que usar una instrucción SQL. Si es una configuración que el usuario puede cambiar y quiero guardar la selección para lanzamientos posteriores, crearé una tabla para usar como registro y simplemente extraeré entradas individuales a las variables según sea necesario.

MaQleod
fuente
1

Sé que esta respuesta fue aceptada, pero quería compartir cómo lo hicimos en mi última tienda de desarrollo web, donde tratamos de reducir las E / S de la base de datos tanto como sea posible.

Utilizamos los archivos de inclusión del lado del servidor para la mayor cantidad de estructuras de datos de búsqueda que pudimos. Principalmente esto fue para la navegación del sitio (para incluir la subnavegación), pero también lo usamos para la mayor cantidad posible de menús desplegables y casillas de verificación (Estados, Países, Categorías).

Originalmente, extrajimos todos estos datos de la base de datos. Como le dimos al cliente un widget de administrador, podían cambiar estos datos a voluntad y nunca nos atascamos con pequeños cambios de cinco centavos. La mayoría de las veces estos datos casi nunca cambian, pero ocasionalmente cambiarían.

Siempre estuvimos buscando tiempos de carga más rápidos. Así que decidimos implementar tantos archivos de texto estáticos del lado del servidor como pudimos. Hicimos esto junto al widget de administrador. Cada vez que se actualiza una tabla de base de datos, regeneramos el archivo de texto estático correspondiente. Esto nos dio un entorno muy flexible y rápido.

Michael Riley - AKA Gunny
fuente
0

Mi solución a esto, que puede no funcionar en todas las situaciones, es vincular los datos de la base de datos estática a un código rígido enum. Dado que el problema proviene de tener datos dinámicos (base de datos) vinculados a la lógica estática (código), haga este enlace explícito (y suelto) al tener una tabla de base de datos que se asocie a enum. Ex:

LooseDBCodeBinding (database table)
   ID : Int32 (key)
   Name : String
   HardCodedTypeID : Int32

// in code:
public enum LooseDBCodeBinding
{
   TYPE_1 = 1,
   TYPE_2 = 2,
   TYPE_3 = 3 // etc...
}

Luego, escriba una IU que le permita ver fácilmente la lista de LooseDBCodeBindingregistros y asignarlos a LooseDBCodeBinding enumvalores (incluido el soporte de enlaces "rotos"). Luego puede programar enumy diseñar la base de datos alrededor de la clave de la tabla, y es solo esta tabla la que tiene conocimiento de ambos contextos.

Dave Cousineau
fuente