Angenommen, ich habe vier Arten von Dienstleistungen, die ich anbiete (die sich wahrscheinlich nicht oft ändern):
- Testen
- Design
- Programmierung
- Andere
Angenommen, ich habe 60-80 tatsächliche Dienste, die jeweils in eine der oben genannten Kategorien fallen. Beispielsweise kann "ein Dienst" "Testprogramm unter Verwendung von Technik A" sein und es ist vom Typ "Testen".
Ich möchte sie in eine Datenbank kodieren. Ich habe mir ein paar Möglichkeiten ausgedacht:
Option 0:
Verwenden Sie diese Option VARCHAR
direkt, um den Diensttyp direkt als Zeichenfolge zu codieren
Option 1:
Datenbank verwenden enum
. Aber Enum ist böse
Option 2:
benutze zwei Tabellen:
service_line_item (id, service_type_id INT, description VARCHAR);
service_type (id, service_type VARCHAR);
Ich kann sogar referentielle Integrität genießen:
ALTER service_line_item
ADD FOREIGN KEY (service_type_id) REFERENCES service_type (id);
Hört sich gut an, ja?
Aber ich muss immer noch Dinge kodieren und mich mit ganzen Zahlen befassen, dh wenn ich die Tabelle auffülle. Oder ich muss aufwändige Programmier- oder DB-Konstrukte erstellen, wenn ich die Tabelle auffülle oder damit umgehe. Nämlich JOINs, wenn Sie sich direkt mit der Datenbank befassen oder neue objektorientierte Entitäten auf der Programmierseite erstellen und sicherstellen, dass ich sie richtig betreibe.
Option 3:
Verwenden Sie nicht, verwenden enum
Sie nicht zwei Tabellen, sondern nur eine Ganzzahlspalte
service_line_item (
id,
service_type INT, -- use 0, 1, 2, 3 (for service types)
description VARCHAR
);
Dies ist wie eine „falsche Aufzählung“, die mehr Overhead auf der Codeseite erfordert, wie z. B. das zu wissen {2 == 'Programming'}
und angemessen damit umzugehen.
Frage:
Derzeit habe ich es mit Option 2 implementiert , die unter Konzepte geführt wird
- benutze keine Aufzählung (Option 1)
- Vermeiden Sie die Verwendung einer Datenbank als Tabellenkalkulation (Option 0)
Aber ich kann nicht anders, als zu glauben, dass mir das in Bezug auf Programmierung und kognitiven Aufwand verschwenderisch erscheint - ich muss zwei Tabellen kennen und mich mit zwei Tabellen gegen eine auseinandersetzen.
Für einen "weniger verschwenderischen Weg" schaue ich Option 3
. IT ist leichter und erfordert im Wesentlichen die gleichen Code-Konstrukte, um zu funktionieren (mit geringfügigen Änderungen, aber Komplexität und Struktur sind im Wesentlichen die gleichen, jedoch mit einer einzigen Tabelle).
Ich nehme an, es ist im Idealfall nicht immer verschwenderisch und es gibt gute Fälle für beide Optionen, aber gibt es eine gute Richtlinie, wann man Option 2 und wann Option 3 verwenden sollte?
Wenn es nur zwei Typen gibt (binär)
Um dieser Frage noch ein bisschen mehr hinzuzufügen, habe ich am selben Ort die binäre Option "Standard" - oder "Ausnahmeservice", die für die Servicebuchung gelten kann. Ich habe das mit Option 3 verschlüsselt .
Ich habe beschlossen, keine neue Tabelle zu erstellen, um nur die Werte {"Standard", "Exception"} zu speichern. Meine Spalte enthält also nur {0, 1} und mein Spaltenname wird aufgerufen exception
, und mein Code führt eine Übersetzung aus {0, 1} => {STANDARD, EXCEPTION}
(die ich in der Programmiersprache als Konstanten codiert habe).
Bisher gefällt mir das auch nicht ..... (weder Option 2 noch Option 3). Ich finde Option 2 besser als 3, aber mit mehr Aufwand, und ich kann es trotzdem nicht vermeiden, Dinge als ganze Zahlen zu codieren, egal welche Option ich von 2 und 3 verwende.
ORM
Um nach dem Lesen der Antworten einen Kontext hinzuzufügen: Ich habe gerade (vor kurzem) wieder angefangen, ein ORM zu verwenden, in meinem Fall Doctrine 2. Nachdem ich das DB-Schema über Annotations definiert hatte, wollte ich die Datenbank auffüllen. Da mein gesamter Datensatz relativ klein ist, wollte ich versuchen, Programmierkonstrukte zu verwenden, um zu sehen, wie es funktioniert.
Ich habe zuerst service_type
s und dann service_line_item
s ausgefüllt, da eine Liste aus einer tatsächlichen Tabelle vorhanden war. Dinge wie 'Standard / Ausnahme' und 'Testen' sind also alle Zeichenfolgen in der Tabelle und müssen vor dem Speichern in der Datenbank in richtige Typen codiert werden.
Ich habe diese SO-Antwort gefunden: Was verwenden Sie in doctrine2 anstelle von ENUM? , das vorschlug, das Enum-Konstrukt von DB nicht zu verwenden, sondern ein INT
Feld zu verwenden und die Typen mit dem 'const'-Konstrukt der Programmiersprache zu codieren.
Aber wie in der obigen SO-Frage ausgeführt, kann ich die direkte Verwendung von Ganzzahlen vermeiden und Sprachkonstrukte - Konstanten - verwenden, sobald sie definiert sind.
Aber trotzdem .... egal wie du es drehst, wenn ich mit string
einem Typ beginne, muss ich ihn zuerst in einen richtigen Typ konvertieren , auch wenn ich einen ORM verwende.
Wenn ich also sage $str = 'Testing';
, muss ich noch irgendwo einen Block haben, der so etwas macht wie:
switch($str):
{
case 'Testing': $type = MyEntity::TESTING; break;
case 'Other': $type = MyEntity::OTHER; break;
}
Das Gute ist, dass Sie nicht mit ganzen Zahlen / magischen Zahlen zu tun haben [stattdessen mit kodierten konstanten Mengen], aber das Schlechte ist, dass Sie ohne diesen Konvertierungsschritt keine Dinge automatisch in die Datenbank ziehen und aus der Datenbank entfernen können Wissen.
Und das meinte ich zum Teil damit, dass ich Dinge wie "noch immer Dinge verschlüsseln und mit ganzen Zahlen umgehen müssen" sagte. (Zugegeben, jetzt, nach Ocramius 'Kommentar, muss ich mich nicht direkt mit ganzen Zahlen befassen, sondern mit benannten Konstanten und einer gewissen Konvertierung in / von Konstanten, je nach Bedarf).