asp.net-mvc “业务逻辑层”在哪里适合 MVC 应用程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4565681/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Where does the "business logic layer" fit in to an MVC application?
提问by Erik Funkenbusch
First, before anyone screams dupe, I had a hard time summarizing it in a simple title. Another title might have been "What is the difference between a domain model and MVC model?" or "What is a model?"
首先,在有人尖叫受骗之前,我很难用一个简单的标题来概括它。另一个标题可能是“域模型和 MVC 模型之间有什么区别?” 或“什么是模型?”
Conceptually, I understand a Model to be the data used by the views and controller. Beyond that, there seems to be a great deal of differing opinions on what makes up the model. What's a domain model, versus an app model, vs a view model, vs a service model, etc..
从概念上讲,我将模型理解为视图和控制器使用的数据。除此之外,对于模型的构成似乎有很多不同的意见。什么是域模型、应用程序模型、视图模型、服务模型等。
For example, in a recent question I asked about the repository pattern, I was told point blank that the repository is part of the model. However, I have read other opinions that the model should be seperated from the persistence model and the business logic layer. After all, isn't the Repository pattern supposed to decouple the concrete persistence method from the model? Other people say there is a difference between the Domain model and the MVC model.
例如,在我最近问到的关于存储库模式的问题中,我被直接告知存储库是模型的一部分。但是,我读过其他观点,认为模型应该与持久模型和业务逻辑层分开。毕竟,Repository 模式不是应该将具体的持久性方法与模型分离吗?其他人说域模型和 MVC 模型之间存在差异。
Let's take a simple example. The AccountController that is included with the MVC default project. I've read several opinions that the Account code included is of poor design, violates SRP, etc.. etc.. If one were to design a "proper" Membership model for an MVC application, what would that be?
我们举一个简单的例子。包含在 MVC 默认项目中的 AccountController。我读过一些意见,其中包含的帐户代码设计不佳,违反了 SRP 等等。
How would you seperate the ASP.NET services (Membership provider, role provider, etc..) from the model? Or would you at all?
您将如何从模型中分离 ASP.NET 服务(成员身份提供者、角色提供者等)?或者你会吗?
The way I see it, the model should be "pure", perhaps with validation logic.. but should be seperate from business rules (other than validation). For example, let's say you have a business rule that says someone must be emailed when a new account is created. That doesn't really belong in the model in my view. So where does it belong?
在我看来,模型应该是“纯粹的”,也许带有验证逻辑......但应该与业务规则(验证除外)分开。例如,假设您有一个业务规则,规定在创建新帐户时必须向某人发送电子邮件。在我看来,这并不真正属于模型。那么它属于哪里呢?
Anyone care to shed any light on this issue?
有人关心这个问题吗?
采纳答案by Josh
The way I have done it - and I'm not saying it is right or wrong, is to have my View and then a model that applies to my view. This model only has what is relevant to my view - including data annotations and validation rules. The controller only houses logic for building the model. I have a service layer which houses all business logic. My controllers call my service layer. Beyond that is my repository layer.
我这样做的方式 - 我不是说它是对还是错,是拥有我的视图,然后是一个适用于我的视图的模型。这个模型只有与我的观点相关的东西——包括数据注释和验证规则。控制器仅包含用于构建模型的逻辑。我有一个包含所有业务逻辑的服务层。我的控制器调用我的服务层。除此之外是我的存储库层。
My domain objects are housed separately (in their own project, actually). They have their own data annotations and validation rules. My repository validates the objects in my domain before saving them into the database. Because every object in my domain inherits from a base class which has validation built in, my repository is generic and validates everything (and requires it inherits from the base class).
我的域对象是单独存放的(实际上是在他们自己的项目中)。他们有自己的数据注释和验证规则。我的存储库在将它们保存到数据库之前验证我域中的对象。因为我的域中的每个对象都继承自一个内置验证的基类,所以我的存储库是通用的并验证所有内容(并要求它从基类继承)。
You might think that having two sets of models is duplication of code, and it is to an extent. But, there are perfectly reasonable instances where the domain object is not appropriate for the view.
您可能认为拥有两组模型是代码重复,并且在一定程度上是重复的。但是,有完全合理的实例域对象不适合视图。
Case in point is when working with credit cards - I have to require a cvv when processing a payment, but I cannot store the cvv (it is a $50,000 fine to do so). But, I also want you to be able to edit your credit card - change of address, name, or expiration date. But you aren't going to give me the number or the cvv when editing it, and I certainly am not going to put your credit card number in plain text on the page. My domain has these values required for saving a new credit card because you give them to me, but my edit model doesn't even include the card number or cvv.
一个恰当的例子是在使用信用卡时 - 我在处理付款时需要一个 cvv,但我无法存储 cvv(这样做会被罚款 50,000 美元)。但是,我还希望您能够编辑您的信用卡 - 更改地址、姓名或到期日期。但是在编辑时您不会给我号码或 cvv,而且我当然不会将您的信用卡号码以纯文本形式放在页面上。我的域具有保存新信用卡所需的这些值,因为您将它们提供给我,但我的编辑模型甚至不包括卡号或 cvv。
Another benefit to so many layers is that if architected correctly, you can use structuremap or another IoC container and swap out pieces without detrimentally affecting your application.
如此多的层的另一个好处是,如果架构正确,您可以使用结构图或其他 IoC 容器并交换部分,而不会对您的应用程序产生不利影响。
In my opinion, controller code should only be code targeted at the view. Show this, hide that, etc. The service layer should house the business logic for your app. I like having all of it in one place so it's easy to change or tweak a business rule. The repository layer should be relatively dumb - devoid of business logic and only query your data and return your domain objects. By separating the view models from the domain model, you have much more flexibility when it comes to custom validation rules. It also means you don't have to dump every piece of data into your view in hidden fields and push it back and forth between the client and server (or rebuild it on the backend). Your view model will then house only the information relevant to the view - and it can be customized to have bools for view logic or counts or enums so that the view itself isn't cluttered up with complicated logic statements like
在我看来,控制器代码应该只是针对视图的代码。显示这个,隐藏那个等等。服务层应该包含你的应用程序的业务逻辑。我喜欢将所有内容集中在一个地方,这样可以轻松更改或调整业务规则。存储库层应该相对简单——没有业务逻辑,只查询您的数据并返回您的域对象。通过将视图模型与域模型分离,您在自定义验证规则方面具有更大的灵活性。这也意味着您不必将每条数据都转储到隐藏字段中的视图中并在客户端和服务器之间来回推送(或在后端重建它)。
<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) &&
Model.SomeObject.SomeInt == 3 && ...) { %>
While everything seems spread out and over-layered, it has a purpose for being architected this way. Is it perfect? not really. But I do prefer it to some past designs of calling repositories from the controller and having business logic mixed in the controller, repository, and model.
虽然一切似乎都是分散和过度分层的,但它有一个目的是通过这种方式进行架构。它是完美的吗?并不真地。但与过去的一些从控制器调用存储库并将业务逻辑混合在控制器、存储库和模型中的设计相比,我更喜欢它。
回答by Bozho
I too often wondered how exactly the MVC elements fit in a traditional web application structure, where you have views (pages), controllers, services, and data objects (model). As you said, there are many versions of that.
我常常想知道 MVC 元素究竟是如何适应传统的 Web 应用程序结构的,在那里你有视图(页面)、控制器、服务和数据对象(模型)。正如你所说,有很多版本。
I believe the confusion exists because of the above stated, widely accepted architecture, which uses the "anemic domain model" (alleged)-anti pattern. I won't go into much details about the "anti-patternness" of anemic data model (you can look at an effort of mine to explain things here(Java-based, but relevant for any language)). But in short, it means that our model holds only data, and business logic is placed in services/managers.
我相信混淆的存在是由于上述广泛接受的架构,它使用了“贫血域模型”(据称)-反模式。我不会详细介绍贫血数据模型的“反模式”(您可以在此处查看我的解释(基于 Java,但与任何语言相关))。但简而言之,这意味着我们的模型只保存数据,业务逻辑放在服务/管理器中。
But let's assume we have domain driven architecture, and our domain objects are the way they are expected to be - having both state and business logic. And in this domain-driven perspective things come into place:
但是让我们假设我们有领域驱动架构,我们的领域对象是它们预期的样子——同时具有状态和业务逻辑。在这个领域驱动的观点中,事情就到位了:
- the view is the UI
- the controller gathers the inputs of the UI, invokes methods on the model, and sends back a response to the UI
- the model is our business components - holding the data, but also having business logic.
- 视图是 UI
- 控制器收集 UI 的输入,调用模型上的方法,并将响应发送回 UI
- 模型是我们的业务组件——保存数据,但也有业务逻辑。
I guess that answers your main questions. Things get complicated when we add some more layers, like the repository layer. It is often suggested that it should be invoked by the business logic placed in the model (and hence each domain object has a reference to a repository). In the article of mine that I linked I argue that this is not quite a best practice. And that in fact it is not a bad thing to have a service layer. By the way, domain-driven design does not exclude the service layer, but it is supposed to be 'thin', and only coordinating domain objects (so no business logic there).
我想这回答了你的主要问题。当我们添加更多层(例如存储库层)时,事情会变得复杂。通常建议它应该由放置在模型中的业务逻辑调用(因此每个域对象都有一个对存储库的引用)。在我链接的文章中,我认为这不是最佳实践。事实上,拥有一个服务层并不是一件坏事。顺便说一下,领域驱动设计不排除服务层,但它应该是“瘦”的,并且只协调领域对象(所以那里没有业务逻辑)。
For the anemic data model paradigm, which is widely adopted (for good or for bad), the model would be both the service layer and your data objects.
对于广泛采用(无论好坏)的贫血数据模型范式,该模型既是服务层又是您的数据对象。
回答by py2020
In my opinion,
在我看来,
Model -
模型 -
Should not contain business logic, it should be pluggable(WCF like scenario). It is used to bind to view so, it should have properties.
不应该包含业务逻辑,它应该是可插入的(WCF 类场景)。它用于绑定到视图,因此它应该具有属性。
Business Logic -
商业逻辑 -
It should be placed at "Domain Services Layer", it is separate layer altogether. Also, will add one more layer here "Application Services".
它应该放在“域服务层”,它是完全独立的层。此外,将在此处再添加一层“应用程序服务”。
App Services talks to Domain Services layer to apply business logic and then lastly return the Model.
应用服务与域服务层对话以应用业务逻辑,然后最后返回模型。
So, Controller will ask Application Service for Model and the flow will go like,
因此,Controller 会向 Application Service 请求 Model 并且流程会像这样,
Controller->Application Services(using domain services)->Model
回答by John Farrell
The MVC pattern and the Asp.net framework makes no distinction on what the Model should be.
MVC 模式和 Asp.net 框架对模型应该是什么没有区别。
MS's own examples include persistence classes in the model. Your question about membership being in the model. This depends. Are classes in your model owned by something? Is there a link between who logs in and what data is displayed? Is there filtering of data part of a permissions system that is editable? Is who last updated or edited an object part of your domain as in somebody else needs to see it or something for backend support?
MS 自己的示例包括模型中的持久性类。您关于模型中成员资格的问题。这取决于。您模型中的类是否归某物所有?谁登录和显示什么数据之间是否存在联系?是否对可编辑的权限系统的数据部分进行过滤?谁上次更新或编辑了您域的对象部分,因为其他人需要查看它或需要后端支持的内容吗?
The email example is also it depends. Are you familiar with domain eventing or eventing in particular? Do you have a separate service to send emails? Is the act of sending an email part of your domain or is it a application level concern outside of the scope of your system? Does the UI need to know if an email was sent successfully or not? Do emails that fail to send need retries? Does the content of the email sent need to be stored for support or customer service requirements?
电子邮件示例也取决于它。您是否熟悉领域事件或特别是事件?你们有单独的发送电子邮件的服务吗?发送电子邮件的行为是您域的一部分还是系统范围之外的应用程序级别问题?UI 是否需要知道电子邮件是否成功发送?发送失败的邮件需要重试吗?发送的电子邮件的内容是否需要存储以用于支持或客户服务要求?
These types of questions are overly broad and subjective but I'm answering so you and everybody who voted you up can understand this.
这些类型的问题过于宽泛和主观,但我的回答是为了让您和投票给您的每个人都能理解这一点。
Your requirements/timelines/resources all bleed into your system's architecture. Even the revenue modelcan have an effect. You also have to consider the pattern you are shooting for. DDD is much different than persistence-as-model applications and all the slop in between are also valid for certain apps. Are you shooting for testing the app? All of this has an effect.
您的需求/时间表/资源都融入了您的系统架构。甚至收入模式也会产生影响。您还必须考虑您要拍摄的模式。DDD 与作为模型的持久性应用程序有很大不同,两者之间的所有差异也适用于某些应用程序。您是否正在为测试应用程序而拍摄?所有这些都会产生影响。