Ich bin gespannt, welche Nachteile die Verwendung des ActiveRecord-Musters für Datenzugriffs- / Geschäftsobjekte hat. Das Einzige, woran ich auf Anhieb denken kann, ist, dass es gegen das Prinzip der einfachen Verantwortung verstößt, aber das AR-Muster ist weit genug verbreitet, dass dieser Grund alleine nicht "gut genug" zu sein scheint, um es zu rechtfertigen, es nicht zu verwenden (natürlich mein Die Ansicht kann verzerrt sein, da häufig keiner der Codes, mit denen ich arbeite, einem der SOLID-Prinzipien folgt .
Persönlich bin ich kein Fan von ActiveRecord (mit Ausnahme des Schreibens einer Ruby on Rails-Anwendung, bei der AR sich "natürlich" anfühlt), weil die Klasse zu viel tut und der Datenzugriff nicht der Klasse selbst überlassen bleiben sollte zu handhaben. Ich bevorzuge die Verwendung von Repositorys, die Geschäftsobjekte zurückgeben. Der Großteil des Codes, mit dem ich arbeite, verwendet in der Regel eine Variante von ActiveRecord in Form von (ich weiß nicht, warum die Methode ein Boolescher Wert ist):
public class Foo
{
// properties...
public Foo(int fooID)
{
this.fooID = fooID;
}
public bool Load()
{
// DB stuff here...
// map DataReader to properties...
bool returnCode = false;
if (dr.HasRows)
returnCode = true;
return returnCode;
}
}
oder manchmal die "traditionellere" Art, eine public static Foo FindFooByID(int fooID)
Methode für die Finder und etwas in der Art des public void Save()
Speicherns / Aktualisierens zu haben.
Ich verstehe, dass ActiveRecord in der Regel viel einfacher zu implementieren und zu verwenden ist, aber für komplexe Anwendungen etwas zu einfach erscheint und Sie eine robustere Architektur haben könnten, indem Sie Ihre Datenzugriffslogik in einem Repository kapseln (ganz zu schweigen davon, dass es einfacher ist, sie auszutauschen) Datenzugriffsstrategien (z. B. verwenden Sie Stored Procs + DataSets und möchten zu LINQ wechseln oder so)
Was sind weitere Nachteile dieses Musters, die bei der Entscheidung, ob ActiveRecord der beste Kandidat für den Job ist, berücksichtigt werden sollten?
quelle
Der größte Nachteil aktiver Datensätze besteht darin, dass Ihre Domain normalerweise eng an einen bestimmten Persistenzmechanismus gekoppelt ist. Sollte dieser Mechanismus eine globale Änderung erfordern, möglicherweise von dateibasierter zu DB-basierter Persistenz, oder zwischen Datenzugriffs-Frameworks, kann sich JEDE Klasse, die dieses Muster implementiert, ändern. Abhängig von der Sprache, dem Framework und dem Design kann es sogar erforderlich sein, dass jedes Objekt durchlaufen wird, um die Datenzugriffsmethoden zu aktualisieren. Dies ist in den meisten Sprachen, die einen einfachen Zugriff ermöglichen, selten Dateien mit Verbindungszeichenfolgen konfigurieren).
Im Allgemeinen müssen Sie sich auch wiederholen. Die meisten Persistenzmechanismen haben viele gemeinsame Codes, um eine Verbindung zu einer Datenbank herzustellen und eine Transaktion zu starten. DRY (Don't Repeat Yourself) würde Ihnen als Codierer empfehlen, eine solche Logik zu zentralisieren.
Es macht auch atomare Operationen schwierig. Wenn eine Gruppe von Objekten vollständig oder vollständig gespeichert werden muss (z. B. eine Rechnung und ihre Rechnungsposten und / oder Kunden- und / oder FIBU-Einträge), muss eines der Objekte alle diese anderen Objekte kennen und deren Beständigkeit steuern ( Dies dehnt den Bereich des steuernden Objekts aus. Große miteinander verbundene Datensätze können leicht zu "Gottobjekten" werden, die alles über ihre Abhängigkeiten wissen. Oder die Kontrolle über die gesamte Transaktion muss von außerhalb der Domäne erfolgen (und in diesem Fall verwenden Sie warum) AR?)
Es ist auch "falsch" aus einer objektorientierten Perspektive. In der Praxis weiß eine Rechnung nicht, wie sie sich selbst ablegen soll. Warum kann ein Rechnungscodeobjekt sich selbst in der Datenbank speichern? Natürlich würde eine zu religiöse Bindung an "Objekte sollten nur das modellieren, was ihre realen Gegenstücke können" zu anämischen Domänenmodellen führen (eine Rechnung weiß auch nicht, wie sie ihre eigene Gesamtsumme berechnet, teilt aber die Berechnung dieser Gesamtsumme auf Ein anderes Objekt wird im Allgemeinen als schlechte Idee angesehen.
quelle
Der grundlegende Nachteil ist, dass Ihr Domain-Modell dadurch komplex wird, weil es nicht nur Geschäftslogik, sondern auch Persistenzinformationen enthält.
Die Lösung besteht also darin, die Data Mapper- Implementierung von ORM zu verwenden. Das trennt die Persistenzschicht und wir konzentrieren uns jetzt mehr auf die Geschäftslogik von Einheiten. Lehre ist Data Mapper ORM.
Aber dieser Ansatz hat auch einige Komplexität. Für Abfragen ist man jetzt zu sehr auf Data Mapper angewiesen, macht eine abfrageorientierte Umgebung. Zur Vereinfachung wird eine weitere Ebene zwischen Domain Model und Data Mapper eingeführt, die als Repository bezeichnet wird .
Das Repository abstrahiert die Persistenzschicht. Die objektorientierte Programmierung fühlt sich in dem Sinne an, dass es sich um eine Sammlung aller Objekte des gleichen Typs handelt (wie alle in der Datenbanktabelle gespeicherten Entitäten), und Sie können sie als Sammeloperation ausführen, hinzufügen , entfernen . enthält usw.
Für Benutzerentität gibt es beispielsweise UserRepository , das eine Auflistung derselben Art von Benutzerobjekten (die in der Benutzertabelle gespeichert sind) darstellt, für die Sie Vorgänge ausführen können. Zur Abfrage der Benutzertabelle wird der Benutzerdaten-Mapper verwendet, der jedoch an das Domänenmodell Benutzer abstrahiert wird .
Repository - Muster Typ ist Data Access Layer , ist ein weiteres Data Access Object nur Unterschiede Repository hat Aggregate Root - Feature
quelle