What I hate for Eloquent ORM
Hello. I want to confess in front of you and tell a little about what I feel when I develop on Laravel. No, do not think, I adore this framework and are incredibly grateful to the team that created it and supports it, they do an extremely cool job and, in my opinion, Laravel is the best continuation of Symfony, which I love no less.
I love dumb code. Dumb in the sense that even after 10 years, if the customer asks you to make changes to it, you can do it without going into all the logic, even after being in the company office on Friday, without breaking anything in the old code. And stupid in the sense that no cognitive effort is needed to understand it. But there is one architectural solution in Laravel Eloquent ORM that makes me cry. Interesting? Come under the cat.
Smart people have long ago invented everything for us: OOP, Design Patterns, SOLID, DDD, and other scary words that scare them in the beginning, and then apply them.
I like this Laravel and Symfony. They allow you to write the most stupid and protected code right out of the box. Yes. Each of them has its drawbacks ... But in Laravel there is one that annoys me the most. This is using Active Record Pattern (AR) to work with models.
For a start - a little about this pattern. What is it all about? To understand, you should go to the parent of this application design opus, the Repository pattern. This pattern is a collection. A collection of entities (Entity) that can retrieve, modify, save, delete, in general, manage them in an abstract storage location. In 90 out of 100 percent of cases, such databases are stored in different locations. But there can be a file system, some kind of cache, and even an external API.
This approach is fully consistent with the principle of common responsibility and the DDD approach. In addition, due to this approach, weak coherence is implemented - it does not matter to us exactly how the application stores something, we work with Entity, when we want to work directly with the object data representation and work with the Repository when we need to interact with the repository.
But Laravel decided to follow the path of using AR, which is undeniably cool and incredibly convenient when you need to make a quick prototype, but it becomes an incredible headache when you need to interact with several data sources and operate with them within the system.
AR is a pattern that maps Entity and Repository into one Model. That is, the object becomes a representation of a specific record in the database. So what? What does this lead to and why is it so annoying?
First, we are violating the very principle of common responsibility - the logic of working with a repository in one place, and the logic of working with an entity in another. This is important, because within my system I don’t want to pass a line from the database in the object representation along the call chain. I want to transfer the model. I should not care how it turns out, changes and persists. I need to have those methods that allow you to interact only with the model, and not with the rows in the database.
Secondly, we cannot (as a consequence of the fact that the Persistent layer - the storage layer - is associated with the entity layer), in a simple way to change the storage location of the model. Yes, we can do this in the configuration by changing it for all at once, within the supported databases. Or change only for a specific model (with all this, we do not remove any methods of the query builder, because you cannot get rid of the methods of the base class) and run into a ton of possible errors in the code or, God forbid, if someone else is will support (and this happens all the time).
Thirdly. I want to test my entities. I want to, damn it, be sure that the changes I make will not break my business logic. And, as practice shows, in the case of AR, you cannot do this, because the devil's principle of common responsibility has been violated! Although here I am a little cunning. You can test the models, just ... It's not easy.
Nevertheless, it is impossible not to say about the advantages of this pattern. Although all its plus is that it is “fast, simple, without thinking.” By merging two close ones according to the logic of their action and patterns that are constantly used together, we got a handy tool that slightly reduces the amount of code (in the direction of complication, do we remember the "stupid code"?). It also allows you to get rid of unnecessary problems at the stage of MVP formation, which is mandatory (practice shows that this happens rarely, but still) is planned to be rewritten. This allows us to shift our thoughts from the question “how we do” to the question “what we do”, that is, to get rid of unnecessary questions about technology and move on to business logic.
What is the conclusion I came for a few years using Laravel Eloquent ORM? Active Record evil in the flesh? No, this is the coolest tool for some situations, especially for the stage when a simple application or a prototype of such an application is written. But this is an impossible thing to work with, when your application grows and you have to work with a large number of data sources, write code with 100% coverage tests, big problems begin.
Yes, new chips are invented ( Trucker ?), But we are going to tricks. But I still want a little more freedom from the framework, especially since it is so good to many!