I am trying to figure out how to address this issue:
I have 3 tables with a many-to-many relationship.
Users *-* Roles *-* Permissions
I use a ORM to obtain data from them.
A method of my business layer must return users per permission, so I return objects with this class:
public class UsersPerPermission
{
public User[] {get;set;}
public Permission {get;set;}
}
But this class does not map to any table in the repository, it is something I generate from the existent tables. Where should this class live?
In other words:
Should I have a IRepository.GetUsersPerPermission()? And then that class should live in the repository.
Or should I have a IBusinessLayer.GetUsersPerPermission()? And then I have to invoke the CRUD methods in the repository?
It makes sense to put it in the business layer only, because the repository should just expose CRUD operations to tables... BUT, in order to execute this operation from the Business layer, I would have to execute several independent queries to get the data and create the 'UserPerPermission' class. In the other hand, if I place it in the repository, I can get that information in one shot using grouping.
Thanks!
PS: What is the name of this intermediate objects? 'transformations'?
In DDD, most entities and value objects should correspond to identified domain concepts that are part of your ubiquitous language. I usually try to limit many-to-many relationships and artificial association objects as much as possible. Eric Evans describes a few techniques allowing that in his book. When I have to create an association object, it must have a meaningful name with regard to the domain, basically I never name it Class1ToClass2.
In your scenario, it's even more artificial since your object :
Redundantly models an association that already exists (indirectly) in the original model.
Has a name that doesn't reflect any particular business concept.
Note that this kind of object wouldn't be useless if we were in the presentation or application layer as it could come in handy to have a structure containing exactly what is displayed on the screen (DTO). But I'm talking about the domain layer here, which should be devoid of such composite objects.
So I wouldn't create a UsersPerPermission class in the first place. If what you want is a list of users and User is an aggregate root, just create a GetUsersByPermission() method in UserRepository. It doesn't mean that you can't have a GetUsersByPermission() method in an application service as well, if it matches a use case of your application (a screen that displays the details of one permission and the list of users with that permission).
I agree with guillaume31 that there is no need to introduce a domain object "UsersPerPermission" to support a single use case.
There are two ways you can implement your use case using existing domain classes "User", "Role" and "Permission".
Solution one:
Assume you have: Permission --> Role --> User
Arrow denotes navigability. A Permission has association to a list of Roles and a Role has association to a list of Users.
I would add a method GetPermittedUsers() : List<User> to the Permission class, which is trivial to implement.
Th UI logic will invoke GetPermissions() of PermissionRepository then call GetPermittedUsers() on each Permission.
I assume that you use a ORM framework like hibernate(Nhibernate) and defines the many-to-many relationships correctly. If you defines eager loading for Role and User from Permission, the ORM will generate a query that joins Permission, Role and User tables together and load everything in one go. If you defines lazy loading for Role and User, you will load a list of Permissions in one query when you call PermissionRepository, and then load all associated Roles and Users in another query. Everything is load from database with up to three queries maximum. This is called a 1+n problem which most ORMs handle properly.
Solution two:
Assume you have: User --> Role --> Permission
Arrow denotes navigability. A User has a list of Roles. A role has a list of Permission.
I'd add getUsersByPermissions(List<long> permissionIds) : List<Users> to the UserRepository, and add getPermissions() : List<Permission> to the User class.
The implementation of the UserRepository need to join the User, Role and Permission tables together in a single query and load everything in one go. Again, most ORMs will handle it correctly.
Once you have a list of Users, you can create a method to build a Map<Permission, List<User>> quite easily.
To be honest, I muck like the solution one. I avoid to write a complicate method to convert a List of Users to to a map of Permission and Users, hence I don't need to worry about where to put this method. However solution one may create cyclic relationship between User, Role and Permission classes if you already have navigability in another direction. Some people don't like cyclic relationship. I think the cyclic relationship is acceptable even necessary sometime if you user cases demand it.
In a similar context I used a query method in a domain service that returns something like an
IEnumerable<KeyValuePair<PermissionName, IEnumerable<Username>>>
By using the KeyValuePair<> I avoided to pollute the domain model with an artificial concept (like UsersPerPermition). Moreover such a structure is immutable.
I didn't used a query method on the repository because, in my context, no entity was coupled with the other. So it wasn't matter for any of the repositories.
However this solution is useful for your GUI, if and only if you modelled correctly the identifiers of your entities (in your example both Permissions and Users are entities).
Indeed if they are shared identifiers that belong to the ubiquitous language that your users understand, they will be enough without further descriptions.
Otherwise you are just building a useful DTO for your GUI. It does not belong to the domain thus you should use the simplest possible thing that works (an ADO.NET query? something even simpler?).
Indeed, in my own scenario both the GUI and the domain used such a service (the GUI showing a preview of an elaboration).
In general, the domain model must mirror the domain expert's language, capturing the knowledge relevant to the bounded context. Everything else must be outside the domain (but most of time can be expressed in terms of the domain's value objects).
Related
I am using ABP Commercial to implement a custom CRM system. I am looking for an example, a best practice, a library, or even a framework for scoping data according to user IDs and roles.
Simple scoping like just showing entities created by a certain user is fairly straightforward. But what about showing increasingly more broad data based on a hierarchy of user roles.
For example, I might have a basic user role that can only see data created by the user in that role. Then, I might have a manager role that can see his own data and all the data created by the basic users he manages. Contemplating any decent size organization, you can see how this hierarchy might get quite deep.
So can anyone tell me whether there is a facility or module within ABP Commercial or ABP Framework to facilitate this kind of pattern or if there is third party best practice, library, or framework that might work in conjunction with my code to realize this functionality?
In the past I have written my own implementations but I am looking for a DDD or clean architecture based solution.
EDIT
A more specific example of what I'm trying to do is to create an extension of the user class and role class or to add additional entities managed by a domain service that would allow for:
users to have a collection of roles they manage and a collection of specific users they manage, and…
roles to have a collection of other roles they manage (think composite pattern)
These relationships would be used to filter all kinds of queries within my application.
Here are some use cases:
return a list of contacts associated with the clients of my direct reports
return a flattened list of all users managed by me or my reports
return the total revenue of all sales made by users managed by me or my reports
We are building a webapplication which uses a database. Also we use an object relational mapper to access the database. One aspect of authorization in the webapplication is that the user may access an object referred to by an URL. The URL contains a unique id (for example the Primary Key) to a specific record in the database. Consider the following example.
a user may belong to many groups and a group may have many users (many-to-many).
a survey belongs to a group (many-to-one).
a survey may have multiple questions. (many-to-one).
Say we have the following URL: http://app.local/question/edit/10. This means we want to edit question with PK 10. Now, we want to verify if the logged in user may access question with PK 10. This can be done by retrieving this question, then it's survey then it's group and then all its users. If any of the users is the same as the logged in user the logged in user may access the question.
To generalize this a bit; we want to check if a record is reachable from another record by the known many-to-one or many-to-many relations. So if there is a many-to-one relation (like with a survey and a question then we should check if a user is reachable from the question through the survey and then through the group. The group has a many-to-many relation with the user so we should check if any (not all) of the users is the same as the logged in user.
If a table has multiple many-to-one relations, say; we can attach a CSS template to a survey and this template also belongs to a group then we have to check if a user is reachable from all many-to-one relations (thus the group and the template). The same holds of course for multiple many-to-many relations.
Are there Object Relation Mappers which support this behaviour? And what is this behaviour called, maybe reachability? Does Propel (for PHP) support this behaviour? I think this reachability can be done in any of the following two ways:
Execute a query to get each "parent", uses many queries)
Join all necessary tables to see if a record exists (the reachable users matches the logged in user) in one query.
Furthermore this behaviour of the ORM should support nested sets, thus if a group contains nested set behaviour it should also try to reach a user through the group's parent.
I don't think this kind of behaviour should be restricted to authorization; objects should simply be able to see if they can reach another object.
Note that I do not mean persistence by reachability: http://jpaobjects.sourceforge.net/m2-site/main/documentation/docbkx/html/user-guide/ch08s03.html.
Or... am I simply looking at this authorization wrong and is there a far better and different approach with an ORM?
I've handled this in the past using nested resources in Ruby on Rails (which uses the Active Record ORM). Rather than http://app.local/question/10/edit, the URI would be http://app.local/survey/5/questions/10/edit
In the controller you load both the question and survey. You check authorization by comparing the survey to the authenticated user's group memberships. One way to engineer this would be to embed this logic into the User class. For example, in the controller you have question and survey (and the relationship between the two is well understood by the ORM, i.e. question.survey). You could then check access as user.hasAccess?(question), which would be a relatively easy method to write. Pseudocode:
class User < ActiveRecord::Base
def hasAccess?(question)
return question.group.users.include?(self)
Yes, this will result in several queries behind the scenes, but ORMs do the work. I do it this way because you're left with solid schema and easy to read code. Don't optimize until you actually have a performance problem.
I am new to this, so my understanding is still flaky.
I have a Person model and an AccountType model in my project. Each person references an account type.
Now if my understanding is correct a Person is definitely an aggregate root, whereas the AccountType probably isn't as the entries in the account type table are going to be pretty much static and are certainly have no meaning outside of a Person.
However when I create a new person I need to set the account type, so it would seem I need a repository to access the account type to assign to the user, but the repository code I have only allows aggregate roots to be accessed.
What would be the correct way to structure this?
I think that AccountType is another aggregate root which is referenced from the Person aggregate root.
It's absolutely normal to have many simple aggregate roots, see Vaughn Vernon articles, see part 1, p. 5:
On one project for the financial derivatives sector using
[Qi4j], Niclas [Hedhman] reported that his team was able to
design approximately 70% of all aggregates with just a
root entity containing some value-typed properties. The remaining 30% had just two to three total entities. This doesn't indicate that all domain models will have a 70/30 split. It
does indicate that a high percentage of aggregates can be
limited to a single entity, the root.
In your question it's not quite understood, what is the problem with accessing repositories to initialize the aggregate root's properties:
However when I create a new person I need to set the account type, so it would seem I need a repository to access the account type to assign to the user, but the repository code I have only allows aggregate roots to be accessed.
The initialization of the Person class should be handled by PersonFactory.
The PersonFactory is a service, so it can have reference to AccountTypeRepository to find a suitable AccountType instance and return a fully constructed Person instance of that type.
update: Also I'd like to add a note that referencing your AccountType by id works equally well. It's all matter of convenience, sometimes it's more convenient(only for displaying, not for modifying, of course) to access the references directly if you use GUI frameworks with rich data binding capabilities like WPF or Spring MVC so you can directly access this properties to display in View. If you are using the id approach, this may force you to create ViewModels (FormBeans) even for the simple Entities.
Regarding the lookup-based solution, it works well for very simple enum-like fields, I suppose that AccountType is something more complex than that and belongs to the knowledge level (see the discussion of the question).
Returning to the choice between aggregates and value object(also see this), it depends on the abstraction level and configuration capabilities of your information system.
From the point of view of the Account class it may look like a value object, you can replace one AccountType with another: it will be just like switching between Color value objects, but from the point of the knowledge level your user may want to customize the behavior of the system for selected AccountType, for example change discounts for specific "Premium" accounts. So if you have the knowledge level, AccountType will be something with an identity which leads you to creating a separate repository.
The most important thing is (assuming AccountType has an entity with an ID and is not a simple enum)...
Account Type and Person should only reference each other by ID.
I have some basic objects like Customer, Portfolio and ... with some association to other objects. I can easily display the required information in the web page by reading object values. The problem is that what do I do when the value associated with the object is calculated and returned by a method, a value that makes sense only in certain context and cannot be attached to the object as an instance variable? In this case if I have a list of say Users I have to pass the username of each user to the method to get the calculated value. This causes problem to keep the association while displaying the values in the page.
An example to make this clear:
An application provides the functionality for users to keep track of each others activities by letting them add whoever they want to a list. If this user performs a search on users there's the option to follow each returned user. I want to make sure this option is disabled for those user's that are already being followed. This functionality is provided by a method like isFollowed(String follower, String followee) which returnes a boolean. How can I associate this boolean values to each user in search result?
Solutions:
One thing I can think of is to add a followed instance variable to User class. But I don't think it's a good approach because this variable only makes sense in a certain context. It's not a part of User class in the domain.
The other way I can think of is to use Decoration or Wrappers in a way to extend the User class and add the attribute in the child class. But again what if I have several objects that need to be in the same context. In that case I have to extend all of them with the same boolean attribute in all classes.
I hope I could make it clear.
In principle, I don't see anything wrong with instance method on User: bool IsFollowedBy(User user).
Of course, this could lead to performance issues. If that is the case, you can create separate object for presentation purposes which bundles data from User and whether he is being followed by the user performing search. Then you can build query which retrieves all necessary data for such object in a single roundtrip to DB.
One solution is to avoid querying Entities (as in DDD/ORM) and query directly using subquery/join or even using some denormalized database. This is something CQRS pattern suggests.
Other solution is to do computations on application layer (how many Users can you show on the same page anyway), which is expensive but you can implement some caching techniques to make things easier.
I'm modeling a very basic ASP.NET MVC app using NHibernate and I seem to be stuck on my design. Here's a sketch of my model:
As you can see this is VERY basic but I have some concerns about it. The User root entity and the Organization root entity are accessing the same Organization_Users entity child via two one-to-many relationships. This doesn't seem right and I think I am breaking the aggregate boundaries. This model smells to me but I like the idea because I would like to have code like this:
var user = userRepository.Load(1);
var list = user.Organizations; // All the organizations the user is a part of.
and
var org = orgRepository.Load(1);
var list = org.Users; // All the users in an organization.
Also the extra data in the table like flagged and role would be used by the Organization entity. Is this a bad design? If you have any thoughts that would be great. I'm still trying to get my mind around the thinking of DDD. Thanks
This is a typical Many-To-Many relationship. And the Organization_Users tables is the bridge table. Infact NHibernate and all the other ORM tools have built-in feature to support bridge table.
This thing should be resolved at data modelling level rather than at application level. You should analyze your data model and it is recommended to avoid many-to-many relationships (in the sense if it is not the necesity of domain model, you should try to avoid many-to-many relationship).
First thing first you need to be sure that many-to-many relationship in data model is necessary for mapping domain entities. Once you have done this then the model represented in your diagram is ok for mapping those relationships at application level
I have used an approach similar to your first model on several occasion. The one catch with this approach is that you need to create an OganizationUser class in your domain to handle the Role and Flagged fields from you Domain. This would leave you with something like this in your code.
var user = userRepository.Load(1);
var list = user.OrganizationUsers; // All the organizations the user is a part of including their role and flagged values.
var organization = list[0].Organization;
*If you're going to be iterating through all a users organizations quite often you'd likely want to eager load the Organization entity along with OrganzitionUser
With the second design you submitted it looks like you would be able to add a user to the OrgUserDetails without adding the user to OrganizationUser. That doesn't seem like something I would want to support from my Domain.
The first things to consider in DDD are :
forget your database schema (there's
no database !)
what actions will you perform on thoses entities from a domain perspective ?
I think your model is fine. I usually think of domain aggregate roots, when I think of them at all, in terms of what is publicly exposed, not internal implementation. With relationships I think of which entity "wears the pants" in the relationship. That is, is it more natural to add a User to an Organization or add an Organization to a User? In this case both may make sense, a User joins an Organization; an Organization accepts a User for membership.
If your domain sees the relationship from the User's perspective, you can put the methods to maintain (add, remove, etc.) the relationship on the User and expose a read-only collection on the Organization.
In response to your second design (it would have been better if you had edited the original question): I don't like it at all. Your original design is fine. I wouldn't necessarily ignore the database while designing your classes, a good design should accurately model the domain and be straightforward to implement in a relational database. Sometimes you have to compromise in both directions to hit the sweet spot. There's no jail term for breaking aggregate boundaries. :-)
My understanding is:
A User can belong to 0-to-many Organizations.
AND
An Organization consists of 0-to-many Users.
Are both of those correct? If so, that does sound like a many-to-many to me.
In a many-to-many, you pretty much need a relationship-like object of some sort to bridge that gap. The problem is, there is no user_organization in the domain.
This makes me think you shouldn't have user_organization as a part of your domain, per se. It feels like an implementation detail.
On the other hand, maybe it makes sense in your domain to have a Roster which holds the Users in an Organization and stores their role and other information specific to that relationship.
Thanks everyone for your answers. They have been very helpful.
While I was thinking about my model a little bit more, I sketched something new that I think would be better.
My thinking was this:
When a user logs into the site the system finds their account and then returns a list of organizations they are apart of and it gets this info from the user_organizations object.
When a user clicks on one of the organizations they are apart of it directs them to the organization's control panel.
The selected organization then looks up that user's role in its org_user_details to know what access the user should have to that organizations control panel.
Does that make sense? :)
I feel like that would be good in a model but I'm having some doubts about the DB implementation. I know I shouldn't even worry about it but I can't break my bad habit yet! You can see that there is kind of duplicate data in the user_organizations object and the org_user_details object. I'm not a DB pro but is that a bad DB design? Should I instead combine the data from user_organizations and org_user_details into a table like the one in my first post and just tell NHibernate that User looks at it as a Many-to-Many relationship and Organization looks at it as a One-to-Many relationship? That sounds like I'm tricking the system. Sorry if I seemed really confused about this.
What are your thoughts on this? Am I over thinking this? :P