Warum ich Eloquent ORM hasse

Bild


Hallo an alle. Ich möchte Ihnen gestehen und Ihnen ein wenig darüber erzählen, wie ich mich fühle, wenn ich mich auf Laravel entwickle. Nein, denken Sie nicht darüber nach, ich liebe dieses Framework und bin dem Team, das es erstellt und unterstützt hat, unglaublich dankbar. Sie machen einen extrem coolen Job und meiner Meinung nach ist Laravel die beste Fortsetzung von Symfony, nicht weniger geliebt von mir.


Ich liebe dummen Code. Dumm in dem Sinne, dass Sie dies auch nach 10 Jahren tun können, wenn der Kunde Sie auffordert, Änderungen daran vorzunehmen, ohne sich mit der Logik zu befassen, selbst nach einer Firmenfeier am Freitag, ohne irgendetwas im alten Code zu brechen. Und dumm in dem Sinne, dass Sie keine kognitiven Anstrengungen unternehmen müssen, um es zu verstehen. Aber es gibt eine architektonische Lösung in Laravel Eloquent ORM, die mich zum Weinen bringt. Interessant? Komm unter die Katze.


Kluge Köpfe haben sich vor langer Zeit alles für uns ausgedacht: OOP, Design Patterns, SOLID, DDD und andere beängstigende Wörter, die Sie am Anfang so sehr erschrecken, und wenden sie dann ahnungslos an.


Diese mag ich Laravel und Symfony. Mit ihnen können Sie den dümmsten und sichersten Code sofort schreiben. Ja Jeder von ihnen hat seine Nachteile ... Aber in Laravel gibt es einen, der mich am meisten nervt. Hierbei wird das Active Record Pattern (AR) für die Arbeit mit Modellen verwendet.


Für den Anfang ein wenig über dieses Muster. Worum geht es hier? Zum Verständnis sollten Sie zum übergeordneten Element dieses Anwendungsdesigns gehen - dem Repository-Muster. Dieses Muster ist eine Sammlung. Eine Sammlung von Entitäten (Entity), die sie abrufen, ändern, speichern, löschen und im Allgemeinen an einem abstrakten Speicherort verwalten können. In 90 von 100 Prozent der Fälle handelt es sich bei diesem Speicherort um eine Vielzahl von Datenbanken. Möglicherweise gibt es jedoch ein Dateisystem, eine Art Cache und sogar eine externe API.


Dieser Ansatz steht in vollem Einklang mit dem Prinzip der geteilten Verantwortung und dem DDD-Ansatz. Dank dieses Ansatzes wird außerdem eine schwache Konnektivität implementiert. Es ist uns egal, wie genau die Anwendung gespeichert ist. Wir arbeiten mit Entity, wenn wir direkt mit der Objektdarstellung von Daten arbeiten möchten, und arbeiten mit Repository, wenn wir mit dem Repository interagieren müssen.


Laravel entschied sich jedoch für AR, das zweifellos cool und unglaublich praktisch ist, wenn Sie einen schnellen Prototyp erstellen müssen. Es wird jedoch zu einem unglaublichen Problem, wenn Sie mit mehreren Datenquellen interagieren und mit ihnen im System arbeiten müssen.


AR ist ein Muster, das Entität und Repository in einem Modell abbildet. Das heißt, ein Objekt wird zu einer Darstellung eines bestimmten Datensatzes in der Datenbank. Na und? Was führt das und warum ist es so nervig?


Erstens verletzen wir das gleiche Prinzip der geteilten Verantwortung - die Logik der Arbeit mit dem Repository an einem Ort und die Logik der Arbeit mit einer Entität an einem anderen Ort. Dies ist wichtig, da ich im Rahmen meines Systems keine Zeile aus der Datenbank in der Objektdarstellung über die Aufrufkette übertragen möchte. Ich möchte das Modell weitergeben. Ich sollte mich nicht darum kümmern, wie es ausgeht, sich ändert und anhält. Ich brauche diese Methoden, mit denen Sie nur mit dem Modell und nicht mit den Zeilen in der Datenbank interagieren können.


Zweitens können wir den Speicherort des Modells nicht einfach ändern (da die persistente Schicht - die Speicherschicht - mit der Entitätsschicht verbunden ist). Ja, wir können dies in der Konfiguration tun und es sofort für alle innerhalb der unterstützten Datenbanken ändern. Oder ändern Sie nur für ein bestimmtes Modell (mit all dem entfernen wir keine Methoden zum Erstellen von Abfragen, da Sie die Methoden der Basisklasse nicht entfernen können) und stoßen auf eine Menge wahrscheinlicher Fehler im Code oder, Gott bewahre, wenn jemand anderes wird unterstützen (und das passiert die ganze Zeit).


Drittens. Ich möchte meine Entitäten testen. Ich möchte es verdammt noch mal tun, um sicherzugehen, dass die Änderungen, die ich vornehme, meine Geschäftslogik nicht brechen. Und wie die Praxis zeigt, können Sie dies bei AR nicht tun, da das teuflische Prinzip der Einzelverantwortung verletzt wurde! Obwohl ich hier etwas unaufrichtig bin. Das Testen von Modellen ist möglich, nur ... Ein bisschen kompliziert.


Über die Vorteile dieses Musters kann man jedoch nichts sagen. Obwohl sein ganzes Plus ist, dass es "schnell, einfach, ohne zu zögern" ist. Durch das Zusammenführen von zwei Mustern, die logisch nahe an ihren Aktionen liegen und ständig zusammen verwendet werden, haben wir ein praktisches Werkzeug erhalten, das die Codemenge geringfügig reduziert (erinnern wir uns in Richtung Komplexität an den "dummen Code"?). Es ermöglicht Ihnen auch, unnötige Probleme in der Phase der MVP-Bildung zu beseitigen, was obligatorisch ist (die Praxis zeigt, dass dies selten vorkommt, aber immer noch). Es ist geplant, es neu zu schreiben. Auf diese Weise können Sie Ihre Gedanken von der Frage „Wie machen wir das?“ Zur Frage „Was machen wir?“ Verschieben, dh unnötige Fragen zu Technologien loswerden und zur Geschäftslogik übergehen.


Zu welchem ​​Schluss bin ich im Laufe der Jahre mit dem Laravel Eloquent ORM gekommen? Active Böse im Fleisch aufzeichnen? Nein, dies ist in einigen Situationen das coolste Tool, insbesondere in der Phase, in der Sie eine einfache Anwendung oder einen Prototyp einer solchen Anwendung schreiben. Dies ist jedoch unmöglich, wenn Ihre Anwendung erwachsen wird und Sie mit einer großen Anzahl von Datenquellen arbeiten, Code mit 100% Testabdeckung schreiben müssen und große Probleme auftreten.


Ja, neue Chips werden erfunden ( Trucker ?), Aber lasst uns Tricks machen. Trotzdem möchte ich ein bisschen mehr Freiheit vom Framework, zumal es für so viele so gut ist!

Source: https://habr.com/ru/post/de434984/


All Articles