Supongamos que tengo 4 tipos de servicios que ofrezco (es poco probable que cambien a menudo):
- Pruebas
- Diseño
- Programación
- Otro
Supongamos que tengo 60-80 de servicios reales que cada uno cae en una de las categorías anteriores. Por ejemplo, 'un servicio' puede ser "Programa de prueba utilizando la técnica A" y es del tipo "Prueba".
Quiero codificarlos en una base de datos. Se me ocurrieron algunas opciones:
Opción 0:
Use VARCHAR
directamente para codificar el tipo de servicio directamente como una cadena
Opción 1:
Usar base de datos enum
. Pero, enum es malvado
Opcion 2:
usa dos tablas:
service_line_item (id, service_type_id INT, description VARCHAR);
service_type (id, service_type VARCHAR);
Incluso puedo disfrutar de integridad referencial:
ALTER service_line_item
ADD FOREIGN KEY (service_type_id) REFERENCES service_type (id);
Suena bien, si?
Pero todavía tengo que codificar cosas y tratar con números enteros, es decir, al llenar la tabla. O tengo que crear programación elaborada o construcciones de base de datos al completar o manejar la tabla. Es decir, SE UNE al tratar con la base de datos directamente, o al crear nuevas entidades orientadas a objetos en el lado de la programación, y asegurándose de que las opere correctamente.
Opcion 3:
No use enum
, no use dos tablas, solo use una columna entera
service_line_item (
id,
service_type INT, -- use 0, 1, 2, 3 (for service types)
description VARCHAR
);
Esto es como una 'enumeración falsa' que requiere más sobrecarga en el lado del código de las cosas, por ejemplo, saber eso {2 == 'Programming'}
y tratarlo adecuadamente.
Pregunta:
Actualmente lo he implementado usando la Opción 2 , guiada bajo conceptos
- no use enum (opción 1)
- evite usar una base de datos como hoja de cálculo (opción 0)
Pero no puedo evitar sentir que me parece un desperdicio en términos de programación y sobrecarga cognitiva: tengo que tener en cuenta dos tablas y tratar con dos tablas, frente a una.
Para una "manera menos derrochadora", estoy mirando Option 3
. Es más liviano y requiere esencialmente las mismas construcciones de código para operar (con ligeras modificaciones, pero la complejidad y la estructura son básicamente las mismas pero con una sola tabla)
Supongo que idealmente no siempre es un desperdicio, y hay buenos casos para cualquiera de las opciones, pero ¿hay alguna buena pauta sobre cuándo se debe usar la Opción 2 y cuándo la Opción 3?
Cuando solo hay dos tipos (binario)
Para agregar un poco más a esta pregunta ... en el mismo lugar, tengo una opción binaria de Servicio "Estándar" o "Excepción", que se puede aplicar a la línea de servicio. Lo he codificado usando la Opción 3 .
Elegí no crear una nueva tabla solo para contener los valores {"Estándar", "Excepción"}. Entonces, mi columna solo contiene {0, 1} y se llama al nombre de mi columna exception
, y mi código está haciendo una traducción {0, 1} => {STANDARD, EXCEPTION}
(que codifiqué como constantes en el lenguaje de programación)
Hasta ahora no me ha gustado de esa manera ... (no me gusta la opción 2 ni la opción 3). Encuentro la opción 2 superior a 3, pero con más sobrecarga, y aún así no puedo escapar de codificar cosas como enteros, sin importar qué opción use de 2 y 3.
ORM
Para agregar algo de contexto, después de leer las respuestas, acabo de comenzar a usar un ORM nuevamente (recientemente), en mi caso Doctrine 2. Después de definir el esquema de DB a través de Anotaciones, quería llenar la base de datos. Como todo mi conjunto de datos es relativamente pequeño, quería intentar usar construcciones de programación para ver cómo funciona.
Primero rellené service_type
s, y luego service_line_item
s, ya que había una lista existente de una hoja de cálculo real. Así que cosas como 'estándar / excepción' y 'Pruebas' son todas cadenas en la hoja de cálculo, y deben codificarse en tipos adecuados antes de almacenarlas en DB.
Encontré esta respuesta SO: ¿Qué utilizas en lugar de ENUM en doctrine2? , que sugirió no usar la construcción enum de DB, sino usar un INT
campo y codificar los tipos usando la construcción 'const' del lenguaje de programación.
Pero como se señaló en la pregunta SO anterior, puedo evitar usar enteros directamente y usar construcciones de lenguaje, constantes, una vez que se definen ...
Pero aún así ... no importa cómo lo gire, si empiezo con string
un tipo, primero tengo que convertirlo a un tipo adecuado, incluso cuando uso un ORM.
Entonces, si digo $str = 'Testing';
, todavía necesito tener un bloque en algún lugar que haga algo como:
switch($str):
{
case 'Testing': $type = MyEntity::TESTING; break;
case 'Other': $type = MyEntity::OTHER; break;
}
Lo bueno es que no se trata de números enteros / mágicos [en cambio, se trata de cantidades constantes codificadas], pero lo malo es que no se pueden extraer y sacar cosas automáticamente de la base de datos sin este paso de conversión. conocimiento.
Y eso es lo que quise decir, en parte, al decir cosas como "todavía tengo que codificar cosas y tratar con números enteros". (De acuerdo, ahora, después del comentario de Ocramius, no tendré que tratar directamente con enteros, sino tratar con constantes con nombre y alguna conversión a / desde constantes, según sea necesario).