在为中型MVC web应用程序规划体系结构时,如何实现层的尽可能解耦和易于测试?(基本上遵循最佳实践),假设我首先使用代码作为我的数据访问。
我很难将“业务逻辑”定义为什么,以及它是如何与数据层交互的。以汽车销售应用程序为例,业务逻辑是否是执行诸如计算给定车辆的税阶、比较每加仑的里程统计等任务的类?至于业务实体(例如汽车、货车、摩托车),我会将它们与我的DataContext类一起放在数据层中。
另外,什么会构成应用程序逻辑而不是业务--我猜是会话/用户输入验证之类的东西?
例如,一个汽车控制器可能返回一个操作/视图结果,其中列出了按类型和最佳mpg筛选的前十位汽车。因此,假设我将一个ICarRepository 'carRepo‘注入到我的控制器中(使用存储库模式/ DI),我从一个动作方法参数(例如var cars = carRepo.getCarsByType("hatchback"); )中过滤我的汽车
因此,我使用存储库将数据访问知识从控制器中保留下来,现在使用域模型- var result = new MpgCalculator(Cars)使业务逻辑远离控制器;-假设我需要计算器类,因为它需要执行额外的逻辑来计算最佳燃油效率,而不仅仅是从DB加载/过滤实体。因此,现在我有了一个用于视图的数据集,它使用存储库从数据访问层检索,并且使用特定于域的对象来处理和执行与业务相关的任务。
我在这里犯错误了吗?我们是否仍然需要使用存储库模式,还是只需要针对接口编写代码来解耦ORM和测试?在这个主题上,由于我的具体数据访问类(S) dbcontext在数据层,接口定义是否应该进入域/业务层,意味着如果数据访问技术发生了变化,我的其他层就不会受到影响?
从我迄今所研究的情况来看,我的结构如下:
MVC Internet应用程序->标准internet项目这里的模型是ViewModels
域/业务层->特定于业务的类/模型,控制器在传递到相关视图之前可以使用这些类/模型从数据层处理域实体
存储库抽象是必需的吗?-> --我听到了很多关于这方面的争论,特别是在使用ORM时。
数据层->实体类(Car,Van,摩托车),DbContext -具体数据访问技术层
发布于 2013-10-04 23:47:44
您的问题中有很多可移动的部分,涉及到许多概念,但在谈到如何考虑中到大型MVC应用程序时,以下是我的基本建议:
首先,最好不要把这个应用程序看作是“MVC应用程序”。它是一个应用程序,它使用MVC模式作为其表示组件。通过这种方式来思考,将有助于您将业务逻辑问题与演示所关注的问题区分开来。也许小型应用程序可以把所有东西都堆到MVC结构中去访问数据库,但对于中到大型的应用程序来说,它很快就站不住脚了。
在您的应用程序中,ASP.NET MVC组件应该处理为显示目的(模型)转换业务数据、显示用户界面(视图)以及诸如路由、身份验证、授权、请求验证、响应处理等通信问题(控制器)。如果您的代码做了其他事情,那么它不属于MVC组件。
在您的应用程序中,数据访问层也应该关注检索和存储持久数据。这通常是以关系数据库的形式进行的,但是有许多其他方法可以持久化数据。如果您的代码没有读取或存储持久数据,那么它不属于数据层。我以前分享过关于ORM/资源库讨论的几点思考,但是简单地说,我不认为ORM与存储库是一样的,原因有几点。
现在您有了表示层(MVC)和数据层(存储库或ORM) .其他一切都是您的业务逻辑层(BLL)。所有决定检索哪些数据、执行复杂计算或做出业务决策的代码都应该在这里。我通常以‘服务’的形式组织我的业务逻辑,我的表示层可以调用它来完成所要求的工作。我所有的领域模型都存在于此。
这就是你的方法对我来说有点坏了。您将您的MVC控制器描述为从存储库中获取数据的地方,并调用MPGCalculator来做一些工作等等。我不想让我的控制器做任何事情,而是将所有这些委托给BLL中的一个服务。
换句话说,我不会将存储库和MPGCalculator注入控制器,这给控制器带来太多的责任(它已经处理了我前面提到的所有控制器内容)。相反,我将在BLL处理所有这些操作中提供一个服务,并将结果传递给控制器。然后,控制器可以将结果转换为正确的模型,并将其传递给正确的视图。控制器中没有任何业务逻辑,唯一注入控制器的是适当的BLL服务。
这样做意味着您的业务逻辑(例如,给定一组工具、计算MPG并对最坏的情况进行排序)与表示和持久性无关。它通常位于一个不知道或不关心数据持久性策略或表示策略的库中。
发布于 2013-10-04 21:41:44
看起来一切都适合你的结构。我不确定的唯一一点是,您提到MVC中的模型是"ViewModels“,并且您的控制器与域层对话。我认为,如果您的默认模式是使用控制器访问域层,然后使用"ViewModels“作为来自多个域实体的更多视图特定的信息编译,这对特定视图是有意义的。如果这就是你正在做的事情,那么你很可能会没事。
有一种观点认为,如果要使用MVC应用程序,就应该对您的域层进行完整的抽象。就我个人而言,在企业应用程序中这样做的想法会给我带来严重的精神痛苦。
我更喜欢使用存储库模式来管理对数据层的访问,因为它增强了可测试性和灵活性。两件事往往是最剧烈的变化是UI和数据库。想象一下,如果将直接从数据库中提取的一些信息更改为必须从服务调用(而不是数据库调用)检索信息,或者将某些信息移动到需要不同.edmx文件的不同数据库中。存储库模式提供了支持这一功能的抽象。
https://softwareengineering.stackexchange.com/questions/213317
复制相似问题