Angenommen, Sie schreiben eine Anwendung, die vom Benutzer konfiguriert werden kann. Zum Speichern dieser "Konfigurationsdaten" in einer Datenbank werden üblicherweise zwei Muster verwendet.
Die einzeilige Tabelle
CompanyName | StartFullScreen | RefreshSeconds | ... ---------------+-------------------+------------------+-------- ACME Inc. | true | 20 | ...
Die Name-Wert-Paar- Tabelle
ConfigOption | Value -----------------+------------- CompanyName | ACME Inc. StartFullScreen | true (or 1, or Y, ...) RefreshSeconds | 20 ... | ...
Ich habe beide Optionen in der freien Natur gesehen und beide haben offensichtliche Vor- und Nachteile, zum Beispiel:
- Die einzeiligen Tabellen begrenzen die Anzahl der Konfigurationsoptionen, die Sie haben können (da die Anzahl der Spalten in einer Zeile normalerweise begrenzt ist). Jede zusätzliche Konfigurationsoption erfordert eine Änderung des DB-Schemas.
- In einer Name-Wert-Paar-Tabelle ist alles "string-typisiert" (Sie müssen Ihre Booleschen / Datums- / usw. Parameter codieren / decodieren).
- (viel mehr)
Gibt es innerhalb der Entwicklungsgemeinschaft einen Konsens darüber, welche Option vorzuziehen ist?
Antworten:
Ich persönlich bevorzuge die einzeiligen Tabellen für die meisten Dinge. Es ist zwar wahr, dass es weniger flexibel ist, es sei denn, Sie erwarten dynamisches Verhalten, aber es ist durchaus akzeptabel, später zusätzliche Spalten hinzuzufügen, wenn dies erforderlich ist. In gewisser Weise entspricht dies der Verwendung eines Wörterbuchs / einer Karte, um Name-Wert-Paare zu halten, im Gegensatz zu Klassenmitgliedern beim Programmieren. Zugegeben, es ist keine perfekte Metapher, aber wenn man darüber nachdenkt, sind viele Vor- und Nachteile gleich.
Würden Sie also ein Wörterbuch / eine Karte über Klassenmitgliedern verwenden? Wahrscheinlich nur, wenn Sie Grund zu der Annahme hatten, dass die Menge der darzustellenden Daten vollständig anpassbar ist, ähnlich wie bei einer Name-Wert-Paartabelle.
quelle
Im Allgemeinen würde ich Option 2 wählen, ABER ich hätte mehrere Spalten, um den Datentyp zu erzwingen
Option 1 hat den zusätzlichen Vorteil, dass Sie sehr einfach ganze Konfigurationen "tauschen" können, indem Sie eine
Active
Spalte hinzufügen .quelle
activatedOn
Zeitstempel an, damit Sie erkennen können, wann der Zeitstempel aktiviert wurde. Und wenn Sie sich für Option 2 entscheiden ... was passiert, wenn am Ende Werte in mehreren Spalten gespeichert werden (oder es ist Oracle, wo (anscheinend) Null und eine leere Zeichenfolge äquivalent sind)?Für mich hängt es davon ab, wie Sie sie konsumieren möchten, ob Sie einreihig oder mit EAV arbeiten.
Die Stärke von EAV besteht darin, dass neue Daten hinzugefügt werden können, ohne die Struktur zu ändern. Dies bedeutet, dass Sie, wenn Sie einen neuen Konfigurationswert möchten, diesen einfach zur Tabelle hinzufügen und an der gewünschten Stelle im Code abrufen und der Domäne, dem Schema, der Zuordnung und den DAL-Abfragen kein neues Feld hinzufügen müssen , usw.
Der Nachteil ist, dass es nur die geringste Struktur aufweist, sodass Sie pessimistisch mit den Daten umgehen müssen. Bei jeder Verwendung eines Konfigurationswerts muss davon ausgegangen werden, dass der Wert nicht vorhanden ist oder nicht das richtige Format aufweist, und muss sich entsprechend verhalten, wenn dies nicht der Fall ist. Ein Konfigurationswert kann möglicherweise nicht in ein double, ein int oder ein char umgewandelt werden. Es kann null sein. Möglicherweise gibt es überhaupt keine Zeile für den Wert. Um dies zu umgehen, muss normalerweise ein einziger gültiger "Standard" -Wert für alle Konfigurationswerte eines bestimmten In-Code-Typs vorhanden sein ( äußerst selten; häufig ist der Standardwert für die Verwendung von Code genauso problematisch wie überhaupt keiner) oder Behalten Sie ein fest codiertes Wörterbuch mit Standardwerten bei (das sich jedes Mal ändern muss, wenn eine neue Spalte hinzugefügt wird, wodurch der Hauptvorteil des EAV-Speichers überflüssig wird).
Eine einzelne breite Reihe ist so ziemlich das Gegenteil. Sie ordnen es einer einzelnen Instanz eines Konfigurationsobjekts mit einem Feld / einer Eigenschaft für jeden vorhandenen Konfigurationswert zu. Sie wissen genau, welchen Typ diese Werte zur Kompilierungszeit haben sollten, und Sie "fallen schnell" in der DAL aus, wenn eine Konfigurationsspalte nicht vorhanden ist oder keinen Wert des richtigen Typs hat, wodurch Sie einen Ort zum Abfangen von Ausnahmen erhalten bei Problemen mit dem Abrufen der Konfiguration / der Flüssigkeitszufuhr.
Der Hauptnachteil besteht darin, dass für jeden neuen Wert eine strukturelle Änderung erforderlich ist. Neue DB-Spalte, neue Spalte in der DAL (entweder das Mapping oder die SQL-Abfragen / SPs), neue Domänenspalte, alles erforderlich, um die Verwendung ordnungsgemäß zu testen.
Die richtige Situation, in der eine von diesen verwendet wird, ist die Situation, in der die Nachteile gemindert werden. In den meisten Situationen für die Konfigurationscodierung war für mich eine einzeilige Implementierung erforderlich. Dies liegt hauptsächlich daran, dass Sie, wenn Sie einen völlig neuen Konfigurationswert einführen, der das Verhalten eines Teils Ihres Programms steuert, den Code bereits ändern müssen, um den neuen Konfigurationswert zu verwenden. Warum nicht zum Konfigurationsobjekt wechseln und den zu verwendenden Wert hinzufügen ?
Kurz gesagt, ein EAV-Schema zum Speichern der Konfiguration löst das Problem, das es zu lösen vorgibt, nicht wirklich, und die meisten Problemumgehungen für die darin enthaltenen Probleme betreffen DRY.
quelle
Speziell für Konfigurationswerte würde ich sagen - gehen Sie mit der einzelnen Zeile. Wie oft werden sich diese Spalten ändern, es sei denn, Sie befinden sich gerade in der Entwicklung?
Es ist wahrscheinlich am besten, den Datentyp der Werte und nicht den Code für die Erweiterbarkeit zu sichern, die Sie in den Ausfallzeiten zwischen großen (r) Releases wahrscheinlich nicht haben. Außerdem ist das Hinzufügen oder Entfernen einer einzelnen Spalte die einfachste Migration, die es gibt. Beim Erstellen einer neuen Konfigurationsoption sind keine Kopfschmerzen zu erwarten.
Außerdem haben Sie gesagt, "Benutzer" können diese Optionen konfigurieren, ohne eine Obergrenze zu setzen. Handelt es sich um Benutzerkonfigurationen? In diesem Fall werde ich noch stärker argumentieren, dass sich die Konfigurationsoptionen in den Spalten befinden sollten - eine einzelne Zeile pro Benutzer. Das erspart später viele Wartungsprobleme.
quelle
Wenn Ihre Clients JSON-Fragmente verarbeiten können (das sind nicht nur Arrays und Wörterbücher, sondern auch einfache Zeichenfolgen, Zahlen, Boolesche Werte und Nullwerte), können Sie eine mehrzeilige Tabelle mit dem Optionsnamen und einem Zeichenfolgenwert haben, der JSON enthält. Dadurch können Sie auch strukturierte Werte speichern, und der Code für die Verarbeitung dieser sollte bereits vorhanden sein.
Wenn Ihre Clients keine JSON-Fragmente verarbeiten können, holen Sie sich neue Clients.
quelle
Einreihige Vorteile: Gut definiert. Nachteile: Das Ändern der Konfiguration kann schmerzhaft sein. DB-Migrationen etc ..
Entity-Value-Vorteile: Superflexibel, unterstützt die Weiterentwicklung Ihrer Konfiguration. Nachteile: Referentielle Integrität? Weitere Überprüfungen in Ihrem Code, um festzustellen, ob die Eigenschaft vorhanden ist, bevor Sie etwas daran ändern können.
Ich würde Ansatz 2 wählen, der von einer nicht relationalen Datenbank wie Mongo unterstützt wird. Wenn es etwas gibt, dessen Sie sich sicher sein können, ändert es sich.
quelle
Verwende beide!
Sortieren Sie, welche Optionen mehrere Instanzen haben können und welche Optionen generisch sind.
Die einzeilige Tabelle (Konfigurationen)
Die Name-Wert-Paar-Tabelle (Optionen)
Ich denke das ist flexibler.
quelle