Warum hassen alle Active Record? [geschlossen]


103

Während ich mehr und mehr über OOP lerne und verschiedene Entwurfsmuster implementiere, komme ich immer wieder auf Fälle zurück, in denen Menschen Active Record hassen .

Oft sagen die Leute, dass es nicht gut skaliert (unter Berufung auf Twitter als Paradebeispiel) - aber niemand erklärt tatsächlich, warum es nicht gut skaliert. und / oder wie man die Vorteile von AR ohne die Nachteile erreicht (über ein ähnliches, aber anderes Muster?)

Hoffentlich wird dies nicht zu einem heiligen Krieg um Designmuster - alles, was ich wissen möchte, ist **** speziell ****, was mit Active Record nicht stimmt.

Wenn es nicht gut skaliert, warum nicht?

Welche anderen Probleme hat es?


9
Ich denke im Allgemeinen ist viel Hass und Abneigung gegen Designmuster mit falschem Gebrauch verbunden. Menschen neigen dazu, sie im falschen Kontext zu überbeanspruchen und zu verwenden, und erhalten am Ende eine komplexere Lösung als das Original
Terjetyl

1
Rubys Active Record-Implementierung ähnelt eher einem ORM.
Jimmy T.

1
Es gibt ein soziales Phänomen, das darin besteht, Wertschätzung, mehr Anerkennung zu erlangen, klüger und blutiger zu wirken. Menschen neigen dazu, jeden Hype der Negation eines aktuellen Standards, Modells oder weit verbreiteter Technologien mechanisch zu wiederholen und ihn mit dem zu verwechseln revolutionärer Fortschritt zur nächsten Welle.
Andre Figueiredo

Antworten:


90

Es gibt ActiveRecord, das Entwurfsmuster, und ActiveRecord, die Rails-ORM-Bibliothek , und es gibt auch eine Menge Nachahmungen für .NET und andere Sprachen.

Das sind alles verschiedene Dinge. Sie folgen größtenteils diesem Entwurfsmuster, erweitern und modifizieren es jedoch auf viele verschiedene Arten. Bevor also jemand "ActiveRecord Sucks" sagt, muss es qualifiziert werden, indem er sagt: "Welcher ActiveRecord, es gibt Haufen?"

Ich bin nur mit Rails ActiveRecord vertraut. Ich werde versuchen, alle Beschwerden zu bearbeiten, die im Zusammenhang mit der Verwendung von Rails vorgebracht wurden.

@BlaM

Das Problem, das ich bei Active Records sehe, ist, dass es immer nur um eine Tabelle geht

Code:

class Person
    belongs_to :company
end
people = Person.find(:all, :include => :company )

Dadurch wird SQL mit LEFT JOIN companies on companies.id = person.company_idund automatisch zugehörige Unternehmensobjekte generiert, sodass Sie dies tun können people.first.companyund die Datenbank nicht aufgerufen werden muss, da die Daten bereits vorhanden sind.

@ pix0r

Das inhärente Problem bei Active Record besteht darin, dass Datenbankabfragen automatisch generiert und ausgeführt werden, um Objekte zu füllen und Datenbankdatensätze zu ändern

Code:

person = Person.find_by_sql("giant complicated sql query")

Dies wird nicht empfohlen, da es hässlich ist. In den Fällen, in denen Sie einfach nur SQL schreiben müssen, ist dies jedoch problemlos möglich.

@ Tim Sullivan

... und wenn Sie mehrere Instanzen des Modells auswählen, führen Sie im Grunde ein "select * from ..."

Code:

people = Person.find(:all, :select=>'name, id')

Dadurch werden nur die Namens- und ID-Spalten aus der Datenbank ausgewählt. Alle anderen 'Attribute' in den zugeordneten Objekten sind nur Null, es sei denn, Sie laden das Objekt manuell neu und so weiter.


Mächtig! Ich wusste nichts über diese spezielle Funktion. Noch ein Pro-AR-Argument für mich, das ich in mein Arsenal aufnehmen möchte.
Tim Sullivan

Das Beitreten geht über das Active Record-Muster hinaus.
Jimmy T.

"Person.find_by_sql" ist überhaupt kein Active Record-Muster. Es ist so ziemlich "Active Record" fehlgeschlagen, also muss ich es manuell patchen.
Magallanes

52

Ich habe immer festgestellt, dass ActiveRecord für schnelle CRUD-basierte Anwendungen geeignet ist, bei denen das Modell relativ flach ist (wie in nicht vielen Klassenhierarchien). Für Anwendungen mit komplexen OO-Hierarchien ist ein DataMapper jedoch wahrscheinlich die bessere Lösung. Während ActiveRecord ein 1: 1-Verhältnis zwischen Ihren Tabellen und Ihren Datenobjekten annimmt, wird diese Art von Beziehung bei komplexeren Domänen unhandlich. In seinem Buch über Muster weist Martin Fowler darauf hin, dass ActiveRecord unter Bedingungen, unter denen Ihr Modell ziemlich komplex ist, zum Zusammenbruch neigt, und schlägt als Alternative einen DataMapper vor .

Ich habe festgestellt, dass dies in der Praxis zutrifft. In Fällen, in denen Ihre Domäne häufig vererbt wird, ist es schwieriger, die Vererbung Ihrem RDBMS zuzuordnen, als Assoziationen oder Zusammensetzungen zuzuordnen.

Ich habe "Domain" -Objekte, auf die Ihre Controller über diese DataMapper-Klassen (oder "Service Layer") zugreifen. Diese spiegeln die Datenbank nicht direkt wider, sondern dienen als OO-Darstellung für ein reales Objekt. Angenommen, Sie haben eine Benutzerklasse in Ihrer Domäne und müssen Verweise auf oder Sammlungen anderer Objekte haben, die bereits geladen wurden, wenn Sie dieses Benutzerobjekt abrufen. Die Daten stammen möglicherweise aus vielen verschiedenen Tabellen, und ein ActiveRecord-Muster kann es sehr schwierig machen.

Anstatt das Benutzerobjekt direkt zu laden und über eine ActiveRecord-API auf Daten zuzugreifen, ruft Ihr Controller-Code ein Benutzerobjekt ab, indem Sie beispielsweise die API der UserMapper.getUser () -Methode aufrufen. Es ist dieser Mapper, der dafür verantwortlich ist, alle zugeordneten Objekte aus ihren jeweiligen Tabellen zu laden und das fertige Benutzerdomänenobjekt an den Aufrufer zurückzugeben.

Im Wesentlichen fügen Sie nur eine weitere Abstraktionsebene hinzu, um den Code besser verwalten zu können. Ob Ihre DataMapper-Klassen benutzerdefiniertes SQL enthalten oder eine API für die Datenabstraktionsschicht aufrufen oder sogar selbst auf ein ActiveRecord-Muster zugreifen, spielt für den Controller-Code, der ein nettes, ausgefülltes Benutzerobjekt empfängt, keine Rolle.

Jedenfalls mache ich das so.


5
Klingt so, als wären Sie mit ActiveRecord einfach nicht vertraut. "ActiveRecord geht von einem Verhältnis von 1: 1 zwischen Ihren Tabellen aus". Einfach gar nicht wahr. ActiveRecord bietet alle Arten von überragender relationaler Magie. Siehe api.rubyonrails.org/classes/ActiveRecord/Associations/…
tybro0103

16
@ JoãoBragança - vielleicht eher als ein sarkastischer Kommentar, könnten Sie tatsächlich die Schwierigkeiten erklären, die auftreten, wenn jemandes Daten gespalten werden - damit der Rest von uns etwas lernen kann :)
Taryn East

11

Ich denke, es gibt wahrscheinlich ganz andere Gründe, warum Leute ActiveRecord "hassen" und was daran "falsch" ist.

In Bezug auf das Thema Hass gibt es viel Gift für alles, was mit Rails zu tun hat. Was daran falsch ist, ist es wahrscheinlich, dass es wie jede Technologie ist und es Situationen gibt, in denen es eine gute Wahl ist, und Situationen, in denen es bessere Entscheidungen gibt. Nach meiner Erfahrung ist die Datenbank schlecht strukturiert, wenn Sie die meisten Funktionen von Rails ActiveRecord nicht nutzen können. Wenn Sie auf Daten ohne Primärschlüssel zugreifen und Dinge, die gegen die erste normale Form verstoßen und für die viele gespeicherte Prozeduren erforderlich sind, um auf die Daten zuzugreifen, ist es besser, etwas zu verwenden, das eher nur ein SQL-Wrapper ist. Wenn Ihre Datenbank relativ gut strukturiert ist, können Sie dies mit ActiveRecord nutzen.

Hinzufügen zum Thema Antworten auf Kommentatoren, die sagen, dass es in ActiveRecord schwierig ist, mit einer Gegenerwiderung aus einem Code-Snippet zu antworten

@Sam McAfee Angenommen, Sie haben eine Benutzerklasse in Ihrer Domäne und müssen Verweise auf oder Sammlungen anderer Objekte haben, die bereits geladen wurden, wenn Sie dieses Benutzerobjekt abrufen. Die Daten stammen möglicherweise aus vielen verschiedenen Tabellen, und ein ActiveRecord-Muster kann es sehr schwierig machen.

user = User.find(id, :include => ["posts", "comments"])
first_post = user.posts.first
first_comment = user.comments.first

Mit der Option include können Sie mit ActiveRecord das Standardverhalten beim verzögerten Laden überschreiben.


8

Meine lange und späte Antwort, nicht einmal vollständig, aber eine gute Erklärung, WARUM ich dieses Muster, diese Meinungen und sogar einige Emotionen hasse:

1) Kurzversion: Active Record erstellt eine " dünne Schicht " " starker Bindung " zwischen der Datenbank und dem Anwendungscode. Was keine logischen, keine Probleme löst, überhaupt keine Probleme. IMHO liefert es keinen Wert, außer etwas syntaktischem Zucker für den Programmierer (der dann eine "Objektsyntax" verwenden kann, um auf einige Daten zuzugreifen, die in einer relationalen Datenbank vorhanden sind). Die Bemühungen, den Programmierern einen gewissen Komfort zu bieten, sollten (IMHO ...) besser in Tools für den Datenbankzugriff auf niedriger Ebene investiert werden, z. B. einige Variationen einfacher, einfacher, einfacher hash_map get_record( string id_value, string table_name, string id_column_name="id" )und ähnlicher Methoden (natürlich variieren die Konzepte und die Eleganz stark mit den verwendete Sprache).

2) lange Version: In allen datenbankgesteuerten Projekten, in denen ich die "konzeptionelle Kontrolle" über die Dinge hatte, habe ich AR vermieden und es war gut. Normalerweise erstelle ich eine mehrschichtige Architektur (Sie teilen Ihre Software früher oder später in Schichten auf, zumindest in mittelgroßen bis großen Projekten):

A1) die Datenbank selbst, Tabellen, Beziehungen, sogar eine Logik, wenn das DBMS dies zulässt (MySQL ist jetzt auch erwachsen)

A2) Sehr oft gibt es mehr als einen Datenspeicher: Dateisystem (Blobs in der Datenbank sind nicht immer eine gute Entscheidung ...), Legacy-Systeme (stellen Sie sich vor, "wie" auf sie zugegriffen wird, viele Varianten möglich ... aber das ist es nicht der Punkt...)

B) Datenbankzugriffsschicht (auf dieser Ebene sind Werkzeugmethoden und Helfer für den einfachen Zugriff auf die Daten in der Datenbank sehr willkommen, aber AR bietet hier keinen Wert, außer etwas syntaktischem Zucker).

C) Anwendungsobjektschicht: "Anwendungsobjekte" sind manchmal einfache Zeilen einer Tabelle in der Datenbank, aber meistens handelt es sich ohnehin um zusammengesetzte Objekte, an die eine höhere Logik angehängt ist. Daher ist es einfach nutzlos, Zeit in AR-Objekte auf dieser Ebene zu investieren , eine Verschwendung wertvoller Codiererzeit, denn der "reale Wert", die "höhere Logik" dieser Objekte muss sowieso über den AR-Objekten implementiert werden - mit und ohne AR! Und warum möchten Sie beispielsweise eine Abstraktion von "Protokolleintragsobjekten" haben? App-Logikcode schreibt sie, aber sollte das die Möglichkeit haben, sie zu aktualisieren oder zu löschen? klingt albern und App::Log("I am a log message")ist einige Größen einfacher zu bedienen alsle=new LogEntry(); le.time=now(); le.text="I am a log message"; le.Insert();. Und zum Beispiel: Die Verwendung eines "Protokolleintragsobjekts" in der Protokollansicht in Ihrer Anwendung funktioniert für 100, 1000 oder sogar 10000 Protokollzeilen, aber früher oder später müssen Sie optimieren - und ich wette, in den meisten Fällen werden Sie es einfach tun Verwenden Sie diese kleine schöne SQL SELECT-Anweisung in Ihrer App-Logik (die die AR-Idee völlig zerstört ..), anstatt diese kleine Anweisung in starre feste AR-Ideenrahmen mit viel Code zu verpacken und zu verbergen. Die Zeit, die Sie mit dem Schreiben und / oder Erstellen von AR-Code verschwendet haben, hätte in eine viel cleverere Oberfläche zum Lesen von Listen mit Protokolleinträgen investiert werden können (auf viele, viele Arten ist der Himmel die Grenze). Codierer sollten es wagen, neue Abstraktionen zu erfinden , um ihre Anwendungslogik zu realisieren, die zur beabsichtigten Anwendung passt, und dumme Muster nicht dumm neu implementieren, das klingt auf den ersten Blick gut!

D) die Anwendungslogik - implementiert die Logik der Interaktion von Objekten und des Erstellens, Löschens und Auflistens (!) Von Anwendungslogikobjekten (NEIN, diese Aufgaben sollten selten in den Anwendungslogikobjekten selbst verankert sein: sagt das Blatt Papier auf Ihrem Schreibtisch Sie die Namen und Positionen aller anderen Blätter in Ihrem Büro? Vergessen Sie "statische" Methoden zum Auflisten von Objekten, das ist albern, ein schlechter Kompromiss, der geschaffen wurde, um die menschliche Denkweise in [einige-nicht-alle-AR-Framework-ähnliche] zu integrieren -] AR Denken)

E) Die Benutzeroberfläche - nun, was ich in den folgenden Zeilen schreiben werde, ist sehr, sehr, sehr subjektiv, aber meiner Erfahrung nach haben Projekte, die auf AR basieren, häufig den UI-Teil einer Anwendung vernachlässigt - Zeit wurde für die Erstellung obskurer Abstraktionen verschwendet . Am Ende haben solche Anwendungen viel Zeit für Codierer verschwendet und fühlen sich an wie Anwendungen von Codierern für Codierer, die innen und außen technisch orientiert sind. Die Programmierer fühlen sich gut an (harte Arbeit endlich erledigt, alles fertig und korrekt, gemäß dem Konzept auf Papier ...), und die Kunden "müssen nur lernen, dass es so sein muss", denn das ist "professionell". ok, sorry, ich schweife ab ;-)

Zugegeben, das alles ist subjektiv, aber es ist meine Erfahrung (Ruby on Rails ausgeschlossen, es kann anders sein, und ich habe keine praktische Erfahrung mit diesem Ansatz).

In bezahlten Projekten hörte ich oft die Forderung, zunächst einige "aktive Datensatz" -Objekte als Baustein für die übergeordnete Anwendungslogik zu erstellen. Nach meiner Erfahrung ist dies auffällig oftwar eine Art Entschuldigung dafür, dass der Kunde (in den meisten Fällen ein Softwareentwickler) kein gutes Konzept, keine große Sicht und keinen Überblick darüber hatte, was das Produkt letztendlich sein sollte. Diese Kunden denken in starren Rahmen ("in dem Projekt vor zehn Jahren hat es gut funktioniert ..."), sie können Entitäten ausarbeiten, sie können Entitätsbeziehungen definieren, sie können Datenbeziehungen auflösen und grundlegende Anwendungslogik definieren, aber dann hören sie auf und gib es dir und denke, das ist alles, was du brauchst ... ihnen fehlt oft ein vollständiges Konzept von Anwendungslogik, Benutzeroberfläche, Benutzerfreundlichkeit und so weiter ... ihnen fehlt die große Sicht und ihnen fehlt die Liebe für die Details, und sie möchten, dass Sie dieser AR-Art der Dinge folgen, denn ... nun, warum hat es in diesem Projekt vor Jahren funktioniert und die Leute beschäftigt und still gehalten? Ich weiß es nicht. Aber die "Details" trenne die Männer von den Jungen oder ... wie war der ursprüngliche Werbeslogan? ;-);

Nach vielen Jahren (zehn Jahre aktive Entwicklungserfahrung) läutet meine Alarmglocke, wenn ein Kunde ein "aktives Aufzeichnungsmuster" erwähnt. Ich habe gelernt, zu versuchen, sie in diese wesentliche Konzeptionsphase zurückzubringen , sie zweimal überlegen zu lassen, zu versuchen, ihre konzeptionellen Schwächen aufzuzeigen oder sie überhaupt zu vermeiden, wenn sie nicht erkennbar sind (am Ende wissen Sie, ein Kunde, der dies noch nicht tut weiß, was es will, denkt vielleicht sogar, dass es weiß, aber nicht, oder versucht, Konzeptarbeit kostenlos an MICH zu verlagern, kostet mich viele wertvolle Stunden, Tage, Wochen und Monate meiner Zeit, das Leben ist zu kurz ...).

Also endlich: DIESES ALLES ist der Grund, warum ich dieses alberne "aktive Aufnahmemuster" hasse, und ich tue es und werde es vermeiden, wann immer es möglich ist.

EDIT : Ich würde dies sogar als No-Pattern bezeichnen. Es löst kein Problem (Muster sollen keinen syntaktischen Zucker erzeugen). Es schafft viele Probleme: Die Wurzel all seiner Probleme (in vielen Antworten hier erwähnt ..) ist, dass es nur das gute alte, gut entwickelte und leistungsfähige SQL hinter einer Schnittstelle verbirgt, die nach der Musterdefinition extrem begrenzt ist.

Dieses Muster ersetzt Flexibilität durch syntaktischen Zucker!

Denken Sie darüber nach, welches Problem löst AR für Sie?


1
Es ist ein Architekturmuster für Datenquellen. Vielleicht sollten Sie Fowlers Patterns of Enterprise Application Architecture lesen? Ich hatte ähnliche Gedanken wie Sie, bevor ich das Muster / ORM tatsächlich verwendete und herausfand, wie sehr es die Dinge vereinfachte.
MattMcKnight

1
Ich teile deine Gefühle. Ich rieche etwas falsches, wenn ein Framework keine zusammengesetzten Schlüssel unterstützt. Ich habe jede Art von ORM vor SQLAlchemy vermieden und wir verwenden es oft auf einer niedrigeren Ebene als SQL-Generator. Es implementiert Data Mapper und ist sehr flexibel.
Marco Mariani

1
Seit zwei Tagen bin ich an einem Projekt beteiligt, das ORM auf dem neuesten Stand der Technik verwendet. Vielleicht sind die Implementierungen jetzt ausgereift (im Vergleich zu dem, mit dem ich vor einigen Jahren gearbeitet habe). Vielleicht wird sich meine Meinung ändern, wir werden in drei Monaten sehen :-)
Frunsi

2
Das Projekt ist abgeschlossen und weißt du was? ORM ist immer noch scheiße, ich habe so viel Zeit mit Mapping-Problemen verschwendet, die sich leicht relational zu einer Reihe von "objektorientiertem Code" ausdrücken lassen. Natürlich bot das ORM Möglichkeiten, Abfragen in einer Art OOP + SQL-Mix auszudrücken - natürlich in einer OOP-ähnlichen Syntax -, aber das dauerte nur länger als das einfache Schreiben einer SQL-Abfrage. Die durchgesickerte Abstraktion, das "OOPSQLExperiment" über OOP - es war die schlechteste Idee aller Zeiten, Benutzern das Schreiben von SQL in OOP-Syntax zu ermöglichen. Nein, nie wieder.
Frunsi

1
Ich habe viele Jahre lang Roh-SQL für alles geschrieben. Rails AR frustriert mich manchmal und für passive Abfragen stimme ich Ihnen fast zu, aber dies ist das, was es löst: 1) Das Speichern von Daten, bei denen die Validierung fehlschlägt, ist angemessen schwierig. 2) Verfolgen, was sich seit dem letzten Mal im Speicher geändert hat. 3) Verwenden von Punkt 2 zum Schreiben sinnvoller before_saveRückrufe, um die Konsistenz innerhalb des Datensatzes aufrechtzuerhalten. 4) after_commitHooks für externe Service-Trigger. 5) Ein gutes DSL zum Organisieren von DDL-Änderungen in Änderungssätzen (Migrationen). (Es gibt immer noch Schmerzen, aber kein Muster zu haben ist schlimmer, wenn> 1 Entwickler.)
Adamantish

6

Einige Nachrichten verwirren mich. Einige Antworten gehen zu "ORM" gegen "SQL" oder so ähnlich.

Tatsache ist, dass AR nur ein Programmiermuster zur Vereinfachung ist, bei dem Sie Ihre Domänenobjekte nutzen, um dort Datenbankzugriffscode zu schreiben.

Diese Objekte haben normalerweise Geschäftsattribute (Eigenschaften der Bean) und ein gewisses Verhalten (Methoden, die normalerweise mit diesen Eigenschaften arbeiten).

Der AR sagt nur "einige Methoden zu diesen Domänenobjekten hinzufügen" zu datenbankbezogenen Aufgaben.

Und ich muss meiner Meinung und Erfahrung nach sagen, dass mir das Muster nicht gefällt.

Auf den ersten Blick kann es ziemlich gut klingen. Einige moderne Java-Tools wie Spring Roo verwenden dieses Muster.

Für mich liegt das eigentliche Problem nur in der OOP-Sorge. Das AR-Muster zwingt Sie in gewisser Weise, eine Abhängigkeit von Ihrem Objekt zu Infrastrukturobjekten hinzuzufügen. Mit diesen Infrastrukturobjekten kann das Domänenobjekt die Datenbank mit den von AR vorgeschlagenen Methoden abfragen.

Ich habe immer gesagt, dass zwei Ebenen der Schlüssel zum Erfolg eines Projekts sind. Die Serviceschicht (in der sich die Geschäftslogik befindet oder über eine Remoting-Technologie exportiert werden kann, z. B. Web Services) und die Domänenschicht. Wenn wir den Domänenschichtobjekten zum Auflösen des AR-Musters einige Abhängigkeiten hinzufügen (die nicht wirklich benötigt werden), ist es meiner Meinung nach schwieriger, unsere Domänenobjekte mit anderen Schichten oder (seltenen) externen Anwendungen zu teilen.

Die Spring Roo-Implementierung von AR ist interessant, da sie nicht auf dem Objekt selbst beruht, sondern in einigen AspectJ-Dateien. Wenn Sie später jedoch nicht mit Roo arbeiten möchten und das Projekt umgestalten müssen, werden die AR-Methoden direkt in Ihren Domänenobjekten implementiert.

Eine andere Sicht. Stellen Sie sich vor, wir verwenden keine relationale Datenbank zum Speichern unserer Objekte. Stellen Sie sich vor, die Anwendung speichert unsere Domänenobjekte in einer NoSQL-Datenbank oder beispielsweise nur in XML-Dateien. Würden wir die Methoden, die diese Aufgaben ausführen, in unseren Domänenobjekten implementieren? Ich denke nicht (zum Beispiel würden wir im Fall von XM XML-bezogene Abhängigkeiten zu unseren Domänenobjekten hinzufügen ... Wirklich traurig, denke ich). Warum müssen wir dann die relationalen DB-Methoden in den Domänenobjekten implementieren, wie das Ar-Muster sagt?

Zusammenfassend kann das AR-Muster für kleine und einfache Anwendungen einfacher und gut klingen. Wenn wir jedoch komplexe und große Apps haben, denke ich, dass die klassische Schichtarchitektur ein besserer Ansatz ist.


Willkommen bei SO. Wir haben Ihren Kommentar geschätzt, aber diese Frage wurde von NullUserException am 17. Dezember 11 um 1:17 Uhr
Tony Rad

3

Die Frage bezieht sich auf das Entwurfsmuster von Active Record. Kein Orm-Tool.

Die ursprüngliche Frage ist mit Rails versehen und bezieht sich auf Twitter, das in Ruby on Rails erstellt wurde. Das ActiveRecord-Framework in Rails ist eine Implementierung des Active Record-Entwurfsmusters von Fowler.


2

Die Hauptsache, die ich in Bezug auf Beschwerden über Active Record gesehen habe, ist, dass Sie beim Erstellen eines Modells um eine Tabelle und beim Auswählen mehrerer Instanzen des Modells im Grunde genommen "select * from ..." ausführen. Dies ist in Ordnung, um einen Datensatz zu bearbeiten oder einen Datensatz anzuzeigen. Wenn Sie jedoch beispielsweise eine Liste der Städte für alle Kontakte in Ihrer Datenbank anzeigen möchten, können Sie "Stadt aus ... auswählen" und nur die Städte abrufen . Um dies mit Active Record zu tun, müssen Sie alle Spalten auswählen, jedoch nur City.

Unterschiedliche Implementierungen werden dies natürlich unterschiedlich behandeln. Trotzdem ist es ein Problem.

Jetzt können Sie dies umgehen, indem Sie ein neues Modell für die spezifische Aufgabe erstellen, die Sie ausführen möchten. Einige Leute würden jedoch argumentieren, dass dies mehr Aufwand als Nutzen bedeutet.

Ich grabe Active Record. :-)

HTH


2
"Um dies mit Active Record zu tun, müssen Sie alle Spalten auswählen, aber nur City verwenden." Es ist eigentlich sehr einfach, eine select-Klausel anzugeben.
MattMcKnight

1

Ich mag die Art und Weise, wie SubSonic nur eine Spalte macht.
Entweder

DataBaseTable.GetList(DataBaseTable.Columns.ColumnYouWant)

, oder:

Query q = DataBaseTable.CreateQuery()
               .WHERE(DataBaseTable.Columns.ColumnToFilterOn,value);
q.SelectList = DataBaseTable.Columns.ColumnYouWant;
q.Load();

Aber Linq ist immer noch König, wenn es um faules Laden geht.


1

@BlaM: Manchmal habe ich gerade einen aktiven Datensatz für ein Ergebnis eines Joins implementiert. Muss nicht immer die Beziehungstabelle <-> Active Record sein. Warum nicht "Ergebnis einer Join-Anweisung" <-> Active Record?


1

Ich werde über Active Record als Entwurfsmuster sprechen, ich habe ROR nicht gesehen.

Einige Entwickler hassen Active Record, weil sie intelligente Bücher über das Schreiben von sauberem und ordentlichem Code lesen. In diesen Büchern heißt es, dass Active Record gegen das Prinzip der einzelnen Resposobilität verstößt, gegen die DDD-Regel verstößt, dass Domänenobjekte dauerhaft ignorant sein sollten, und gegen viele andere Regeln aus dieser Art von Büchern .

Das zweite, was Domänenobjekte in Active Record in der Regel 1: 1 mit der Datenbank sind, kann in einigen Systemen als Einschränkung angesehen werden (meistens n-Tier).

Das sind nur abstrakte Dinge, ich habe Ruby on Rails nicht gesehen, wie dieses Muster tatsächlich umgesetzt wurde.


0

Das Problem, das ich bei Active Records sehe, ist, dass es immer nur um eine Tabelle geht. Das ist in Ordnung, solange Sie wirklich nur mit dieser einen Tabelle arbeiten, aber wenn Sie in den meisten Fällen mit Daten arbeiten, haben Sie irgendwo eine Art Join.

Ja, Join ist normalerweise schlechter als gar kein Join, wenn es um die Leistung geht, aber Join ist normalerweise besser als "gefälschter" Join, indem zuerst die gesamte Tabelle A gelesen und dann die gewonnenen Informationen zum Lesen und Filtern von Tabelle B verwendet werden.


@BlaM: Du hast absolut recht. Obwohl ich Active Record noch nie verwendet habe, habe ich andere angeschraubte ORM-Systeme (insbesondere NHibernate) verwendet, und ich habe zwei große Beschwerden: dumme Methoden zum Erstellen von Objekten (dh .hbm.xml-Dateien, von denen jede abgerufen wird in ihre eigene Assembly kompiliert) und der Leistungseinbruch, der nur beim Laden von Objekten auftrat (NHibernate kann einen Single-Core-Prozess für mehrere Sekunden auslösen, indem eine Abfrage ausgeführt wird, die überhaupt nichts lädt, wenn eine äquivalente SQL-Abfrage fast keine Verarbeitung erfordert). Natürlich nicht spezifisch für Active Record, aber ich finde, die meisten ORM-Systeme (und ORM-ähnlichen Systeme) scheinen
TheSmurf

Es gibt viele Alternativen zur Verwendung von hbm.xml-Dateien. Siehe zum Beispiel NHibernate.Mapping.Attributes und Fluent-nhibernate.
Mauricio Scheffer

In Bezug auf die Leistung bei der Objekterstellung bin ich noch nie auf solche Perfektionsprobleme gestoßen. Vielleicht möchten Sie dies mit einem Profiler überprüfen.
Mauricio Scheffer

@mausch: Brauche keinen Profiler. Es ist ein ziemlich bekanntes Problem. Ich weiß nicht, ob es für die neueste Version gilt (die ich bei meiner Arbeit noch nicht verwende). ayende.com/Blog/archive/2007/10/26/…
TheSmurf

4
Wenn Sie: joins oder: includes in den Suchvorgängen verwenden, führt IE Customer.find (: all ,: include =>: Kontakte ,: Bedingungen => "active = 1") einen SQL-Join durch, keinen vollständigen Tabellenscan.
Tilendor

0

Das Problem mit ActiveRecord besteht darin, dass die Abfragen, die automatisch für Sie generiert werden, Leistungsprobleme verursachen können.

Am Ende machen Sie einige unintuitive Tricks, um die Abfragen zu optimieren, bei denen Sie sich fragen, ob es zeitsparender gewesen wäre, die Abfrage überhaupt von Hand zu schreiben.


0

Obwohl alle anderen Kommentare zur SQL-Optimierung sicherlich gültig sind, ist meine Hauptbeschwerde mit dem aktiven Aufzeichnungsmuster, dass es normalerweise zu einer Impedanzfehlanpassung führt . Ich mag es, meine Domain sauber und richtig gekapselt zu halten, was das aktive Aufzeichnungsmuster normalerweise jede Hoffnung auf etwas zerstört.


ActiveRecord löst das Problem der Impedanzfehlanpassung, indem Sie OO-Code für ein relationales Schema verwenden.
Mauricio Scheffer

Möchtest du das näher erläutern? Allgemeiner Konsens ist, dass Objekte, die einer relationalen Datenbank nachempfunden sind, per Definition nicht objektorientiert sind (da sich relationale Datenbanken nicht um OO-Konzepte wie Vererbung und Polymorphismus drehen).
Kevin Pang

Es gibt drei bekannte Möglichkeiten, die Vererbung einem relationalen Schema zuzuordnen. Ref: schlossproject.org/ActiveRecord/documentation/trunk/usersguide/…
Mauricio Scheffer

Ich denke, Sie verwechseln das Castle Active Record OSS-Projekt mit Active Record als Entwurfsmuster. Die ursprüngliche Frage (und meine Antwort) beziehen sich auf das Entwurfsmuster. Das Castle Active Record-Projekt enthält Dinge, die bei der OO-Entwicklung hilfreich sind, das Muster selbst jedoch nicht.
Kevin Pang

Ich habe nur Castle als Referenz zitiert. ActiveRecord von RoR implementiert nur die Vererbung einzelner Tabellen ( martinfowler.com/eaaCatalog/singleTableInheritance.html ), die anderen Strategien werden jedoch in Betracht gezogen ( blog.zerosum.org/2007/2/16/… )
Mauricio Scheffer

0

Versuchen Sie eine viel zu viele polymorphe Beziehung. Nicht so einfach. Besonders wenn Sie STI nicht verwenden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.