I have recently been looking at the Repository Pattern as a way of brushing all the details of persistence under the carpet where the client code is concerned. While reading around it appears that a Repository is/can be [usually?] responsible for aggregates rather than just straight-forward classes.
This make sense to me as you could have a class defining Posts and another defining Comments. This makes an ideal candidate for an aggregate since the two are very closely related. However, how would I represent a Users class and its relationship with his or her Posts?
Would it make sense to aggregate Users with the Posts/Comments aggregate, or keep Users by itself and simply have an association via a good old fashioned reference?
I have tried looking for the answer myself using Google, but a lot of the examples I find are just stand-alone. ie, Posts/Comment or maybe Order and OrderLine etc. I can't find anything that shows how other related classes fit together.
I am not applying this to anything specific, though PHP or Java/C# would probably be the area I would look to using these ideas. In any case I am just exploring and trying to get my head around some of these ideas and concepts before I run off and create a monster. :)
Thank you for your time.
The Repository Pattern is fairly loosely defined and does not necessarily have any relationship to the Aggregate Pattern. However, if you subscribe to the DDD way of doing things, then yes, repositories are unique to aggregates.
So let's have a look at this from the DDD point of view. DDD says that objects within an aggregate can have a reference to another aggregate root, but objects within an aggregate can only be accessed via the root. The rule of thumb for determining aggregates is what should be deleted when deleting the root. However, DDD discourages the use of relationships more than most methodologies saying that just because a relationship exists in a domain, it does not need to exist in your model of the domain, so just keep that in mind.
In your case, when you delete a post I assume that you would also delete the comments, but not the user who created the post or users who commented on it. Therefore, you are correct in defining the post/comment aggregate, but it would not make sense to group users into that aggregate.
Users, being its own aggregate, can contain a relationship to all of their posts, because Post is the aggregate root. You could also implement this a method on the PostRepository to get all of the posts by a given user. Hope that helps!
Related
I've modeled the following UML for the database of our website (uni project):
However, I can't seem to find how to convert to SQL the generalization case between Post, Story and Comment. My teacher suggested to use the same table, but I think that limits me if I want to add more features, like tags for stories. Right now I already have two extra relations: a post can have several child comments, and a story belongs to a specific channel.
Should I follow my teacher's suggestion? Or should I use 3 classes?
Since your class hierarchy has only two subclasses that come with only 3 additional properties (title, channel and post), you should use the Single Table Inheritance approach. Even when you may add a few more properties/methods later on, this will be the best choice, since implementing your class hierarchy with multiple tables would imply a much greater effort/overhead.
You can read more about this choice in the section Representing class hierarchies with SQL database tables (of a tutoral on handling class hierarchies in a JavaScript front-end web app authored by me).
As always it depends. Having a single table has the advantage of accessing related post info in a simple query and just looking at a flag inside the column telling what kind of object you're dealing with. Having separate tables is a more "academic" way of solving it since you (as you noticed) have object information separated.
I'd probably go with the single table approach in this case. But - YMMV - you can as well stick to your 3 table approach. There might come other opinions here. Just wait a few days to decide :-)
A system has nested resources. For example
Farm HasMany Sectors
An example object relation will be like below
farm1 => [sector1]
farm2 => [sector2, sector3]
Now say, user1 has read,write permission on farm1.
user1 Has(read,write) on farm1
I need the system to automatically use the access for all the nested resources of farm1, in this case sector1.
In other words, something like user1.hasWritePermisson(sector1) should return true, though the ACL is actually stored with farm1. I need this even to work on the nested resources of sector and so on.
A straightforward solution would probably be to copy the access to all of the children objects of farm1 at the updating its acl. But I believe this would be a really inefficient one if farm1 contains thousands of sectors.
What would be the best way to achieve this in symfony2?
First of all. I think your question has nothing to do with SF2. In my opinion, you should create a efficient database which helps you to do the task. The rest is only a few queries away.
As I understand, it will be 3 major objects: User, Farm and Sector.
User could be in many Farms and Farms could be seen/wrote by many users
A Farm has many sectors, but a sector can only be in one farm
That being clarified, you will also need to declare the permissions for every user has in a farm. But, this will be declared in the many-to-many relationship with two relationship properties (read, write).
Once everything well designed, you should be able to create queries that satisfy your needs.
I know it's hard to understand because I'm talking in abstract, but let me know if you don't understand and I will draw you a scheme.
I need help with something I can’t get my head wrapped around regarding the Repository and Service/Use-case pattern (part of DDD design) I want to implement in my next (Laravel PHP) project.
All seems clear. Just one part of DDD that is confusing is the data structures from repositories. People seem to choose data structures the Repository should return (arrays or entities) but it all has disadvantages. One of which is performance looking at my experiences in the past. And one is which you don’t have interfaces for simple data structures (array or simple object attributes).
I’ll start with explaining the experience I have with a previous project. This project had flaws but some good strengths I learned from and like to see in my new project but with solving some design mistakes.
Previous experience
In the past I’ve build a website that was API Centric using the Kohana framework and Doctrine 2 ORM (data mapper pattern). The flow looked like this:
Website controller → API client (HMVC calls) → API controller → Custom Repository → Doctrine 2 ORM native Repository/Entity-manager
My custom Repository returned plain arrays using Doctrine2 DQL. Doctrine2 recommends array result data for read only operations. And yes, it made my site nice and light. The API controller just converted the array data to JSON. Simple as that.
In the past my company created projects relying fully on loaded Doctrine2 entities and it’s something we regretted due to performance.
My REST API supported queries like
/api/users?include_latest_adverts=2&include_location=true
on the users resource. The API controller passed include_location to the repository which directly included the location relation. The controller read latest_adverts=2 and called the adverts repository to get the latest 2 adverts of each user. Arrays were returned.
For example first user array:
[
name
avatar
adverts [
advert 1 [
name
price
]
advert 2 [
….
]
]
]
This proved to be very successful. My whole website was using the API. It would be very easy to to add a new client because the API was perfectly in production already using oauth. The whole website runs on it.
But this design had flaws too. My controller still contained A LOT of logic for validation, mailing, params or filters like has_adverts=true to get users with adverts only. It would mean that if I created a new port, like a total new CLI interface, I would have to duplicate alot of these controllers due to all the validation etc. But no duplication if I would create a new client. So at least one problem was solved :-)
My admin panels were completely coupled to the doctrine2 repository/entity-manager to speed up development (sort of). Why? Because my API had fat controllers with special functionality for the website only (special validation, mailing for registering etc). I would have to redo work or refactor a lot. So decided to use the Entities directly to still have some sort clear way of writing code instead of rewriting all my API controllers and move them to Services (for site & admin) for instance. Time was an issue in fixing my design mistakes.
For my next project I want all code to go through my own custom repositories and services. One flow for good separation.
New project (using DDD ideas) and dilemma with data structures
While I like the idea of being API centric, I don’t want my next project to be API centric in core because I think the same functionality should be available without the HTTP protocol in between. I want to design the core using DDD ideas.
But I liked the idea using a layer that just talked as a API and returns simple arrays. The perfect base for any new port, including my own frontend. My idea is to consider my Service classes as the API interface (return the array data), do the validation etc. I could have Services specially for the website (registering) and plain services used by the Admin or background processes. In some admin cases a Service would not be required anyway for simple CRUD editing, I could just use Repositories directly. Controllers would be very thin. With this creating a real REST API would just be a matter to create new controllers using the same Services my frontend controller classes do.
For internal logic like business rules it would be useful to have Entities (clear interfaces) instead of arrays from repositories. This way I could benefit from defining some methods that did some logic based on attributes. BUT If I would be using Doctrine2 and my repositories would always return Entities my application would suffer a big performance hit!!
One data structure ensures performance but no clear interfaces, the other ensures clear interfaces but bad performance when using a Data Pattern pattern like Doctrine 2 (now or in the future). Also I could end up with two data types which would be confusing.
I was thinking something similar to this flow:
Controller (thin) → UserService (incl. validation) → UserRepository (just storage) → Eloquent ORM
Why Eloquent instead of Doctrine2? Because I want to stick a bit to what’s common within the Laravel framework and community. So I could benefit from third party modules, for example to generate admin interfaces or similar based on models (bypassing my DDD rules). Other than using third party modules, I would design my core stuff so switching should always be easy and not affect data structure choices or performance.
Eloquent is an activerecord pattern. So I would be tempted to convert this data to POPO’s like Doctrine2 entities are. But nope... as said above, with doctrine2 real models would make the system very fat. So I fall back to simple arrays again. Knowing this would work for both and any other implementation in the future.
But it feels bad always rely on arrays. Especially when creating internal business rules. A developer would have to guess values on arrays, have no autocompletion in his IDE, could not have special methods like in Entity classes. But making two ways of dealing with data feels bad too. Or I am just too perfectionist ;) I want ONE clear data structure for all!
Building interfaces and POPO’s would mean a lot of duplicate work. I would need to convert an Eloquent model (just a table mapper, not entity) to an entity object implementing this interface. All is extra work. And eventually my last layer would be just like a API, thus converting it to arrays again. Which is extra work too. Arrays seem the deal again.
It seemed so easy reading up into DDD and Hexagonal. It seems so logic! But in reality I struggle with this one simple issue trying to stick to OOP principles. I want to use arrays because it’s the only way to be 100% sure I am not depended on any model choice and querying choice from my ORM regarding performance etc and don't have duplicate work in converting to arrays for views or an API. But there's no clear contract on how a user array could look. I want to speed up my project using these patterns, not slow them down :-) So not an option to have many converters.
Now I read a lot of topics. One makes POPO’s & interfaces that conform proper entities like Doctrine2 could return, but with all the extra work for Eloquent. Switching to Doctrine2 should be fairly easy, but would impact performance so bad or one would need to convert Doctrine2 array data to these own entity interfaces. Others choose to return simple arrays.
One convinces people to use Doctrine2 instead of Eloquent, but they leave out the fact that Doctrine2 is heavy and you really need to use array results for read only operations.
We design repositories to be changeable right? Not because it’s “nice” by design only. So how could we rely on full Entities if it has such big impact on performance or duplicate work? Even when using Doctrine2 only (coupled) this same issue would arise due to its performance!
All ORM implementations would be able to return arrays, thus no duplicate work there. Good performance. But we miss clear contracts. And we don’t have interfaces for arrays or class attributes (as a workaround)... Ugh ;)
Do I just miss a missing block in our programming languages? Interfaces on simple data structures??
Is it wise to make all arrays and have advanced business logic talk to these arrays? Thus no classes with clear interfaces. Any precalculated data (normally would be returned by an Entity method) would be within an array key defined the Service class. if not wise, what’s the alternative considering all of the above?
I would really appreciate if someone with great experience in this “domain” considering performance, different ORM implementations, etc could tell me how he/she has dealt with this?
Thanks in advance!
I think what you are dealing with is something similiar I'm struggling with. The solution I'm thinking works best is:
Entities/Repositories
Use and pass around Entities always when performing Write operations (Creating things, Updating things, Deleting things, and complex combinations thereof).
Sometimes you may use Entities when doing Read operations (when you anticipate the Read might need to be used for a Write soon after...ie. ->findById is soon followed by ->save).
Anytime you are working with an Entity (whether it be Write or Read), the Repositories need to be the place to go. You should be able to tell new developers that they can only persist to the database through Entities and the Repository.
The Entities will have properties that represent some Domain Object (many times they represent a database table with the fields of a table, but not always). They will also contain the domain logic/rules with them (ie. validation, calculations) so they are not anemic. You may additionally have some domain services if your Entities need help interacting with other Entities (need to trigger other events), or you just need an additional place to handle some extra domain logic (perform Repository calls to check for some unique conditions).
Your Repositories will solely be for working with Entities. The Repositories could accept Entities and do some persistence work with them. Or they could accept just some parameters, and do some reading/fetching into full Entities.
Some Repositories will know how to save some Domain Objects that are more complex than others. Perhaps an Entity that has a property which contains a list of other Entities that need to be saved along side the main entity (you can dive deeper into learning about Aggregate roots if you want).
The interfaces to Repositories rest in your Domain layer, but not the actual implementations of those Repositories. That way you can have an Eloquent version or whatever.
Other Queries (Table Data Gateway)
These queries won't work with Entities. They'll just be accepting parameters and returning things like Arrays or POPO's (Plain Old PHP Objects).
Many times you will need to perform Reads that do not return nicely into a single Entity. These Reads are typically more for reporting (not for CRUD-like operations, like Reading a user into an edit form that is eventually submitted and saved). For example, you might have a report that is 200 rows of JOINed data. If you used the Repositiory and tried to return large deep objects (with all the relationships populated, or even lazy-loaded) then you are going to have performance issues. Instead, use the Table Data Gatway pattern. You are just displaying data and not really needing OOP power here. The outputted data could however contain ID's, which through the UI could be used to initiate calls to Repository persistence methods.
As you are developing your app, when you come across the need for a new Read/Report query, create a new method in some class somewhere in your Table Data Gatway folder. You may find you have already created a similar query, so see how you can consolidate the other query. Use some parameters if necessary to make the gateway method's queries more flexible in particular ways (ie. columns to select, sort order, pagination, etc.). Don't make your queries too flexible though, this is where query builders/ORMs go wrong! You need to constrain your queries to a certain extent to where if you need to replace them (perhaps a different database engine) then you can easily perceive what the allowed variations are and aren't. It's up to you to find the right balance between flexibility (so you have more DRY code) and constraints (so you can optimize/replace queries later).
You can create services in your Domain to handle receiving parameters, then passing them to the Table Data Gateway, and then receiving back arrays to do some more mutating on. This will keep your Domain logic in the domain (and out of the infrastructure/persistence layer of the Repository & Table Data Gateway).
Again, just like the Repository, use interfaces in your domain services so that the implementation details stay out of your Domain layer, and resides in the actual Table Data Gateway folder.
I am quite new to DDD and have some fundamental problems that i cant really understand.
Consider we have a User entity. A User has some Friend's (one to Many).
There are 2 possible solutions to fetch the friends.
Solution 1:
user.getFriends()
The Problem here is that all the friends have to be loaded or I am forced to use a Proxy.
If i use a Proxy it feels for me like cheating because the entity must not have an instance of the Repository. Can the Proxy have one?
Solution 2:
Avoid the getFriends Method and load the Friends Based on the User Repository, like:
userRepository.getFriendsOf(user)
This could sometimes be a good idea, but where to stop here? Whats about an AddressRepository for accessing user Addresses, or ?
I think you should look at it from perspective of Aggregate Roots.
In case of user.getFriends() - the user seem to be AR with associated friends which I don't think is correct. The definition of AR says "that we treat as a unit for the purpose of data changes". Friends are outside of the Boundary of user AR.
Considering the above the other option seem better - userRepository.getFriendsOf(user)
I'm not sure that either of them are correct. I think from a DDD point of view, the code is supposed to use the Ubiquitous Language of the domain. In that regard, getters are frowned upon.
Why are you getting the friends of a user? The public methods of User should reflect the ubiquitous language.
For example if your domain is a social networking site, users should have methods to update status which will internally notify friends etc. How the User knows who its friends are or how they are queried is hidden as an implementation detail.
One thing to keep in mind is that you shouldn't use your domain model for querying. So you do not want to be lazy-loading or applying any other fetching strategies.
You also need to identity your aggregates. An aggregate is loaded in its entirety from the data store.
In your case if a Friend class can only ever exist in the context of a User then it is part and parcel of the User and its life-cycle is linked to that of the User. That means that when the User is deleted (conceptually, as one probably would not want a hard delete) then the associated Friend instances are deleted also.
So if a Friend represent the association between users then it probably only contains the User Id. So you could go with a list of Ids in that case. This would depend on your domain.
I would guess that you very rarely would need to load the entire list of User instances that are friends of another user. If you need related data you could implement a light-weight query layer.
I'd like to ask other opinions about code structuring of business logic on Laravel applications, mainly regarding permissions at the row level.
For those that don't know it, Laravel is a MVC framework for PHP, much like Rails.
For the sake of understanding, let's suppose a multi-tenant application where each user has his own albums and pictures, so far so good.
Now, each user can invite others to collaborate (by uploading photos) into his album.
Both, the album's owner and collaborator that uploaded the picture may be able to delete or update information about that picture.
Only the owner may edit the album and invite new collaborators.
Collaborators can remove themselves of the album if they want so.
Pinterest should be a nice example of something similar, but our application is probably 3 or 4 times more complex.
The question is: where should I handle that kind of logic?
Laravel proposes the approach of having repositories, entities and services, which I don't fully understand, probably because of the lack of good examples. So the obvious first choice to meet those deadlines was to put it all on controllers (ew!). Now, digging into refactoring, there are many possible ways to un'spaghettize our code:
I've seen people implement ACL at row level (looks kinda dumb and overkill)
It would be possible to turn models into behavior aware objects and not only data containers, something like $album->add_photo($photo) and check permissions at that function
It would also be possible to override model's save method and do there those checks
Or, follow the Laravel proposed road of having separate layers of concern
I suppose that having methods like $album->can_be_edited_by($user) may simplify the displaying of 404 erros on routes not allowed, hiding view's links as well as validating before saving the models
Which would you recommend, and does anyone know any simple, but understandable, example of repositories, entities and services not using .NET?
Thanks!
Edit: I guess that a full ACL system would cause excessive overhead, since there may be thousands of resources associated with each user, but only one role per kind of association. For instance, pictures will have an uploader_id and albums will have an owner_id.
I could be wrong but I think ACLs are OBJECT based permissions (i.e., a user can or can't delete photos in GENERAL). What you want is more custom MODEL based permissions (row level like you said), i.e., a user can delete photos that they themselves created (SPECIFIC ones).
Most Laravel packages are designed for object based permissions I think, but not https://github.com/deefour/authorizer - this one is a great hidden gem. We don't use it in our project but I found that it really covers all the bases we'd need.
We have really advanced model permissions on our app, I have them scattered throughout my models, but I take a very model centric approach, which isn't necessarily very "laravel-esque". In your example with delete, I would override the delete method in your model or listen for the eloquent event and prevent it there. If you have to prevent read/write on certain attributes you could even do that by extending your validator or using custom mutators/getters, serializers or listening on events. More on where to add business logic in my question/answer here: https://stackoverflow.com/a/27804817/796437
I'm still trying to find the best approach, if I do I'll update this - but thought I'd post.
In Laravel you can use Policies or use solutions, like Symfony Voters.
For Laravel exists same package - Laravel Simple Voters.
Using this, you can check access to custom objects, looks like this:
Access::isGranted('edit', $post) // current user can edit this post?
You can put this logic, to example, into middleware, if you wish check requests to controllers.