Orm
-
Hallo zusammen,
mir würde mal eure Meinung zu ORMs interesssieren. Beim beschäftigen mit Datenbanken, bin ich darauf mehrmals gestoßen, aber so ganz einleuchten tut mir das nicht. Im wesentlichen, wie ich es verstehe, schreibt man doch einfach Klassen, die dem Schema entsprechen und das orm mappt das dann automatisch.
Was ja erstmal total toll klingt, nur verhunzt man damit nicht sein komplettes OOP Design?
Das Ziel des Datenbankschemas ist ja ein anderes als das eines OOP Schemas. Und eines an das andere anzugleichen, erscheint mir da wenig sinnvoll.
Hier würde mich mal interessieren:- Wie schätzt ihr Orms allgemein ein?
- Wie nutzt ihr sie? Gleicht ihr eine Sache an die andere an oder gibt es da tolle techniken, um das zu verhindern?
-
Was siehst du denn als Alternative, außer händisch Code zum Kopieren der Daten (zwischen Logik- und Datenbankschicht) zu schreiben?
-
Im DDD gibt es sowieso mehrere Schichten und die gleichen Objekte kommen in mehreren Schichten vor. Dann gibt es DTO Objekte, die zwischen den Schichte ausgetauscht werden - im Endeffekt werden da öfter mal Daten rumkopiert.
Relativ weit unten wäre ein Repository, und drunter wäre dann irgendwo das ORM angesiedelt. Die Objekte, die da verwaltet werden, können noch recht flach sein, so wie das für die Datenbank passt. Erst drüber kommen dann die Domain Schichten, die die Objekte dann vielleicht wieder ganz anders verpacken, anreichern usw...So in etwa - ist mindestens zehn Jahre her, dass ich damit zu tun hatte.
In letzter Zeit habe ich nicht viel mit Datenbanken zu tun, und wenn, dann benutze ich kein ORM (paar eigene Abstraktionsschichten). Liegt auch daran, dass ich mit C++ arbeite und da kein ORM Framework kenne, das mir zusagt. Kann mir auch nicht so wirklich eins vorstellen. Das ist aber auch hochgradig subjektiv.
In C#/Java fühlen sich die ORM Frameworks natürlicher an, da kann man mit Reflection viel verstecken.
-
@Th69 Ich kenne mich so ziemlich null damit aus.
Im Grunde starte ich mehr oder weniger grade mit Datenbanken (embedded sqlite) und versuche da irgendwie zu verstehen wie das alles funktioniert. Ich finde Kurse, Bücher etc. über Datenbankdesign, sql oder wie ich ne mit sqlite3 sql befehle in C++ ausführen kann. Was mir fehlt ist das Wissen darüber wie ich sowas sinnvoll integriere, da konnte ich bisher nicht allzu viel finden (Vermutlich fehlen mir die richtigen google Begriffe?)
Worauf ich immer mal wieder gestoßen bin ist orm und DAO (data access object pattern). Daher hab ich mir mal angeguckt was es da für libs und Beispiele gibt und mir ist aufgefallen, dass man im Grunde lauter Klassen erstellt, die 1 zu 1 dem Datenbankschema entsprechen. Und aus OOP Sicht widerum eher weniger Sinn macht. Da konnte ich mir irgendwie nicht so recht vorstellen, dass man einfach seine OOP Grundsätze über Board schmeißt und es nach der Datenbank ausrichtet?
@Mechanics Da würde mich mal interessieren, was du dann verwendest um die Datenbank in deine Objekte zu mappen? Machst du das alles irgendwie per Hand?
-
@Mechanics Da würde mich mal interessieren, was du dann verwendest um die Datenbank in deine Objekte zu mappen? Machst du das alles irgendwie per Hand?
Ich muss mal überlegen, wie ich darauf antworte, weil bei uns wird da sowieso viel per Hand gemacht... Auf der anderen Seite haben wir da jetzt auch keine typische Enterprise/Datenbankanwendung, deswegen haben wir jetzt sowieso nicht wirklich Klassen, die großartig den Daten entsprechen, die aus der Datenbank kommen.
Das ist oft eher so, dass die Objekte an sich Key-Value Paare sind, und an den meisten Stellen im Code ist auch egal, was da drinsteht (wird konfiguriert), paar Felder sind aber vorgegeben (ID, Änderungsdatum, ...).Wir haben dann hauptsächlich zwei Strukturen, um damit umzugehen. Wir haben sowas wie Records. Das ist so in etwa an das Active Record Pattern angelehnt. Wir hatten uns aber nicht im Detail damit befasst, deswegen weiß ich nicht, ob da jetzt nicht lauter Konzepte definiert sind, auf die wir nicht geachtet haben. Das war etwas, was mir und einem Kollegen beim Refactoring halbwegs sinnvoll vorkam, ohne die komplette Software umzubauen. Was ich damit sagen will, ich bin nicht der Meinung, dass Active Record an sich besser wäre, als ORM, das hat sich bei uns einfach eher angeboten.
Und das andere ist so ein "Builder" für (verschachtelte) Queries.
Edit: da evtl. unklar, ich meinte tatsächlich Abfragen, und nicht Insert/Update. Damit man die Bedingungen als Baum im Code definieren und kann nicht als String mit where x > y...Hauptsache keine Sql Statements als Strings im Code aufbauen, das war das primäre Ziel.
Und das ganze abstrahiert intern auch die Datenbankunterschiede, soweit wir das brauchen.
-
Bei ORMs geht es ja u.a. auch darum, die ganzen SQL-Anweisungen intern zu verpacken und dafür typsichere Funktionen anzubieten ("no raw string queries").
Du kannst dir ja mal ein paar der C++ ORMs für SQLite anschauen:
- SQLite ORM
- SQLiteC++
- Hiberlite ORM
bzw. - ODB (welches auch andere Datenbanken unterstützt)
-
@Th69 Das habe ich tatsächlich sogar
Die sqliteC++ ist relativ basic, da gibt es auch keinen query builder. Also quasi grad so das notwendigste.
Die orm lib dagegen hat einen query builder und auch orm. Die hatte ich jetzt auch im Auge und daraufhin sind im Grunde auch erst die Fragen gekommen.
Beispiel:
Die Klassen haben dort dann alle eine "id" als member. Das ist ja in der Regel nichts, was man in seinen Objekten normalerweise hätte.
Oder wenn man sich https://github.com/fnc12/sqlite_orm/blob/master/examples/foreign_key.cpp anschaut. Hier stehen die foreign key ja wirklich drin (statt eine Referenz zum Object direkt). Das kann wohl kaum als Ersatz für seine "richtigen" Objekte angesehen werden, oder??
Den Vorteil mit "raw string queries" vermeiden, sehe ich auf jeden Fall auch. Dafür reicht aber auch erstmal ein query builder.
-
@Mechanics Ich hab mich mal etwas schlau gemacht und informiert, was das active record pattern ist (das ist übrigens ungemein hilfreich einfach mal so ein paar fachbegriffe gehört zu haben ... dann ist das googeln schon gleich viel leichter^^).
Was ich so zunächst mitgenommen habe, ist das man wohl zumindest primär zwischen "Activate Record" und "Data Mapper" unterscheidet. Beides gibt es auch außerhalb des Kontexts von orm, aber im Kontext von orm ist das wohl auch die Haupart von orms zu unterscheiden (sprich orm is nicht gleich orm).
Active record vermischt das ganze nach meinem verständnis. Hier ist tatsächlich Klasse = Table. Die Vorteile hier sind natürlich, dass es verhältnismäßig relativ einfach zu nutzen ist. Aber die Kritik ist ebenfalls stark ... insbesondere das man hier Applikations logik mit Daten vermischt, was ja auch so ein bisschen mein Kritikpunkt war oben (nicht nur das es etwas OOP zerstört, testen wird damit auch erschwert etc.).
Ich denke https://github.com/fnc12/sqlite_orm fällt hier auch in diese Kategorie?Bei Data Mapper versucht man die beiden eher unabhängig voneinander zu halten wie der Name wohl schon zeigt. Hier ist man etwas flexibler, aber die Schwierigkeit nimmt auch zu.
Ich kenne allerdings keine C++ orm lib, die das nutzt?Vlt. hat hier ja jemand ergänzende Worte oder noch noch neue Anhaltspunkte, Empfehlungen. Allgemein scheinen mir die Nachteile von Active Record ja schon ziemlich groß. Da wundert es mich ein bisschen wie populär das ist.
-
Active record vermischt das ganze nach meinem verständnis. Hier ist tatsächlich Klasse = Table.
Achso, das habe ich nicht klar kommuniziert. Wir haben da wie gesagt eigentlich gar keine Klassen. Ein "Record" ist etwas wie ein Dictionary mit interner Logik (z.B. Tabellenzuordnung).
Das kann man sich in etwa so vorstellen, dass die Benutzer eigene Daten an unsere Objekte anhängen können (die nicht aus einer Datenbank kommen), die uns nicht weiter interessieren (die sind aber in einer Datenbank abgelegt). Nur sind dann doch im Laufe der Zeit dutzende Stellen hinzugekommen, wo man diese Daten doch irgendwie benutzen will, z.B. zum Filtern/Suchen/Sortieren, oder vielleicht auch was eintragen.
Da haben wir aber keine Klassen wie "Produkt" dafür. Gibt aber verschiedene Möglichkeiten, Abfragen gegen diese Zusatzdaten zu definieren, und dann z.B. auf konfigurierten Spalten zuzugreifen. Das geht bei uns eben über diese zwei Konzepte, mit so einem QueryBuilder baut man sich die Bedingungen zusammen, und kriegt dann Records, die die Daten enthalten. Auf die Werte kann man über den Spaltennamen zugreifen. Und man kann sie auch aktualisieren und in die Datenbank zurückschreiben. In dem Sinne ähnlich zu Active Record, aber da fehlt sogar die eigentliche spezialisierte Klasse.Es ist jetzt nichts, was ich per se gut oder elegant finde. Ich finde, das ist eine pragmatische Lösung, die bei uns ganz gut passt.
-
Hallo Leon0402,
Ich beschäftige mich schon seit geraumer Zeit mit objektorientierten Datenbanken für C++-Klassen. Das Ziel ist ja, Objekt zu speichern ohne sich um das wie zu kümmern.
Schau Dir doch mal GlobalObjects an, vielleicht ist das etwas für Dich. Ist open source und eigentlich schon weit gediehen.
Einen schnellen Überblick bekommst Du über die Videos.Gruß Helmut