NET MVC-业务逻辑应该存在于控制器中吗?

德里克 · 惠特克(DerikWhitaker)几天前发表了一篇 文章的文章,这篇文章触及了我一直好奇的一个问题: 业务逻辑应该存在于控制器中吗?

到目前为止,我看到的所有 ASP.NET MVC 演示都将存储库访问和业务逻辑放在控制器中。有些人甚至还在里面加上了验证。这会导致相当大的、臃肿的控制器。这真的是使用 MVC 框架的方法吗?看起来最终会有很多重复的代码和逻辑分布在不同的控制器上。

51790 次浏览

Business logic should really be in the model. You should be aiming for fat models, skinny controllers.

For example, instead of having:

public interface IOrderService{
int CalculateTotal(Order order);
}

I would rather have:

public class Order{
int CalculateTotal(ITaxService service){...}
}

This assumes that tax is calculate by an external service, and requires your model to know about interfaces to your external services.

This would make your controller look something like:

public class OrdersController{
public OrdersController(ITaxService taxService, IOrdersRepository ordersRepository){...}


public void Show(int id){
ViewData["OrderTotal"] = ordersRepository.LoadOrder(id).CalculateTotal(taxService);
}
}

Or something like that.

This is a fascinating question.

I think that its interesting that a large number of sample MVC applications actually fail to follow the MVC paradigm in the sense of truly placing the "business logic" entirely in the model. Martin Fowler has pointed out that MVC is not a pattern in the sense of the Gang Of Four. Rather, it is paradigm that the programmer must add patterns to if they are creating something beyond a toy app.

So, the short answer is that "business logic" should indeed not live in the controller, since the controller has the added function of dealing with the view and user interactions and we want to create objects with only one purpose.

A longer answer is that you need to put some thought into the design of your model layer before just moving logic from controller to model. Perhaps you can handle all of app logic using REST, in which case the model's design should be fairly clear. If not, you should know what approach you are going to use to keep your model from becoming bloated.

You can check this awesome tutorial by Stephen Walther that shows Validating with a Service Layer.

Learn how to move your validation logic out of your controller actions and into a separate service layer. In this tutorial, Stephen Walther explains how you can maintain a sharp separation of concerns by isolating your service layer from your controller layer.

I like the diagram presented by Microsoft Patterns & Practices. And I believe in the adage 'A picture is worth a thousand words'.

Diagram shows architecture of MVC and business sevices layers

Business Logic should not be contained in controllers. Controllers should be as skinny as possible, ideally follow the patter:

  1. Find domain entity
  2. Act on domain entity
  3. Prepare data for view / return results

Additionally controllers can contain some application logic.

So where do I put my business logic? In Model.

What is Model? Now that's a good question. Please see Microsoft Patterns and Practices article (kudos to AlejandroR for excellent find). In here there are three categories of models:

  • View Model: This is simply a data bag, with minimal, if any, logic to pass data from and to views, contains basic field validation.
  • Domain Model: Fat model with business logic, operates on a single or multiple data entities (i.e. entity A in a given state than action on entity B)
  • Data Model: Storage-aware model, logic contained within a single entity relates only to that entity (i.e. if field a then field b)

Of course, MVC is a paradigm that comes in different varieties. What I describe here is MVC occupying top layer only, vide this article on Wikipedia

Today, MVC and similar model-view-presenter (MVP) are Separation of Concerns design patterns that apply exclusively to the presentation layer of a larger system. In simple scenarios MVC may represent the primary design of a system, reaching directly into the database; however, in most scenarios the Controller and Model in MVC have a loose dependency on either a Service or Data layer/tier. This is all about Client-Server architecture

If u use Dependency Injectors your business logic will go to them and hence you will get neat and clean controllers.