Ist ORM immer noch ein Anti-Pattern?
(github.com/getlago)- ORM wird zwar als „Spielzeug für Startups“ kritisiert, doch der eigentliche Streitpunkt liegt weniger bei ORM selbst als bei falscher Nutzung
- Objektgraphen und relationale Tabellen sind unterschiedliche Modelle, wodurch eine Paradigmen-Impedanz entsteht; das allein macht ORM aber noch nicht zum Anti-Pattern
- Die Debatte um Verstöße gegen SRP und SOC ist berechtigt, doch ORM ist von vornherein eine Abstraktion, die zwei Datenmodelle verbindet, sodass eine Bewertung allein anhand von Prinzipienverstößen schwierig ist
- Performance-Probleme entstehen häufiger durch Muster, bei denen Daten in der Logik der Host-Sprache zusammengesetzt werden, als durch ORM selbst; sie lassen sich mit den SQL-ähnlichen Funktionen von ORM reduzieren
- Der Hauptgrund, warum Lago Active-Record-Abfragen durch Raw SQL ersetzt hat, war weniger Geschwindigkeit als Transparenz und Debugging; bei großen Abfragen kann der Wechsel zu Raw SQL in der Praxis vorteilhaft sein
Grundhaltung zur ORM-Kritik
- ORM wird häufig als „Anti-Pattern“ angegriffen, doch die Schlussfolgerung, ORM selbst sei schlecht, ist eher überzogen
- Wie andere Abstraktionen ist auch ORM nicht perfekt und kann gewisse Transparenzverluste sowie Performance-Kosten verursachen
- Lago stieß auf Probleme, während es auf Active Record, das ORM von Ruby on Rails, setzte, und nahm dies zum Anlass, den Umgang mit ORM-Abhängigkeiten neu zu prüfen
- Die Schlussfolgerung geht weniger dahin, ORM aufzugeben, sondern ORM als Abstraktion mit klaren Vor- und Nachteilen zu behandeln
Unterschiede zwischen Objektmodell und relationaler Datenbank
- Die Objekte, mit denen ORM arbeitet, ähneln eher einem gerichteten Graphen, der auf andere Knoten verweist
- Tabellen in relationalen Datenbanken ähneln eher einem ungerichteten Graphen, in dem Daten über gemeinsame Schlüssel bidirektional verbunden sind
- ORM kann einen ungerichteten Graphen zwar nachbilden, doch Konfiguration und Verhalten sind nicht immer einfach
- Einem
User-Objekt kann dasPosts-Array fehlen - Die Entitäten im
Posts-Array haben möglicherweise keinen Rückverweis auf dasselbeUser-Objekt - Selbst wenn ein Rückverweis vorhanden ist, kann es sich statt um dasselbe Objekt um ein kopiertes Objekt handeln
- Einem
- So kann ein ORM beispielsweise die Beiträge eines Nutzers als Array zurückgeben, ohne in jedem Beitrag einen Rückverweis auf den Nutzer in der Rolle des Autors einzuschließen
- Diese Diskrepanz ist eine gute akademische Kritik an ORM, doch im realen Betrieb zeigen sich größere Probleme eher in der konkreten Nutzung
SRP- und SOC-Debatte
-
Single-Responsibility-Prinzip (SRP)
- ORM wird dafür kritisiert, gegen das Single-Responsibility-Prinzip (SRP) zu verstoßen
- Denn es kann dazu führen, dass eine Klasse oder Schicht mehrere Rollen gleichzeitig übernimmt
- Ausführung von Datenbankoperationen und Transaktionen
- Darstellung von Datensätzen
- Definition von Beziehungen
- Erzeugen und Ausführen von Migrationen
- Da der Zweck von ORM jedoch gerade darin besteht, zwei unterschiedliche Datenparadigmen zu verbinden, lässt sich ORM nicht allein wegen einzelner Prinzipienverstöße verwerfen
-
Separation of Concerns (SOC)
- ORM kann auch das Prinzip der Separation of Concerns (SOC) verwischen
- SOC besagt, dass eine Infrastrukturkomponente nur ein einziges Anliegen haben sollte
- Weil ORM das Datenbankmanagement in Richtung Backend verlagert, kann man darin einen SOC-Verstoß sehen
- Allerdings kombinieren heutige Infrastrukturkomponenten und Coding-Patterns mitunter mehrere Rollen, um Performance, Latenz und Code-Struktur zu verbessern
- CPU-Aggregatoren in OLAP-Datenbanken
- Edge-Backend-Frontend
- Monorepo
Performance-Probleme entstehen häufiger durch die Nutzungsweise als durch ORM
- Die Kritik, ORM sei immer ineffizient, ist größtenteils falsch
- Viele ORMs können deutlich effizienter arbeiten, als Entwickler vermuten
- Das Problem ist, dass ORM es leicht macht, Daten mit Logik in der Host-Sprache wie JavaScript oder Ruby zusammenzusetzen
- Im TypeORM-Beispiel gilt es als schlechtes Muster, zunächst die Autoren eines bestimmten Unternehmens abzufragen, anschließend für jeden Autor erneut dessen Beiträge zu laden und jeden Beitrag separat zu speichern
- Besser ist es, mit
createQueryBuilder()von TypeORM eine einzelne Update-Abfrage zu konstruieren - Auch beim Refactoring der Billing-SQLs von Lago gab es zwischen der Active-Record- und der Raw-SQL-Version keinen Performance-Unterschied
- Da die Daten-Join-Funktionen von Active Record stark genutzt wurden, waren die bestehenden Abfragen bereits optimiert
- Die Neufassung in Raw SQL diente eher der Transparenz als der Performance-Verbesserung
Fälle, in denen ORM tatsächlich langsam werden kann
- ORM ist nicht immer so effizient wie Raw SQL und kann in manchen Situationen erheblich ineffizient sein
- Das erste Problem ist, dass ORM beim Umwandeln von Abfrageergebnissen in Objekte einen großen Rechen-Overhead erzeugen kann
- TypeORM wird als Beispiel für dieses Problem genannt
- Das zweite Problem tritt auf, wenn beim Traversieren von One-to-many- oder Many-to-many-Beziehungen mehrere Roundtrips zur Datenbank entstehen
- Dieses Muster wird als N+1-Problem bezeichnet
- Zu einer ursprünglichen Abfrage kommen N Unterabfragen hinzu
- Im Prisma-Beispiel können beim verschachtelten Laden von Nutzern, Beiträgen und Kommentaren für jeden Kommentar neue Datenbankanfragen entstehen
- N+1 tritt bei ORMs häufig auf, doch mit einem Data Loader lassen sich N+1 Abfragen auf 2 Abfragen zusammenfassen
- Viele der typischen ORM-Probleme lassen sich vermeiden, wenn man die ORM-Funktionen ausreichend nutzt
Das größere Problem sind Transparenz und Debugging
- Die größte Schwäche von ORM ist Transparenz
- Da ORM faktisch ein Query Builder ist, ist es – abgesehen von offensichtlichen Fehlern bei primitiven Typen – nicht der letztliche Überbringer von Fehlern
- Wenn ein SQL-Fehler zurückgegeben wird, muss das ORM ihn interpretieren und an den Nutzer weiterreichen
- Active Record hatte an dieser Stelle Schwierigkeiten, und genau das war auch der Grund, warum Lago seine Abfragen für Billing-Abonnements refaktoriert hat
- Bei unerwarteten Ergebnissen musste der folgende Ablauf wiederholt werden
- Die gerenderte SQL-Abfrage prüfen
- Diese SQL-Abfrage erneut ausführen
- Den SQL-Fehler wieder in Änderungen an Active Record übertragen
- Dieser Hin-und-her-Prozess schwächt den ursprünglichen Zweck, Active Record zu verwenden, nämlich nicht direkt mit der SQL-Datenbank interagieren zu müssen
Praktische Einschätzung
- Richtig eingesetzt kann ORM eine Effizienz nahe an Raw SQL erreichen
- Viele Probleme entstehen, wenn man die SQL-ähnlichen Funktionen von ORM nicht nutzt und sich zu stark auf die Logikstrukturen der Host-Sprache verlässt
- Wenn große Abfragen Entwicklern Schwierigkeiten bereiten und das Debugging behindern, kann der Wechsel zu Raw-SQL-Abfragen eine gute Investition sein
- Die meisten ORMs bieten die Möglichkeit, SQL-Abfragen innerhalb des ORM auszuführen
1 Kommentare
Hacker-News-Kommentare
Ich nutze ORMs seit dem Erscheinen von Hibernate in Java, aber ich fand sie immer eher schlecht.
Der angebliche Vorteil „man kann auf eine andere Datenbank wechseln“ ist rückblickend fast Unsinn, und in der Praxis macht das ohnehin niemand.
Auch die Aussage „man muss kein SQL kennen“ ist falsch; bei langlebigen, nicht trivialen Apps muss man am Ende individuelle Queries doch auf String-Ebene nachbearbeiten.
Die Datenschicht sollte meiner Meinung nach Query für Query als String-SQL aufgebaut und interpoliert werden, und je näher man an raw JDBC ist, desto besser.
Auch die Behauptung, ORM unterstütze ein „Domain Model“, ist ein schlechtes Argument, weil dieses Domain Model am Ende immer ein anämisches Domain Model ohne Logik wird.
Wenn ich an die vergeudete Zeit für ORM, XML, Annotationen und das Debuggen des generierten SQL denke, möchte ich weinen.
Die einfachen Teile sind ohnehin schon einfach und interessieren mich nicht besonders; stattdessen wurde die Arbeit oft millionenfach schwerer, weil ich genau in den schlimmsten Momenten, wenn Queries unter Last und Größe zusammenbrechen, zusätzlich noch mit dem ORM selbst kämpfen musste.
Query Builder sind nicht vollständig dasselbe wie ORMs, aber ich mag den Artikel https://gajus.medium.com/stop-using-knex-js-and-earn-30-bf41... und bin ein Fan von Technologien wie Slonik geworden.
Sie liefern 90 % der Funktionen, die ich haben will, etwa automatisches Binden der Ergebnisse an Objekte und starke Typprüfung, lassen mich aber einfach normales SQL schreiben.
Ich verstehe auch nicht, warum SQL als mysteriös schwierige Sprache gilt. Sie ist alt und hat Schwächen, aber bevor ich eine eigens von ORM-Tools erfundene Query-Sprache lerne, lerne ich lieber SQL.
Damals blickten andere Entwickler auf einen herab, wenn man solche Kritik äußerte.
Auch heute gibt es als Entwickler viele Werkzeuge und Techniken, die man widerwillig benutzen muss und die Antipatterns sind; die unglückliche Realität der Branche ist, dass viele weit verbreitete Tools nicht besonders gut sind und Antipatterns sogar fördern.
In der Tech-Branche gibt es eine kleine Zahl gut vernetzter Entwickler und Ex-Entwickler mit Entscheidungsmacht, und ich habe das Gefühl, dass sie nicht besonders gut sind.
Es gibt auch ORMs mit einem vernünftigen Verhältnis von Vor- und Nachteilen, besonders im Python-Umfeld.
Das Django ORM ist grob und nicht besonders performant, aber gut integriert, praktisch, produktiv und angenehm in der Nutzung.
Peewee bietet ORM in einem kleinen Paket, sodass man kleine Programme angenehm schreiben kann, wenn man keine großen Funktionen braucht und sich nicht lange damit herumschlagen will.
SQLAlchemy erfordert mehr Investition, ist aber sehr flexibel, erzeugt sauberes SQL und funktioniert korrekt.
Es stellt auch einen Low-Level-Query-Builder bereit, für Fälle, in denen man kein objektorientiertes Paradigma will, sondern idiomatisches SQL-Verhalten abstrahiert in Python ausdrücken möchte.
Am Ende ist es einfach eine normale Engineering-Entscheidung nach Return on Investment.
Ich mache das seit über zehn Jahren, aber es gab keine Query, die sich nicht besser lösen ließ, wenn man fünf Minuten die Hibernate-Dokumentation liest und dann genau das tut, was dort für den Fall empfohlen wird.
Es wirkt, als wollten SQL-Fanboys, die glauben, jeder Entwickler müsse Dreiwertigkeits-Logiktabellen und COBOL-artige Funktionsnamen auswendig kennen, sich ausgerechnet nicht die Mühe machen, die Hibernate-Dokumentation zu lesen.
ORMs sind für OLTP-Workloads gedacht, nicht für OLAP, und das hat auch einer der Hibernate-Gründer so gesagt.
Der Hauptnutzen besteht nur darin, dass man lange, fehleranfällige INSERT-/UPDATE-Queries nicht von Hand schreiben muss und SQL-Zeilen automatisch auf Objekte gemappt werden.
Wenn man auf den raw-Ansatz geht, implementiert man vieles davon wieder selbst; auch das ist also kein Nullsummenspiel.
In hinreichend komplexen Apps entsteht irgendwann so etwas wie ein Query Builder, bei dem mehrere Teile der App gemeinsam Queries verzögert zusammensetzen können
Die Struktur läuft darauf hinaus, Daten nicht im Speicher zusammenzuführen, zu filtern und zu sortieren, sondern dies per Query zu kombinieren
Ein ORM ist ein Werkzeug, mit dem sich so etwas leicht bauen lässt, kann einen aber auch unabsichtlich ins Knie schießen lassen, weil man damit leicht N+1-Queries erzeugt
Wie bei jedem Werkzeug muss man die Trade-offs zusammen mit dem tatsächlichen Anwendungsfall abwägen, und SQL-Strings direkt zusammenzumanipulieren würde ich in keinem Fall empfehlen
Trotzdem gibt es immer Leute, die diese Unterschiede ignorieren und absolut behaupten, ORMs seien gut oder schlecht
Das sollte man besser als provokante Haltung zur Aufmerksamkeitserzeugung abhaken und sich auf Diskussionen konzentrieren, die bei „ORMs haben Vorteile, aber man muss wissen, wo sie gelten, und darauf achten, dass die Nachteile in der Nutzung die Vorteile nicht überwiegen“ anfangen
Wenn Daten benötigt werden, geht man zur Datenzugriffsschicht, und wenn diese das Benötigte nicht bereitstellt, erstellt man ein neues Repository oder einen Provider oder etwas anderes, das zum gewählten Muster passt
Ob ORM oder selbstgebauter Query-Kombinierer: Wenn eine App so weit ist, dass man sich einredet, sie sei „hinreichend komplex und brauche das“, ist sie bereits zu komplex, um noch stabil nutzbar zu sein
Am Ende bewertet man den Builder auf der falschen Schicht oder übersieht beim Iterieren über Ergebnisse, dass man N+1-Queries erzeugt
Ein ORM ist nicht nötig
LINQ ist nicht exakt ein ORM; wenn man stark typisierte LINQ-Ausdrücke erstellt, werden sie in Ausdrucksbäume umgewandelt, die dann von einem Query-Provider wieder in Queries übersetzt werden
Während der Entwicklung bevorzuge ich die Lesbarkeit eines ORMs innerhalb des Modells, beobachte aber bei Bedarf N+1 und andere Ineffizienzen sehr genau und optimiere dann
Wo genau „bei Bedarf“ beginnt, ist nicht klar, aber ich versuche, nicht zu früh zu optimieren
Bei neuen Projekten beginne ich eher von der Datenbank aus und verschaffe mir vor dem Coden mit Factorys, Seedern und raw-SQL-Queries ein Gefühl für das Datenmodell
Ein ORM wie Eloquent von Laravel hat gute Methoden, um N+1 zu lösen und Lazy Loading auszuführen, aber es gibt immer Trade-offs
Statt Bibliotheken, die verzögerte Query-Komposition erlauben, schreibt man die Query direkt, und die Bibliothek generiert zur Compile-Zeit den Code für genau diese Query
Man schreibt zum Beispiel eine Query wie
getUser: SELECT * FROM users WHERE id = ?, und daraus werden eine KlasseGetUserQueryund eine Methode wiegetUser(id: String): GetUserQueryResulterzeugt; dieses Modell halte ich für deutlich besserMein Hauptproblem mit ORMs ist, dass sie moderne SQL-Engines oft wie übertrieben dumme Bit-Speicher behandeln
CTEs, LATERAL-Joins und RETURNING-Klauseln können die Verarbeitung stark vereinfachen oder die Möglichkeit von Dateninkonsistenzen beseitigen, trotzdem bleiben ORMs meist dabei, Basistabellen und Views nur simpel auf vordefinierte Objekte abzubilden
Wenn das ORM sogar die Tabellen erstellt, wird es noch schlimmer
SQL ist im Kern ein Werkzeug zur Datengewinnung und zugleich eine Transformationssprache, aber ORMs ignorieren diese Seite fast vollständig, sodass viele Entwickler gar nicht wissen, dass SQL mehr bietet als INSERT/SELECT/UPDATE/DELETE
Es gibt Pivot-Tabellen, temporale Abfragen, CUBE/ROLLUP, Window Functions, mengenrückgebende Funktionen, materialisierte Views, externe Tabellen, JSON-Verarbeitung, Datumsverarbeitung, Exclusion Constraints, Typen wie Range/Intervall/Domain, Row-Level Security, MERGE und vieles mehr
Das ist, als hätte man eine komplette Werkstatt, aber jemand reicht einem nur je einen Hammer, Schraubendreher und eine Metallsäge und redet einem ein, das reiche völlig aus, während man die Karriere verbringt, ohne zu ahnen, dass nur ein paar Meter weiter Tischsäge, Oberfräse, Schleifer und ein Satz Keile stehen
Ein ORM bringt einen zwar meist dazu, in einfachen CRUD-Statements zu denken, aber vielleicht ist genau das besser und fortgeschrittene Features sollten sparsam eingesetzt werden
Selbst wenn ich eine DB benutze, versuche ich absichtlich, nur einen sehr kleinen Teil der DB-Funktionen zu verwenden
Denn „Code“ ist ein Bereich, den man kontrollieren kann, während die „Datenbank“ ein gefährlicher, schwer greifbarer Bereich ist, in dem Fehler erst später in langsamen Integrationstests oder ähnlichem sichtbar werden
Logik, die innerhalb der DB passiert, liegt außerhalb der Reichweite von Low-Level-Tests und ist mir deshalb unheimlich; wahrscheinlich würde ich nicht einmal
select-from-select-Queries verwendenAuf den Großteil der Werkstatt würde ich gern verzichten
Die meiste Zeit ging dafür drauf, ausgefeilte Umgehungslösungen zu bauen, um grundlegende Schutzmechanismen für Datenintegrität neu zu erfinden
Seine eigene Datenbank zu bauen mag zum Lernen Spaß machen, aber nicht für Produktionsanwendungen
ActiveRecord hat sich immer gut angefühlt
Es gibt einige Ausnahmen, aber es trifft den 80/20-Punkt gut, man kann bei Bedarf zu SQL ausbrechen, und die Lifecycle-Hooks zum Organisieren von Domänenlogik sind großartig und leicht zu verstehen
Praktische ORMs, die nicht alles hinter „Magie“ verstecken oder eine eigene Query-Sprache einführen, sind gut
Schwer handhabbar sind die ORMs, die versuchen, das ORM-Problem vollständig zu „lösen“
So sollte ein ORM gebaut sein
Um es aber richtig zu verwenden, braucht man gute SQL-Vorkenntnisse
Probleme entstehen, wenn Leute SQL nicht lernen und die von AR erzeugten Queries sowie seine Grenzen nicht verstehen
Die Prämisse ist falsch. Ein ORM war nie eine „schädliche Idee“.
Es gibt ORMs, mit denen die Zusammenarbeit schrecklich ist, aber das bedeutet nicht, dass das ganze Genre eine schlechte Idee ist.
SQLAlchemy nutze ich seit Jahren gern, weil es nicht versucht, das Konzept von SQL selbst neu zu erfinden.
Stattdessen bietet es eine praktische Schicht zum Erstellen und Übergeben von Queries und kümmert sich sauber um die kleinen Details, sodass man nicht selbst daran herumfummeln muss.
Während ich zuletzt Rust gelernt habe, fühlte es sich schmerzhaft und wie Zeitverschwendung an, Boilerplate für einfaches CRUD selbst zu schreiben.
Das SQLAlchemy-ORM kann bei komplexeren oder zu optimierenden Queries etwas im Weg sein, aber in solchen Fällen kann man jederzeit direkt auf SQL heruntergehen.
Wie bei allem gibt es Situationen, in denen es gut passt, und solche, in denen es das nicht tut, und Technologie lässt sich leicht überstrapazieren oder falsch einsetzen.
ORMs wie zum Beispiel Entity Framework in .NET können ein großer Gewinn sein, besonders wenn man mit einem Database-First-Ansatz arbeitet.
Wenn man eine DB mit Hunderten von Tabellen und korrekt angelegten Fremdschlüsselbeziehungen hat, hilft ein ORM dabei, ein komplexes Schema zu durchdringen und bei Änderungen Prüfungen zur Compile-Zeit zu bekommen.
Eingebettetes SQL ist ein zweischneidiges Schwert, das wie ein Performance-Vorteil wirken mag, aber besonders bei Joins ist hart kodiertes, ausuferndes SQL sehr schwer wartbar.
Gemeint sind nicht 5 bis 10 Tabellen, sondern Hunderte davon.
Ich will niemanden überzeugen, aber man sollte nicht einfach alles glauben, was man im Internet über Best Practices liest.
Es kann gut sein, dass Leute über völlig unterschiedliche Dinge sprechen, und es gibt schlechte Entwickler, egal welche Technologie man verwendet.
Wenn man kein ORM oder anderes DB-Interface verwendet, schreibt und pflegt man am Ende selbst eines für Dinge wie CRUD.
Und darin landen dann mit hoher Wahrscheinlichkeit seltsame Bugs, Edge Cases und Sicherheitslücken.
Es ist auch problematisch, wenn Prinzipien wie SOLID in Universitätskursen als Prinzipien des Softwaredesigns gelehrt werden.
In der Wissenschaft ergibt das Sinn, weil dort Randbedingungen wie Zeit, Wartbarkeit, Geld und Aufwand weniger wichtig sind, aber wenn frische Absolventen in die Praxis kommen, führt das zu einem sehr unangenehmen Aufprall.
Sie sind daran gewöhnt, den ganzen Tag Yak Shaving zu betreiben und das Rad neu zu erfinden, um eine „perfekte“ Lösung zu finden.
Wenn es nicht genug fähige Senior-/Lead-Entwickler gibt, die das einfangen, bekommt man sehr interessante Produkte, Budgetüberschreitungen, Großbrände oder eine Kombination daraus.
Noch schlimmer ist es, wenn etwas, das in der Wissenschaft entwickelt und für die Wissenschaft entworfen wurde, auf die breite Öffentlichkeit losgelassen wird.
Ein typisches gutes/schlechtes Beispiel ist OpenStack: Es hat so viele Hebel und Stellschrauben und seine Komponenten sind wahnsinnig modularisiert, damit es die Spezialumgebungen von CERN und Hunderten von Universitäten unterstützen kann, aber es ist so byzantinisch, dass der Einstieg nahezu unmöglich ist.
ORM macht den Wechsel der Datenbank nicht mühelos, nimmt einem nicht die Notwendigkeit ab, das erzeugte SQL zu lernen und zu verstehen, und glättet auch das Schema nicht.
Trotzdem nutzt man es, weil es eine Standardabstraktion ist, die man sonst ohnehin duplizieren müsste.
Es macht Caching von DB-Zugriffen möglich, was mit manuellem SQL mit wachsender Größenordnung überraschend schwierig wird.
Dazu kommen standardisierte Werkzeuge und Best Practices, die Probleme wie N+1 irrelevant machen können.
Das Hauptproblem bei ORM sind falsche Erwartungen und schlechte ORMs.
Wenn man den Wert von ORM verstehen will, öffnet man einfach ein Projekt, das ohne ORM geschrieben wurde, und versucht, irgendetwas daran zu ändern.
Siehe https://news.ycombinator.com/item?id=36498583.
Dadurch kamen nützliche Dinge nicht voran oder dauerten 20- bis 100-mal länger als ein schneller, schmutziger Ansatz.
Am schlimmsten war ein Fall, in dem ein Team erfahrener HTML-Designer gezwungen wurde, funktionale Programmierung zu lernen.
Der Backend-Konfigurationszauber war ein Wunderwerk moderner Ingenieurskunst und eleganten Designs, aber 10 Leute haben ein Jahr dafür gebraucht.
VC-Geld macht Menschen seltsam.
Die SQL-Sprache ist sehr komplex, und einen ordentlichen, voll funktionsfähigen Query Builder zu bauen, ist wirklich alles andere als trivial.
Das gilt selbst dann, wenn man den eigentlichen relationalen Mapping-Teil außen vor lässt.
Ich denke, SQL ist ein Fall von „programmiere den verdammten Kram einfach direkt“
Es hat wenig Sinn, SQL oder ORM-Bibliotheken zu lernen; es ist besser, SQL direkt zu lernen und zu verwenden
Datenbankzugriff ist wahrscheinlich eine grundlegende Aufgabe, die einen die ganze Karriere begleitet, daher ist es am besten, die eigentliche Technik direkt zu lernen
Bei CSS ist es ähnlich: Statt CSS-Bibliotheken zu lernen, sollte man CSS selbst lernen und verwenden
Eigentlich gilt das für fast alle Aspekte der Frontend-Entwicklung, und statt einer „Form-Library“ kann man direkt mit der Form-API des Browsers arbeiten
Für mich persönlich war SQL viel leichter zu lernen als jedes ORM
Man sollte keine Kosten darauf verschwenden, etwas Falsches zu lernen
Bei CSS ist es genauso: Wenn man CSS kennt, ist man viel flexibler und versteht besser, wie man Bibliotheken aus Bequemlichkeit auswählt
Über Mainframes, Desktops, Client/Server, das Web und die vielen Sprachen auf diesen Plattformen hinweg war SQL immer der gemeinsame Faden
Ich stimme völlig zu, dass Entwickler, die die Datenschicht und das, was darunter passiert, gut verstehen, stärkere Entwickler sind
Wenn man ohnehin Zeit darauf verwenden will, die Eigenheiten eines ORMs zu lernen, warum diese Zeit nicht stattdessen in SQL investieren? Das ist die klassische Frage
Der Zinseszinseffekt von SQL-Erfahrung dürfte in 10–15 Jahren wertvoller sein als das ORM einer bestimmten Plattform oder Sprache
Es gibt Gründe, ORMs zu lernen und zu verwenden, aber man sollte sich nicht nur deshalb in Richtung ORM bewegen, weil man SQL nicht lernen will
Nur dann weiß man, welchen Preis man für diese Abstraktion zahlt. Außer natürlich, es handelt sich um eine „Zero-Cost-Abstraction“
Heute nutze ich jedoch
crudvonazer, das wegen des Marshalling/Unmarshalling mit Go-Typen als ORM eingeordnet werden könnteDie Go-Standardbibliothek
sqlist so elementar, dass man Objekt-Marshalling/Unmarshalling praktisch selbst schreiben muss, und das ist wirklich langweiligWenn ich heute ein ORM verwenden würde, dann wahrscheinlich nur für genau diesen Zweck
Ich mag Mikro-ORMs als „Mittelweg“ wie Dapper oder Diesel
Man schreibt die Queries in SQL, bekommt aber starke Typisierung und automatisches Objekt-Mapping der Result Sets
Man erhält also Produktivität zusammen mit einer vollwertigen „echten“ Query-Sprache
Außerdem mag ich inzwischen den Ansatz, Objekt-Mapper nur für Read-only-Queries zu verwenden
Updates erfolgen per Command-Pattern, also über Stored Procedures, die man so mappen kann, dass sie wie native Methoden aussehen
Entwickler sollten nicht so tun, als gäbe es SQL nicht, sondern es einfach akzeptieren
Eloquent abstrahiert diese Routinearbeiten ausreichend, sodass ich mich auf die Logik konzentrieren kann
Ich schreibe gerade eine „alte“ PHP-App, die nur aus Arrays und Queries besteht, auf eine Struktur mit Modellen und Eloquent um, und es fühlt sich nach einem kompletten Gamechanger an
Früher, als ich SQLite unter .NET verwendet habe, habe ich sogar selbst eine Wrapper-Bibliothek in diese Richtung gebaut: https://github.com/zmj/sqlite-fast
Dieser Thread zeigt sehr gut die Mindshare-Dominanz von ORMs
In fast allen Kommentaren ist die implizite Alternative zum ORM rohes SQL als String-Literal im App-Code
Schon vor 6 Jahren gab es Tools, die SQL als eigene Sprache verwenden und Wrapper generieren, die Queries der App als Methoden bereitstellen
Dinge wie queryfirst, pgtyped, pugsql und sqlc
Das war ein Paradigmenwechsel oder hätte zumindest einer werden können, und es zeigt sich, dass es eine klar überlegene Art zu arbeiten ist; aber ORMs und diese unveränderliche Diskussion saugen den ganzen Sauerstoff auf, sodass das am Rand bleibt
SQL ist eine Sprache, und zwar eine Sprache auf sehr hohem Niveau
SQL in einer noch niedrigeren Sprache zusammenzustückeln ist ein Paradebeispiel für „wenn man einen Hammer hat, sieht jedes Problem wie ein Nagel aus“
Wenn man zum Beispiel in einer Low-Level-Sprache wie Assembler codiert und mit einem großen System interagiert, dessen Dokumentation sagt, dass Eingaben nur in JavaScript ausgedrückt werden können, dann hat man eine Wahl
Man kann eine obskure Bibliothek holen, mit der man in reinem Assembler irgendetwas zusammenstückelt und dann keine
xxx.js-Datei ins Repository committen muss, oder man drückt es einfach als.js-Datei aus und nutzt die Stärke der High-Level-SpracheMan bekommt eine Single Source of Truth für die verwendeten SQL-Queries, und weil das, was man tatsächlich schreibt und pflegt, die Queries selbst sind, werden Optimierungen wie das Anlegen neuer Indizes ebenfalls einfacher
Eine Abstraktion über rohe SQL-Strings zu legen ist sehr nützlich, aber Relationen so zu behandeln, als wären sie Objekte, ist ein unnötig verworrener Ansatz
TopLink wahrscheinlich auch
So wurde damals das Mapping zwischen Stored Procedures und lokalen Entitäten gehandhabt