No. No siempre debes guardar tus tablas de referencia en la base de datos
Las tablas de referencia o de dominio son aquellas en las que almacenamos el conjunto de valores posibles que puede tomar un campo de una tabla que representa una entidad (su dominio, de ahí su nombre alternativo). También son llamadas de forma coloquial como tablas maestras y descriptores, entre otros términos.
¿Es correcto almacenar datos de referencia en la base de datos? Al momento de diseñar una solución, esta pregunta suele generar discusiones en las distintas esferas de IT: desarrolladores y SREs, juniors, seniors e incluso arquitectos. Y suelen ser discusiones que ponen sobre la mesa un arsenal de argumentos, a veces válidos, otras veces no. Es por ello que me gustaría compartir en esta entrada los míos que justifican la afirmación del título, dejando abierta la discusión, desde luego.
La pregunta clave
¿Esos datos serán administrados por los usuarios? Si le respuesta es “si”, la decisión lógica es que se almacenen en la misma base de datos ó en una estructura de almacenamiento paralela, según la implementación. El dilema se instala cuando la respuesta es “no”, en cuyo caso, te recomiendo que sigas leyendo.
No hacer hoy lo que te “podrían” pedir mañana
Los requerimientos siempre deben ser claros, y en base a ellos debe crearse una especificación. La especificación debe limitarse a satisfacer los requerimientos. Y la implementación debe cumplir lo especificado.
Hay casos excepcionales en los que se puede romper la premisa anterior: cuando existen dos o más especificaciones asociadas a evolutivos que presentan cercanía cronológica respecto de su implementación. Dicho de otra forma, si un evolutivo que será atacado en un tiempo breve está relacionado con algo que estamos implementando hoy, podríamos (notar el potencial) orientar nuestra solución de manera de facilitar las cosas para el siguiente evolutivo. Esto no es más que simple economía de procesos. Sin embargo debe estarse seguro de que: 1. Ambos evolutivos realmente están acoplados, y 2. ambos evolutivos realmente serán completados en un periodo de tiempo cercano; por poner una medida arbitraria, no más de dos sprints.
Dicho lo anterior, es común ver implementaciones que, al momento de preguntar al equipo “¿por qué se hizo de esta forma?” la respuesta suele ser “por si acaso en un futuro nos lo piden”. Todos sabemos que los sistemas no se hacen “por si acaso”, sino “para esto”, es decir, para satisfacer una demanda de negocio específica. Caso contrario el resultado es un sistema elefantiásico que nadie comprende y nadie quiere mantener (ver feature bloat).
En este caso, no deberíamos enfocar una solución haciendo suposiciones sobre “cómo será el sistema en un futuro”, a menos que esté dentro de un plan de negocio. En caso de no cumplir esto, sólo estaríamos sumando ruido al ciclo de vida de nuestra solución, acelerando su degradación.
El abuso del modelo relacional y los sistemas database-centric
Los millennials y generaciones anteriores fuimos instruidos en una época en la que las empresas competían por penetrar en el sector corporativo con con soluciones de bases de datos, época en la que proliferaron certificaciones, cursos y libros que defendían el enfoque de “la base de datos como núcleo irrefutable y atemporal de tu negocio”. Estas bases de datos empoderadas no sólo almacenaban cualquier dato de tu sistema, sino además parte de su lógica (procedimientos almacenados, funciones, esquemas de réplica y reporting). Hoy en día el escenario ha cambiado, y las bases de datos han sido relegadas al plano de lo que realmente son: almacenes de datos que deberían poder sustituirse por otros más adecuados en caso de ser necesario, concentrando la lógica en la base de código, que es donde debe estar. En esta transición han ayudado los ORMs y, más adelante, las arquitecturas corporativas más avanzadas e infraestructura en la nube que facilitan el desacoplamiento entre el “qué”, el “cómo” y el “dónde”. Sin embargo, muchos de los antes mencionados millennials y personas de generaciones anteriores siguen estando a cargo de proyectos y de cátedras en las universidades, por lo que aquellos que aún no se han subido al “mundo moderno” siguen evangelizando la idea de la base de datos omnipotente.
Son frecuentes en este sentido argumentos como “no estaríamos aplicando correctamente el diseño relacional si dejáramos afuera los descriptores” o “es más eficiente tener un índice numérico con una clave foránea”. Siguiendo este razonamiento: ¿Deberíamos también almacenar otros campos de texto que se pueden repetir, como apellido y nombre, en una tabla aparte? Todos sabemos cuál es la respuesta.
La internacionalización
Este sí es un tema a tener en cuenta dentro de una proyección a largo plazo de un sistema. Si sabes que el objetivo de tu negocio es expandirse a nuevos mercados, resulta lógico pensar en la internacionalización como un elemento clave de tu solución. En lo personal considero que es una mala praxis no aplicarlo en sistemas de empresas medianas o grandes.
Si el diseñador opta por almacenar datos de referencia en la base de datos, esto entra en conflicto con un diseño orientado a traducciones, dejando como única solución modificar el modelo de datos actual para incluir las mismas dentro de la base de datos y agregar lógica seguramente compleja, difusa y repetitiva para discriminar qué traducción tomar según la configuración regional del cliente.
Comprender la relevancia, longitud y función de los datos
Ciertos datos, sea por su estructura, complejidad o interrelación, son más fáciles de administrar dentro de una base de datos. Son ejemplos de este caso la jerarquía “ciudad-región-país”. En el otro extremo están las estructuras simples, como “tipo de documento”, cuyo único valor radica en su nombre y eventualmente algún código asociado.
Mal uso de recursos
En línea con el punto anterior, es común ver tablas de bases de datos con unos pocos registros de referencia. Y también es común ver que, en implementaciones posteriores, estos mismos datos también se agregan a la base de código, al comprender las limitaciones que conlleva tenerlos en un almacén de datos. Recordemos además el costo adicional e impacto en el rendimiento al procesar información en la base de datos, ponderando el incremento en la complejidad de las consultas y conexiones a la misma.
Por lo anterior, minimizar el uso de tablas de referencia toda vez que sea posible, genera mejoras en la gestión del cambio: en lugar de utilizar migraciones o aplicar cambios directamente en la base de datos, basta con implementar el cambio en la base de código.
Conocer opciones
En lugar de utilizar tablas para almacenes datos de referencia, en la mayoría de los casos resulta más apropiado definir enumerativos en la base de código, indicando para cada uno una clave, preferentemente mnemónica y breve, que será la que se almacene en el campo de la tabla. Algunas ventajas de esta implementación son el versionado de estos valores sin necesidad de requerir mecanismos adicionales como migraciones, y una mayor cohesión entre la lógica de negocio y los valores de dominio, facilitando una clara implementación de validaciones dentro de los objetos de negocio.
Conclusión
No siempre las preguntas simples tienen respuestas simples. Tampoco existe una única forma de resolver un problema. Es parte del buen criterio del profesional el tomar decisiones adecuadas en base a las condiciones presentadas, y en este punto, la experiencia suele marcar la diferencia. Sin embargo es igualmente importante cuestionarse y abrir a debate cada detalle de una solución, propiciando el aprendizaje del equipo y logrando soluciones más sólidas y adaptables.