需要一些关于ASP.NET MVC 3体系结构的指导
本文关键字:MVC 体系结构 NET ASP | 更新日期: 2023-09-27 18:21:59
我是一名经验丰富的.NET开发人员,主要从事Web表单的开发。我熟悉MVC,但还没有在商业上使用过它。我目前正在这一领域进行一些自我教育,对建筑主题的意见分歧感到有些困惑,让我在这个问题的前面加上一个理解,即没有对错答案,但我只是在寻求一个优雅的解决方案。
我首先要说的是,我没有使用实体框架或任何形式的ORM——我想直接实现我自己的业务对象和数据访问代码(使用ADO、SPROC等),以确保它们是最佳的,这是我个人的偏好。这就是我努力寻找一致信息的地方,因为似乎大多数信息都与LINQ to SQL或实体框架的使用有关。
我的申请由以下项目组成:
- Web(MVC 3 Web应用程序)
- 模型(类库)
只有两个项目,因为我在脱钩方面遇到了问题;这是我问题的根源。我的模型类库包含…
- 具有字段和属性的经典业务对象
- 每个业务对象的存储库类,其中包含数据访问代码(ADO.NET直接式SqlDataReaders等)
- 每个存储库类的接口
我遇到的问题是所有这些层之间的依赖关系。感觉一点都不对劲!
1.业务对象应该包含实现业务逻辑的方法,所以除了字段和属性之外,还有实现任何所需逻辑的方法吗?
2.存储库类执行数据访问代码,但知道业务对象,这再次感觉不对,数据访问代码应该放在自己的类库中,对对象一无所知?
3.控制器(在web层)利用存储库接口,但为什么?它们不应该包含业务逻辑,"模型"或业务对象应该包含吗?控制器当然不应该包含业务逻辑,所以这也是不对的。我不希望业务逻辑出现在存储库中,因为它们正在访问数据库。
我正在努力为应用程序找到一个优雅的体系结构,只是如何实现我自己的对象、我自己的数据访问代码以及确保应用程序松散耦合的基本概述。有人能为我提供指导吗?
我建议对您的解决方案结构进行一些更改。
例如,项目的结构可以如下:-
核心库
这将是简单的POCO,代表您的域数据和任何服务的接口。这里没有商业逻辑。只是简单的属性。
例如。
公共类用户{public int UserId{get;set;}公共字符串名称{get;set;}}
- Core
'Entities <-- Poco's
'Services <-- Interfaces for services
服务
这将是您包含业务逻辑的地方。用户如何验证?我们如何计算订单何时应该自动存档或其他什么?一般来说,我在这里不做任何数据库方面的工作。
存储库
这是你做基本数据库工作的地方。你说你没有使用L2S或EF等。没有问题。我会认真考虑使用Micro ORM,比如Dapper或Massive。
测试
你在做单元和集成测试,对吧?我推荐xUnit或nUnit作为测试框架。
Web应用程序
这是MVC3应用程序。我建议使用StructureMap进行依赖注入。(您使用的是IoC/DI,对吧?)
一开始你可能会想->太多的项目了,对吧?嗯,很容易把它分成两个项目。
- Web应用程序
- 测试项目
核心库、服务和存储库都以文件夹的形式存在于Web应用程序项目中。
尽量不要过度设计Visual Studio解决方案。大多数人认为他们需要大量的项目和大量的抽象。。因为他们认为其他人都在这么做,这是正确的。嗯,这种想法是在2000年代早期。。2012年,很多shiz都发生了变化。
尝试使用DI/IoJ、NuGet将这些库下载到您的解决方案中,使用Micro OR/M进行数据访问和测试项目。
一些项目需要检查,re:事情是如何安排的:
- JabbR.net
- RavenOverflow
-
也许,如果模型需要的话。大多数模型都是具有公共属性的简单dto。但你可以很容易地封装其中的一些。
-
不完全是。存储库是业务对象的集合。它可以从数据库中创建这些对象的实例。
-
控制器是控制服务器上发生的事情的入口点。reads将数据从存储库加载到视图模型中,并将视图模型推送到视图中。写入操作将从存储库加载数据,更新域并保存更改。然后重定向到读取控制器动作。
最重要的是。不要过度考虑架构。这种情况发生得太多了。开发人员想要干净的代码,并使其维护起来更复杂,而不是更简单。
无论您是否使用数据库或ORM都无关紧要,您的存储库中都有相同的功能。
我认为从小处开始是好的,然后随着需要的出现,你开始扩大你的视野,并开始根据需要分离层。如果您在数据库中有2个模型、1个视图和一个表要查询和更新,为什么要将您的工作分成20个项目呢。
从小处着手,让"需求"驱动设计。如果您需要在数据库中读取/写入大量表,那么现在可能是时候开始使用存储库模式了。你发现你现在需要至少10个或更多不同的模型——现在可能是时候实现一个库来包含DTO/模型,并将它们从web应用程序中删除了。
例如,如果您需要编写单元测试或进行TDD,您会发现能够直接模拟存储库、业务和服务层非常有用。
不过,为了便于讨论,我看到了与以下项目类似的项目(但大多数项目不需要这种级别的分离):
- 网络项目;使用服务库与dto库
- 服务图书馆;使用业务层库和dto库
- 业务层库;使用存储库、实体库和dto库
- 存储库;使用实体库
- 实体库
- dto库
其中大多数甚至被进一步分解为单独的库,其中包含接口,另一个包含实现,等等。我参与过的一些项目有50多个库,可以分离大部分(如果不是全部的话),但它总是基于需求或需要。
上面示例的思想是让web应用程序只处理将DTO传递给服务调用和从服务调用接收DTO。
大多数情况下,您可以将DTO用作模型,但有时,如果您需要一个基于多个DTO的平面模型,则可以创建自己的视图模型作为包装器来展开多个DTo。
该服务进入并调用管理器中的一个方法,传递驻留在业务层库中的DTO。该管理器将使用DTO并将其映射到一个或多个实体,并调用存储库上传递这些实体的方法。存储库返回管理器用来构造要发送回的DTO的实体。
有很多方法可以做到这一点,我相信没有一种是唯一正确的方法。
例如,您可以使用像Ninject这样的依赖注入框架来实现进一步的分离和独立。
以上只是一个例子。它可能对一组人很有效,而另一组人则认为这是不可接受的。这取决于许多因素,项目的规模是主要因素之一。
不过,除此之外,始终从一个可管理大小的架构开始,当需要更改时,您将不断地重新考虑,无论是为了满足单元测试中的嘲笑,模型的数量在web应用程序中变得无法管理,还是现在必须由一个单独的团队编写服务层,而您不希望这会干扰您的开发,服务层现在可能必须由不同的UI层使用,而不仅仅是web前端等。
几点:
-
存储库中有"业务逻辑"是没有问题的。事实上,你的大部分"商业逻辑"都会存在。您的存储库包含查询,如果这些查询非常有趣,那么这些查询将与您的"业务逻辑"密切相关。
-
控制器中有"业务逻辑"是没有问题的。控制器控制着用户界面,用户界面的工作方式是"业务逻辑"。
-
根据定义,在分层架构中,每一层都知道其上一层的公共接口。您的数据访问可以看到域层的公共界面。用户界面层可以看到服务层的公共界面。
-
如果你的项目太小,以至于你可以手动编码自己的数据访问层,而不是使用ORM或类似的东西,那么拥有一个完全解耦的星舰企业架构可能只会让你的生活变得最困难。(我的意思是,我认为你正在疯狂地编写自己的数据访问层——至少可以尝试像Dapper这样的轻量级框架)。
-
根据自己的需要做出选择。问问自己"为什么X需要与Y脱钩"。答案可能是"所以当我对Y进行单元测试时,我可以模拟X"。答案可能是"所以我可以在我的另一个项目中使用X,而不需要知道Y"。如果你找不到答案,那么YAGNI。