Mai*_*eyy 14 c# architecture asp.net repository-pattern
在为我的ASP.NET项目实现存储库模式时,我遇到了一些我无法理解的问题.所以我对如何以正确的方式实现存储库模式有几个问题.
根据我的经验,我认为只有在我的应用程序中,没有行为的类/模型,在他们的存储库旁边并不是很好的OOP.但是,这是我实现存储库模式的方式.我只是到处都需要一个存储库实例,来执行一些操作.这种方法的结果是我的所有域类都没有行为.
它们只是没有方法的数据对象.我的老师告诉我,我正在使用薄模型,我应该努力制作胖模型.为了回应这些反馈,我在类中实现了一些业务逻辑,但是我遇到了一些问题:
场景:
我的User班级中有一个包含用户对象的朋友列表,代表某个用户的朋友.向用户添加新朋友时,域类方法会检查朋友列表中是否已存在"朋友".如果没有,他将被添加到列表中.需要将这些更改发送到数据库以实现持久性.
我知道这必须在每个域类的存储库中完成,但是对存储库方法的调用在哪里属于应用程序的体系结构?
现在我调用域类方法本身的存储库方法,以保持对数据库的更改:
public void AddFriend(User friend)
{
foreach(User f in Friends)
{
if(f.Username == friend.Username)
{
throw new Exception(String.Format("{0} is already a friend.", friend.Username));
}
}
Friends.Add(friend);
userRepo.AddFriend(this.Id, friend.Id);
}
Run Code Online (Sandbox Code Playgroud)
这是一个很好的方法,因为某些原因我认为不是.关于单元测试,我们需要使用这种方法进行一些依赖注入,它告诉我它不是一个独立的类(良好的可测试单元).我读过一些人说他们使用额外的服务层或其他东西的帖子.我认为这里需要这种抽象,但某个服务层是怎样的?它是什么,哪些方法等?
我见过其他一些学生在域类中使用静态方法,它提供了添加新对象,更新对象,删除对象和获取所有对象等功能.
例:
public class Tram
{
private static TramRepository Repo = new TramRepository(new DBTram());
public static void AddTram(int tramID, TramType type, int lineNr)
{
Tram tram = new Tram(tramID, type, TramStatus.depot, lineNr, true, null);
Repo.AddTram(tram);
}
public static List<Tram> GetAll()
{
Repo.GetAll();
}
}
Run Code Online (Sandbox Code Playgroud)
我发现在域类中将一个新实体添加到数据库中的方法是一个奇怪的事情,即该实体本身.同样对于GetAll()方法,我认为在类本身中拥有一个获取所有trams的方法是很奇怪的.所以电车对象可以获得所有电车.我认为这是实现存储库模式的一种奇怪方式.我对吗?
那么,这里需要什么样的抽象?是否需要额外的图层?如果是这样,这个层怎么样?(示例代码)或者我正在寻找错误的方向,是否有另一种解决方案可以解决使用存储库模式的单元测试问题?
我每次遇到这个架构问题,确保我需要它来回答.
我发现很难清楚地解释这个问题,但我希望你们能理解它.
你的问题绝对正常,但不要指望找到绝对的答案。欢迎来到软件行业!
这是我的意见:
- 拥有一个依赖于在其存储库旁边仅具有保存值而没有行为的值的模型/类的应用程序是否是好的 OOP?
我认为您尝试实现存储库模式,但您错过了更高的架构视图。大多数应用程序至少在 3 层中解耦:查看(演示)、业务和数据访问。存储库模式发生在 DataAccess 中,您可以在这里找到纯数据对象。但是这个数据访问层是由业务层使用的,您将在其中找到域模型、具有业务行为和数据的类。单元测试工作必须在业务层的域模型上进行。这些测试不应该关心数据是如何存储的。
- 我在哪里调用应用程序架构中的存储库方法?
同样没有绝对的答案,但通常使用类似商业服务的东西是有意义的。这些服务可以安排不同领域对象之间的流程,并加载它们,并将它们保存在存储库中。这基本上就是您在 AddFriend 类中所做的,它属于业务层。
关于单元测试,我们需要使用这种方法进行一些依赖注入,这对我说它不是一个独立的类
业务服务通常依赖于存储库,这是单元测试的一个非常常见的情况。Tram 类可以持有业务行为,并且仍然是独立的。AddTram 业务服务需要一个存储库,并且依赖注入允许对其进行测试。
- 在数据库中插入、更新和删除新实体的方法是否应该在类本身中?
对于这一点,我可以明确而大声地:请不要这样做,是的,CRUD 操作属于 Tram 存储库。这当然不是商业逻辑。这就是为什么在您的示例中您需要两个不同层中的两个类:
“因为我看到其他一些学生在提供这些功能的域类中使用静态方法”
使用静态方法显然不是一个好主意,这意味着任何人都可以通过您的对象存储数据,即使它应该处理业务案例。再说一次,数据存储不是商业案例,而是技术必需品。
现在公平地说,所有这些概念都需要在上下文中讨论才能有意义,并且需要在每个新项目中进行调整。这就是为什么你的工作既困难又令人兴奋:环境为王。
我还写了一篇以 MVVM 为中心的博客文章,但我认为它可以帮助理解我的答案。