it-swarm.com.de

Warum brauche ich kein ORM in einer funktionalen Sprache wie Scala?

Ich frage mich, ob ich in einem Spring + Hibernate-Projekt von Java zu Scala wechseln kann, um einige Scala -Funktionen wie Pattern Matching, Option und zu nutzen Was mir scheint, ist eine sauberere Syntax im Allgemeinen. Ich habe standardmäßig im Scala Ökosystem nach ORM gesucht und dabei Gedanken wie Aktivieren gefunden (aber meistens versuche ich herauszufinden, ob Hibernate mit Scala verwendet werden kann). Auf der Suche danach habe ich dies in der Spieldokumentation über JPA + Scala gelesen.

Der wichtigste Punkt ist jedoch: Benötigen Sie wirklich einen Mapper für die Beziehung zu Objekten, wenn Sie die Fähigkeit einer funktionalen Sprache haben? Wahrscheinlich nicht. JPA ist eine bequeme Möglichkeit, die mangelnde Leistungsfähigkeit von Java bei der Datentransformation zu abstrahieren. Es fühlt sich jedoch wirklich falsch an, wenn Sie es von Scala aus verwenden.

Ich habe kein tiefes Verständnis dafür, wie man funktionale Programmierung verwendet, um eine vollständige Anwendung zu erstellen (deshalb beabsichtige ich, Scala zu verwenden, damit ich dies schrittweise verstehen kann, da es OOkombiniert. _ + Functional), daher kann ich nicht herausfinden, warum ich kein ORM mit einer funktionalen Sprache benötige und wie der funktionale Ansatz zur Bekämpfung der Persistenz des Domänenmodells aussehen würde.

Ein DDD-Ansatz für die Geschäftslogik macht bei Scala immer noch Sinn, nicht wahr?

30
gabrielgiussi

Nun, eine Sache, die wichtig ist, wenn wir eine Diskussion wie diese haben, ist die klare Unterscheidung zwischen objektrelationalen Mappern ("ORM") und Datenbankabstraktionsschichten) . Ein ORM ist eine Art Datenbankabstraktionsschicht, aber nicht alle Datenbankabstraktionsschichten sind ORMs. Ein gutes Werkzeug, um dies zu verstehen, ist Pythons beliebte SQLAlchemy -Bibliothek, die sich selbst als "SQL Toolkit und Object Relational Mapper" bezeichnet "(mein kühnes Gesicht), mit der Idee, dass dies verschiedene Dinge sind. Wie sie es auf ihrer Seite mit den wichtigsten Funktionen angegeben haben:

Kein ORM erforderlich

SQLAlchemy besteht aus zwei unterschiedlichen Komponenten, die als Core und [~ # ~] orm [~ # ~] bekannt sind. Der Core selbst ist ein voll ausgestattetes SQL-Abstraktions-Toolkit, das eine reibungslose Abstraktionsebene über eine Vielzahl von DBAPI-Implementierungen und -Verhalten bietet sowie eine SQL-Ausdruckssprache, die den Ausdruck der SQL-Sprache über generative Python - Ausdrücke ermöglicht. Ein Schemadarstellungssystem, das sowohl DDL-Anweisungen ausgeben als auch vorhandene Schemas überprüfen kann, und ein Typsystem, das die Zuordnung von Python - Typen zu Datenbanktypen ermöglicht, runden das System ab. Der Object Relational Mapper ist dann ein optionales Paket, das auf dem Core aufbaut.

Die Startseite beschreibt das ORM folgendermaßen:

SQLAlchemy ist am bekanntesten für seinen objektrelationalen Mapper (ORM), eine optionale Komponente, die das Daten-Mapper-Muster bereitstellt, bei dem Klassen auf verschiedene Arten offen auf die Datenbank abgebildet werden können, sodass sich das Objektmodell und das Datenbankschema in a entwickeln können von Anfang an sauber entkoppelt.

Die Schlüsselidee eines ORM besteht darin, die berühmte objektrelationale Impedanzfehlanpassung zu überbrücken. Dies bedeutet, Beziehungen zwischen benutzerdefinierten Klassen zu Tabellen in einem Datenbankschema zu definieren und automatische "Speichern" - und "Laden" -Operationen für die Klassen Ihrer Anwendung bereitzustellen.

Im Gegensatz dazu sind Nicht-ORM-Datenbankabstraktionsschichten eher dem relationalen Datenmodell und SQL verpflichtet und überhaupt nicht der Objektorientierung. Anstatt "Zuordnungen" zwischen Tabellen und Klassen zu verwenden und das Datenbankschema vor dem Programmierer auszublenden, neigen sie dazu, die Datenbank dem Programmierer zur Verfügung zu stellen , jedoch mit besseren APIs und Abstraktionen. Mit SQL-Abfrageerstellern können Sie beispielsweise komplexe SQL-Abfragen programmgesteuert und ohne Manipulation von Zeichenfolgen generieren. Dies ist ( ein Beispiel aus der jOOQ-Bibliothek für Java ):

// Typesafely execute the SQL statement directly with jOOQ
Result<Record3<String, String, String>> result =
    create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
          .from(BOOK)
          .join(AUTHOR)
          .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID))
          .where(BOOK.PUBLISHED_IN.equal(1948))
          .fetch();

Nun, scheint das Play-Framework nicht zu 100% mit dem übereinzustimmen, was ich gerade beschrieben habe , aber ihr Argument scheint in diesem allgemeinen Bereich zu liegen: Arbeiten Sie direkt mit dem relationalen Modell anstatt es in Klassen und zurück von ihnen zu übersetzen.

Die jOOQ-Bibliothek ist als Kontrapunkt zu ORMs zu studieren. Sie haben auch einige relevante Blogeinträge, die eine Lektüre wert sind:

30
sacundim

Es ist schwer zu erklären, bis Sie viel funktionale Programmierung durchgeführt haben. Bei der objektorientierten Programmierung bleiben Ihre Daten in einem Objekt stecken und bleiben dort. Dieses Objekt wird ein wenig herumgereicht und ziemlich verändert, aber normalerweise arbeiten Sie während der gesamten Lebensdauer dieser Daten grundsätzlich mit derselben "Identität".

ORMs basieren im Allgemeinen auf diesem Paradigma. Sie rufen einige Daten aus der Datenbank ab, mischen sie in ein Objekt, ändern sie möglicherweise ein paar Mal, und wenn Sie fertig sind, haben Sie immer noch dasselbe Objekt, das Sie in die Datenbank zurückschreiben können.

Die funktionale Programmierung funktioniert anders. Ihre Daten behalten während ihrer gesamten Lebensdauer keine einzige Identität. Es wird aufgeteilt, kopiert, geteilt und transformiert. Es durchläuft eine Reihe von Funktionen und wird schließlich wieder in das von Ihnen benötigte Ausgabeformular zusammengesetzt. Damit sich eine Datenbank-API in einer funktionalen Sprache natürlich anfühlt, muss dies berücksichtigt werden, JPA jedoch nicht.

20
Karl Bielefeldt

In scala ist es immer noch nützlich, Datenbanktabellen Objekten zuzuordnen, und es gibt verschiedene Möglichkeiten, dies zu tun.

Ein beliebtes Framework in der Welt von Scala ist slick . Es ist kein ORM, weil es weniger tut (nämlich keine Beziehungen abruft, ohne dazu aufgefordert zu werden) explizit beitreten).

Sie ordnen Objekte also weiterhin Datenbankzeilen zu, aber Ihre Objekte sind unveränderlich (daher keine Statusbereinigung), und Sie führen Abfragen explizit mit einem monadischen DSL aus. Das Ergebnis ist, dass Sie viele der "guten" Teile eines ORM erhalten, ohne die Probleme mit der Veränderbarkeit und unvorhersehbaren N + 1-Problemen.

Man sollte beachten, dass Menschen mit viel dünneren Bibliotheken wie anorm oder auch direktem JDBC große Erfolge erzielt haben, indem sie funktionale Techniken verwenden, um den Code schön zu halten.

Eine fantastische Bibliothek, die funktionale Techniken zusätzlich zu JDBC anwendet, ist auch doobie .

Sie haben also viele Möglichkeiten für den Datenbankzugriff, aber der Ruhezustand (der de facto das ORM zu sein scheint) ist nicht der beste, da er auf Mutabilität ausgerichtet ist.

10
triggerNZ

Sie benötigen kein ORM, auch nicht in objektorientierten Sprachen.

Erstens, wer hat gesagt, dass Ihre Daten physisch von Ihrem dauerhaften Speicher auf Ihr Objekt kopiert werden sollten? Alan Kay , ein Mann hinter Smalltalk, wollte Objekte, um Daten loszuwerden . Er schlug vor, dass ein Objekt nur einen Verweis auf einen Bereich haben kann, in dem seine Daten gespeichert sind.

Zweitens - wie kann man das am besten erreichen? Ich empfehle identifizieren Sie Ihre Objekte anhand ihrer Verantwortlichkeiten und nicht an Daten zu denken, die sie besitzen. Wenn Sie von CRC-Karten gehört haben, wird es genau dafür verwendet.

Und schließlich, für den Fall, dass Sie jemals zum OO-Feld zurückkehren, hier ein Möglichkeit, es zu implementieren .

0
Zapadlo