存储库模式 - 构建存储库
Repository Pattern - Structuring repositories
我正在尝试在我的 MVC 程序设计中使用存储库,但我 运行 遇到了如何最好地构建它们的问题。
例如,假设我有一个对象 USers 和一个 UserRepository,它具有 getUser(int id)
、saveUser(Dal.User model)
等功能...
因此,如果在我的控制器中我有 EditUser,并且我想显示一个包含用户详细信息输入表单的视图。所以我可以这样做:
User user = _userRepository.getUserDetails(userId);
好处是我的控制器只处理处理 HTTP 请求,业务逻辑被移动到存储库,使测试等更容易
所以,假设我想显示一个下拉列表,其中包含此用户在我的系统中可能拥有的角色,即客户、管理员、员工等
在 _userRepository 中有一个名为 getPossibleUserRoles() 的函数是否可以,或者我应该有一个单独的 _roleRepository 和函数 getRoles() 吗?
将您遇到的每个实体的存储库注入到您的控制器中是个坏主意吗?或者在你的存储库中混合实体是不是一个坏主意,使它们变得混乱。
我意识到我提出了一个非常简单的场景,但显然随着系统复杂性的增加,您可能会谈到需要在控制器中为每个页面调用实例化 10 个存储库。并且还可能实例化当前控制器方法中未使用的存储库,只是为了让它们可用于其他控制器方法。
任何关于如何最好地使用存储库构建项目的建议表示赞赏
is it ok to have a function in the _userRepository called getPossibleUserRoles() or should I have a seperate _roleRepository with a function getRoles() ?
两种解决方案都可以接受,但请考虑您将如何控制存储库和这些存储库上的方法的扩散。恕我直言,典型的存储库使用场景往往会以太多的存储库结束,每个存储库都有太多的方法。 DDD 提倡每个聚合根一个存储库。这是一个很好的经验法则...如果您遵循 DDD 原则。
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.
注入可变依赖项,所以是的,为您的控制器需要的每个实体注入一个存储库。然而,一旦您开始注入四个以上的依赖项,您很可能在设计中的某处遗漏了抽象。有些人用 RepositoryFactory
解决了这个问题,但可以说,这引入了不透明依赖关系的问题,恕我直言,未能传达 class 的真正依赖关系,降低了它的可用性和自文档能力。
看看在控制器中使用查询对象而不是存储库 (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/)。我认为您会发现更好的设计出现,可以帮助您解决设计问题。
is it ok to have a function in the _userRepository called
getPossibleUserRoles() or should I have a seperate _roleRepository
with a function getRoles() ?
假设您有一些控制器调用:
_userRepository.getUserDetails(userId);
但他们从不打电话:
_userRepository.getPossibleUserRoles(userId);
那么你就是在强迫你的控制器依赖于它们不使用的方法。
所以这不就可以了,你应该分开这个。
但是如果 getUserDetails
和 getPossibleUserRoles
是选择性的(共享相同的实体,共享相同的业务逻辑等)。
除了为 Roles
.
创建新的 class 之外,您可以在不更改 userrepository 实现的情况下拆分它
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
如果构造函数获取过多参数,则很可能违反 SRP。 Mark Seemann 在 here.
中展示了如何解决这个问题
简而言之:在创建行为时,如果您总是同时使用 2 个或更多存储库。然后,这些存储库非常接近。所以你可以创建一个服务并在这个服务中编排它们。之后,除了在控制器构造函数中使用 2 个或更多存储库之外,您还可以将此服务用作参数。
我正在尝试在我的 MVC 程序设计中使用存储库,但我 运行 遇到了如何最好地构建它们的问题。
例如,假设我有一个对象 USers 和一个 UserRepository,它具有 getUser(int id)
、saveUser(Dal.User model)
等功能...
因此,如果在我的控制器中我有 EditUser,并且我想显示一个包含用户详细信息输入表单的视图。所以我可以这样做:
User user = _userRepository.getUserDetails(userId);
好处是我的控制器只处理处理 HTTP 请求,业务逻辑被移动到存储库,使测试等更容易
所以,假设我想显示一个下拉列表,其中包含此用户在我的系统中可能拥有的角色,即客户、管理员、员工等
在 _userRepository 中有一个名为 getPossibleUserRoles() 的函数是否可以,或者我应该有一个单独的 _roleRepository 和函数 getRoles() 吗?
将您遇到的每个实体的存储库注入到您的控制器中是个坏主意吗?或者在你的存储库中混合实体是不是一个坏主意,使它们变得混乱。
我意识到我提出了一个非常简单的场景,但显然随着系统复杂性的增加,您可能会谈到需要在控制器中为每个页面调用实例化 10 个存储库。并且还可能实例化当前控制器方法中未使用的存储库,只是为了让它们可用于其他控制器方法。
任何关于如何最好地使用存储库构建项目的建议表示赞赏
is it ok to have a function in the _userRepository called getPossibleUserRoles() or should I have a seperate _roleRepository with a function getRoles() ?
两种解决方案都可以接受,但请考虑您将如何控制存储库和这些存储库上的方法的扩散。恕我直言,典型的存储库使用场景往往会以太多的存储库结束,每个存储库都有太多的方法。 DDD 提倡每个聚合根一个存储库。这是一个很好的经验法则...如果您遵循 DDD 原则。
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.
注入可变依赖项,所以是的,为您的控制器需要的每个实体注入一个存储库。然而,一旦您开始注入四个以上的依赖项,您很可能在设计中的某处遗漏了抽象。有些人用 RepositoryFactory
解决了这个问题,但可以说,这引入了不透明依赖关系的问题,恕我直言,未能传达 class 的真正依赖关系,降低了它的可用性和自文档能力。
看看在控制器中使用查询对象而不是存储库 (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/)。我认为您会发现更好的设计出现,可以帮助您解决设计问题。
is it ok to have a function in the _userRepository called getPossibleUserRoles() or should I have a seperate _roleRepository with a function getRoles() ?
假设您有一些控制器调用:
_userRepository.getUserDetails(userId);
但他们从不打电话:
_userRepository.getPossibleUserRoles(userId);
那么你就是在强迫你的控制器依赖于它们不使用的方法。
所以这不就可以了,你应该分开这个。
但是如果 getUserDetails
和 getPossibleUserRoles
是选择性的(共享相同的实体,共享相同的业务逻辑等)。
除了为 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
如果构造函数获取过多参数,则很可能违反 SRP。 Mark Seemann 在 here.
中展示了如何解决这个问题简而言之:在创建行为时,如果您总是同时使用 2 个或更多存储库。然后,这些存储库非常接近。所以你可以创建一个服务并在这个服务中编排它们。之后,除了在控制器构造函数中使用 2 个或更多存储库之外,您还可以将此服务用作参数。