-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Repository pattern #44
Comments
Hey @vonalbert! Actually, I followed an excellent blog post by @mnavarrocarter, but it seems like it has been removed (maybe Matias could give us the reason why?). About the inconsistency, you're totally right, but I think it worth it for the sake of performances. Many thanks for that review! |
Thank you for pointing me to the right direction. So, when you say "it worth it for the sake of performances" you mean that:
Is that right? Given that the InMemory repository is only used for testing purposes (and if I were to choose I'd go for the Doctrine repository way) it's maybe a not-so-big issue leaving the things how are now. But I think I'm digressing now :) The issue can be closed since my main question was solved! |
Hey @mtarld I appreciate the credits, and sorry for the article being lost. I'm terrible at keeping my blogs! When I created the new one I didn't migrated all the old entries, and this one got lost in the process. Thanks to you, however, it has been reposted and polished a bit in the one that is my current blog (until I get bored and change it again! 🤣 ) https://blog.mnavarro.dev/the-repository-pattern-done-right Nice talk at API Platform Conf by the way! 😃 Also @vonalbert if you have any other questions, happy to assist. |
@mnavarrocarter first of all, thank you for taking the time to re-post the article. So if I interpreted correctly your final advice, you're suggesting that the read part of the application is not so important from a domain point of view and as such it could suffice to define a service that simply takes the db record and send to output it as raw data. To generate this raw data you won't use the repository, since the repository is just a collection of the main aggregate, but you use another service. Does this service belong to the domain layer? If yes I suppose that an interface is required. In this case you define a each read model as a distinct object? And what about the naming of the service above? Would you call it SomeViewModelProvider? SomeViewModelRepository? |
Hi @vonalbert yes. More specifically, if your read operation's purpose is to just expose the data over an API endpoint or any other infrastructure interface, then that read operation its not a domain read operation, and thus can be outside the domain. Something I've grown fond of doing is that I have a <?php
interface APIResourceFinder
{
public function all(string $resource, array $params = []): array;
public function one(string $resource, string $field, mixed $value): array;
} This is implemented by something called
Is no simple thing to instrument something like this, and it is also highly opinionated to my particular use case, so let me know if you need to look at an existing implementation. But basically, the principle behind this is that you don't need a repository to provide data to a JSON endpoint. You do need a repository for your command handlers, because they are the heart of your application and logic and you want the persistence layer there completely abstracted away in there. All this lives in the infra layer. It's your HTTP layer (Infra) making use of your persistence layer (Infra). Only drawback I see is that when a resource changes implementation, you need to update it's repository implementation and decorate this Of course, this is one way of doing it. I have other projects where I use the repository in the controller anyway and let a serializer do the heavy lifting. It's completely up to you and what you need for your particular use case. |
Thank you for sharing your insight. That was an interesting point of view.
Ok, I think I understand. Basically displaying the data over API is a UI concern, so we put that in the infra. But what about those rules that controls which resources I can view? Aren't those related to the domain? For example, take the classic e-commerce application with the classic order aggregate. When a customer request a list of orders should only view a list of its own orders, while the admin can (and should) view all of them. Isn't this rule a domain rule? Or I'm missing something? On a second thought it's maybe not that important since the rule is enforced in the infrastructure layer anyway (it's the doctrine implementation that performs the query after all).
That would be very appreciated! If you have a public repository I'd love to read the code 🙂 |
Hi. I see 3 problems with Repository design here:
|
Hi @domis86 , sorry I have not read your previous comment, but let me respond to your three points. Hopefully I can do it in a clear way, explaining the reasoning behind any decision and providing an alternative if possible.
|
This is not really an issue, but more an information request. I really like the way repositories are implemented in this project. A problem I usually have with repositories is their size when implementing all the queries needed for the model.
From what I see here I understand that the basic idea is to treat them like immutable collections where methods are basically filters used to reduce the size of the collection.
Can you point me to a book, blog post or another resource that explore the subject in detail?
There's only a little inconsistency though between the doctrine book repository and the in memory one:
Except this the idea is excellent.
The text was updated successfully, but these errors were encountered: