Entspricht das ActiveRecord-Muster den SOLID-Entwurfsprinzipien?

43

Ich interessiere mich dafür, ob das durch Ruby on Rails bekannte ActiveRecord- Muster die Verwendung von SOLID- Entwurfsprinzipien fördert oder davon abhält .

Zum Beispiel scheint es mir, dass ActiveRecord-Objekte sowohl Domänenlogik als auch Persistenzlogik enthalten, was eine Verletzung der Einzelverantwortung darstellt.

nicholaides
quelle
6
Jim Weirich, am Ende seines SOLID Ruby Talk auf der Ruby Conference 2009, fragt das Publikum: "ActiveRecord-Objekte implementieren ein Domänenkonzept und ein Persistenzkonzept. Verstößt dies gegen das SRP (Single Responsibility Principle)?" Das Publikum stimmt zu, dass es die SRP verletzt. Jim fragt, ob das sie stört. Viele Zuschauer sagen ja. Warum? Es macht das Testen schwieriger. Dadurch wird das Persistenzobjekt viel schwerer.
David J.

Antworten:

56

Es gibt einige berechtigte Kritik an ActiveRecord. Wie immer fasst Onkel Bob es perfekt zusammen :

Das Problem, das ich mit Active Record habe, ist, dass es Verwirrung über diese beiden sehr unterschiedlichen Programmierstile schafft. Eine Datenbanktabelle ist eine Datenstruktur. Es hat Daten und kein Verhalten ausgesetzt. Ein aktiver Datensatz scheint jedoch ein Objekt zu sein. Es hat "versteckte" Daten und offengelegtes Verhalten. Ich habe das Wort "versteckt" in Anführungszeichen gesetzt, weil die Daten tatsächlich nicht versteckt sind. Fast alle ActiveRecord-Derivate exportieren die Datenbankspalten über Accessoren und Mutatoren. In der Tat soll der aktive Datensatz wie eine Datenstruktur verwendet werden.

Auf der anderen Seite fügen viele Leute Geschäftsregelmethoden in ihre Active Record-Klassen ein. was sie als Objekte erscheinen lässt. Dies führt zu einem Dilemma. Auf welche Seite der Linie fällt der aktive Datensatz wirklich? Ist es ein Objekt? Oder ist es eine Datenstruktur?

Wikipedia fasst die Kritik in einem Testbarkeitsproblem zusammen :

In OOP steht das Konzept der Einkapselung häufig im Widerspruch zum Konzept der Trennung von Bedenken. Im Allgemeinen eignen sich Muster, die die Trennung von Bedenken begünstigen, besser für isolierte Komponententests, während Muster, die die Verkapselung begünstigen, einfacher APIs zu verwenden sind. Active Record bevorzugt die Kapselung so stark, dass das Testen ohne Datenbank recht schwierig ist.

Speziell für die Ruby on Rails-Implementierung schreibt Gavin King (Hervorhebung von mir):

An diesem Punkt denken die meisten Entwickler, ok, wie zum Teufel soll ich wissen, welche Attribute ein Unternehmen hat, wenn ich meinen Code betrachte? Und wie kann meine IDE sie automatisch vervollständigen? Natürlich haben die Rails-Leute eine schnelle Antwort auf diese Frage. Oh, starten Sie einfach Ihren Datenbank-Client und sehen Sie in der Datenbank nach !. Unter der Annahme, dass Sie die Regeln für die automatische Groß- und Kleinschreibung und die Pluralisierung von ActiveRecord genau kennen , können Sie dann die Namen der Attribute Ihrer eigenen Firmenklasse erraten und manuell eingeben.

John Januszczak schreibt auch über die Implementierung von Ruby on Rails (Schwerpunkt Mine):

PROBLEM 1: STATISCHE METHODEN

...

Einige würden sagen, dass die Verwendung statischer Methoden einfach eine prozedurale Programmierung darstellt und daher ein schlechtes objektorientiertes Design darstellt. Andere würden sagen, dass statische Methoden der Testbarkeit zum Opfer fallen.

PROBLEM 2: GLOBALE KONFIGURATIONSEINSTELLUNGEN

...

Daher gibt es in meinem Beispiel keine Abhängigkeitsinjektion für die Account-Klasse und auch nicht für die Account-Instanzen. Wie wir alle wissen sollten, ist es sehr, sehr schlecht, nach Dingen zu suchen!

Ein paar weitere Ressourcen, warum ActiveRecord und ORM im Allgemeinen als Anti-Pattern angesehen werden:

ActiveRecord fühlte sich immer als äußerst nützliches Anti-Pattern an , aber ich stimme zu, dass es gegen SRP und zusätzlich gegen das Prinzip der Abhängigkeitsinversion verstößt.

yannis
quelle
WICHTIGES Update für Rails 5+: "Und wie kann meine IDE sie automatisch vervollständigen? Natürlich haben die Rails-Leute eine schnelle Antwort auf diese Frage. Oh, starten Sie einfach Ihren Datenbank-Client und sehen Sie in der Datenbank nach!" Ist ungültig nicht mehr. Mit der Attribut-API können Sie alle verfügbaren Spalten des Modells definieren
Filip Bartuzi
6

(Ich gehe davon aus, dass die ActiveRecord-Klasse ohne Abhängigkeitsinjektionsmöglichkeit implementiert ist.)

Aus persönlicher Erfahrung kann ich sagen, dass das ActiveRecord-Muster ein Haupthindernis für das Schreiben von Unit-Tests darstellt. Die Kopplung der Persistenzschicht und der Geschäftslogik in einer einzigen "ActiveRecord-Klasse" macht es unmöglich, Komponententests zu schreiben (es sei denn, Sie überarbeiten zuerst). Daher besteht die einzige Option darin, Integrationstests zu schreiben. und das ist nicht so effektiv wie Unit-Tests. Dies ist besonders dann ein großes Problem, wenn Sie ein Projekt mit vielen ActiveRecord-Klassen übernehmen. Dies führt zu sehr komplizierten Integrationstests, die schwer zu warten sind.

Der ActiveRecord wirkt sich also ziemlich negativ auf SRP aus und verursacht einige Wartungsprobleme. es scheint die Macht zu nehmen, Unit-Tests zu schreiben.

Guven
quelle