Reputation: 6417
I am trying to use repositories in my MVC program designs and I have run up against a problem on how to best structure them.
as an example, say I have an object USers and I have a UserRepository which has functions like getUser(int id)
, saveUser(Dal.User model)
etc...
So If in my controller I have EditUser and I want to display a view that will have a user details input form. so I can do something like this:
User user = _userRepository.getUserDetails(userId);
The benefit being that my controller just deals with processing HTTP requests, and business logic is moved to repositories, making testing etc easier
So, say I want to display a drop down list of possible roles this user could have in my system, ie client, admin, staff etc
is it ok to have a function in the _userRepository called getPossibleUserRoles() or should I have a seperate _roleRepository with a function getRoles() ?
IS it a bad idea to inject a repository for every entity you encounter into your controller? or is it a bad idea to mix entities inside your repositories, making them cluttered.
I realise I have presented a very simplistic scenario, but obviously as systems grow in complexity you are potentially talking of 10s of repositories needing to be instantiated in a controller for every page call. and also possibly instantiating repositories that are not being used in current controller methods simply to have them available to other controller methods.
Any advice on how best to structure a project using repositories appreciated
Upvotes: 1
Views: 148
Reputation: 4382
is it ok to have a function in the _userRepository called getPossibleUserRoles() or should I have a seperate _roleRepository with a function getRoles() ?
Let's say you have some controllers call:
_userRepository.getUserDetails(userId);
but they never call:
_userRepository.getPossibleUserRoles(userId);
Then you are forcing your controllers to depend on methods they do not use.
Sot it's not just ok, you should split this.
But if getUserDetails
and getPossibleUserRoles
are chosive (sharing same entity, sharing same business logic etc..).
You can split this without changing implemantation of userrepository beside of creating new class for Roles
.
public class UserRepsitory : IUserRoles, IUserRepository
{
}
I realise I have presented a very simplistic scenario, but obviously as systems grow in complexity you are potentially talking of 10s of repositories needing to be instantiated in a controller
If a constructor gets too many parameters, there is high posibility SRP violation. Mark Seemann shows how to solve this problem in here.
In a short way: While you are creating a behaviour, if you use always 2 or more than repositories together. Then, these repositories are very close. So you can create a service and orchestrate them in this service. After that, you can use this service as a paremeter beside of using 2 or more repositories in your controller constructor.
Upvotes: 1
Reputation: 6781
is it ok to have a function in the _userRepository called getPossibleUserRoles() or should I have a seperate _roleRepository with a function getRoles() ?
Both solutions are acceptable but consider how you're going to control the proliferation of repositories and methods on those repositories. IMHO, the typical repository usage scenario tends to end-up with too many repositories with too many methods on each. DDD advocates a repository per aggregate root. This is a good rule of thumb... if you're following DDD principles.
IS it a bad idea to inject a repository for every entity you encounter into your controller? or is it a bad idea to mix entities inside your repositories, making them cluttered.
Inject volatile dependencies, so yes, inject a repository for every entity your controller needs. However, once you start injecting more than four dependencies, chances are you've missed an abstraction somewhere in your design. Some solve this problem with RepositoryFactory
but this, arguably, introduces the problem of opaque dependencies and, IMHO, fails to convey the class's real dependencies, reducing its usability and self-document-ability.
Take a look at using query objects rather than repositories (https://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/, etc.) and take a look at using orchestration/mediation (http://codeopinion.com/thin-controllers-cqrs-mediatr/) in your controllers. I think you'll find a better design emerges that will help you with your design issues.
Upvotes: 1