Rails - STI verwenden oder nicht ... das ist die Frage

8

Vor sechs Monaten stellte ich eine Frage zu Modellierungsdaten für meine App und erhielt einige Ratschläge, die mich auf STI hinwiesen ( Einzelheiten finden Sie unter Rails-Datenmodell - Best Practices-Frage ).

Ich habe damit herumgespielt, es etwas zum Laufen gebracht, mich dann abgelenkt und das Projekt unterbrochen.

Ich habe gerade angefangen, es von Grund auf neu zu entwickeln, mit dem Vorteil von 6 weiteren Monaten Programmier- / ROR-Erfahrung, und ich bin wieder einmal an diese Wand gestoßen, wenn es darum geht, Zutaten für meine Bierrezepte zu modellieren.

Um eine kurze Zusammenfassung zu geben, gehe ich davon aus, dass ich drei Zutatenarten (Malz, Hopfen und Hefe) habe - jede hat einige Attribute (Name, Preis, Verkäufer), aber jede hat auch Attribute, die für diese Zutatenart spezifisch sind. Sie sind alle verwandt (sie sind alle Zutaten), aber sie haben ein unterschiedliches "Verhalten" (zum Beispiel werden Körner püriert und es wäre logisch, mit dem umzugehen, was für Hopfen / Hefe usw. nicht gelten würde.)

Die Zutaten sind gerade so unterschiedlich, dass ich erwäge, nur drei separate Tabellen in der Datenbank zu haben ... aber was ist mit Controllern? Könnte ich einen einzelnen Ingredients-Controller verwenden, um die einzelnen Modelle zu verwalten?

Ich habe über Alternativen zu STI (Klassentabellenvererbung und Mehrtabellenvererbung) gelesen, aber alle Lösungen scheinen klobig. Gibt es Alternativen, die mir die Bequemlichkeit von STI bieten (z. B. das Abrufen aller Zutaten unabhängig vom Typ mit einer einzigen Tabellenabfrage) ohne die Nachteile (Nullfelder, unhandliche Tabellen, wenn Sie weiterhin Unterklassen und Felder hinzufügen usw.)

Entschuldigung, ich weiß, dass diese Frage etwas verschwommen ist, aber ich habe das Gefühl, dass ich keine saubere Lösung finden kann, und ich versuche jetzt herauszufinden, welche Methode da draußen das geringere Übel ist. Ich bin sicher, andere haben sich damit befasst, und ich würde gerne die Vor- und Nachteile verschiedener Lösungen hören. Vielen Dank!

Jim
quelle
2
Eine Antwort ist nur möglich, wenn Sie eine Postleitzahl angeben. Wenn Sie es nicht wissen, wählen Sie einfach eine aus und sehen Sie, wie es geht. Sie schreiben Ruby-Code. Warum sollten Sie sich also so viele Gedanken darüber machen, was in der Datenbank vor sich geht? Sie können die Zuordnung später jederzeit ändern. Es hört sich nicht so an, als würden Sie bald eine große Datenbank in Produktion haben.
Kevin Cline
Ich würde sagen, dass sie alle Zutaten sind und die Geschäftslogik höher ausführen, aber das bin nur ich ... und wie @kevincline sagt, können Sie sie später ändern. Da sie im Wesentlichen wie der gleiche Tisch klingen, wäre es nicht einmal zu schwer.
Rig
Ich glaube, ich hasse die Idee, nullbare Felder in meiner Tabelle zu haben, aber vielleicht muss ich einfach darüber hinwegkommen ...
Jim

Antworten:

7

Während permanent Nullfelder und große unhandliche Tabellen konzeptionell hässlich sind, verursachen sie im Allgemeinen keine wirkliche Ineffizienz. Der zusätzliche Speicherplatz, der von Nullfeldern verwendet wird, spielt für die meisten Systeme keine wichtige Rolle, und die Abfragegeschwindigkeit wird nicht langsamer, wenn Sie Ihre Indizes gut einrichten.

Die Vorteile von STI lohnen sich häufig (Datenbankeffizienz durch Minimierung von Joins sowie Einfachheit und Trockenheit des gemeinsam genutzten Codes). Wenn Sie also ein traditionelles SQL-System verwenden möchten, lernen Sie einfach, die konzeptionelle Hässlichkeit zu ignorieren und STI zu verwenden. Ihr Anwendungsfall ist das, wofür STI entwickelt wurde.

Das heißt, wenn Sie nicht zu tief in Ihrem Entwicklungszyklus sind, als dass dieses Projekt an Ihr Datenbanksystem angehängt werden könnte (und es scheint, als ob Sie es nicht sind), und Sie bereit sind, etwas Zeit in Forschung / Lernen zu investieren, könnten Sie dies wirklich tun Ich möchte eine Alternative zu SQL in Betracht ziehen (es gibt viele gute da draußen). Derzeit ist MongoDB die beliebteste Alternative (und mein persönlicher Favorit) .

MongoDB ist eher dokumentbasiert als schemabasiert. Dies bedeutet, dass es nicht so starr ist, was darin gespeichert werden kann. Da MongoDB kein erzwungenes strukturiertes Schema hat, können Sie in Ihrem Projekt nur eine einzige Sammlung von haben ingredients("Sammlungen" in MongoDB ähneln "Tabellen" in SQL-Datenbanken). Jedes ingredientin dieser Sammlung könnte gemeinsam genutzte Felder haben, wie sie in einer IngredientOberklasse definiert sind (diese Felder würden nicht in der Datenbank selbst definiert). Und die Unterklassen Malt, Hopsund Yeastkonnten ihre eigenen individualisierten Felder (auch hier als direkt in diesen Modellunterklassen definiert sind , nicht in der db selbst) haben. Dies ist genau das , wonach Sie suchen - es bietet Ihnen den Komfort von STI ohne seine konzeptionelle Hässlichkeit.

Zusätzlicher Bonus: Möglicherweise hilft die Verwendung eines solchen NoSQL-Datenbanksystems auch bei der Vereinfachung anderer Bereiche Ihrer App. In vielen (den meisten?) Gängigen Web-Business-Domänen ist NoSQL eine bessere Wahl als SQL, da Web-Domains in der Regel besonders dokumentenintensiv sind (Dokumente sind daher eine natürliche Wahl für Speichermechanismen).

Zusammenfassung: Wenn Sie aufgrund der Verwaltung oder eines Teils Ihrer App, der darauf basiert, an die Verwendung einer SQL-Datenbank gebunden sind oder keine Zeit haben, in das Erlernen neuer Funktionen zu investieren, entscheiden Sie sich einfach für STI. Wenn Sie nicht an die Verwendung einer SQL-Datenbank gebunden sind und Zeit haben, etwas Neues zu lernen, würde ich dringend empfehlen, zu MongoDB oder einer anderen dokumentbasierten NoSQL-Datenbank zu wechseln.

Ben Lee
quelle
Ich liebe diese Antwort. Praktische Ratschläge für meine Situation mit dem zusätzlichen Bonus einiger Ratschläge, um die Dinge in Zukunft einfacher zu machen. Ich habe NoSQL-DBs überhaupt nicht ausgecheckt, aber ich werde MongoDB untersuchen - hört sich gut an, und da dieses gesamte Projekt wirklich eine Lernerfahrung ist, bin ich definitiv offen für neue Dinge.
Jim