在MVC中使用服务层


13

如果控制器太胖,并且模型实例化开始加起来,则可以使用服务层。

  • 如果仅将逻辑包装在服务类中,则将获得一堆带有一个/两个方法的服务。感觉像是代码气味。有什么最佳实践吗?

  • 服务可以实例化模型吗?

  • 如果服务实例化模型,则不能对服务进行单元测试。它们只能接受集成测试吗?

Answers:


25

在“ SOLID”中,“ I”代表接口隔离。该原理的整体思想是将大型接口拆分为更小,更模块化的接口。在MVC中,服务通常具有控制器将依赖的接口。您不希望您的控制器了解该服务的具体实现。因此,拥有一两种方法的一堆服务是一件好事。

服务通常在大型应用程序中返回DTO,而在小型应用程序中直接返回域模型。DTO通常意味着更多的工作,但更好的关注点分离。典型的流程是:

  • 控制器呼叫服务
  • 服务返回一个对象(可以是DTO,域模型或其他)
  • 控制器将DTO /域模型映射到视图模型

映射可以手动完成,但是大多数开发人员更喜欢使用Automapper之类的自动映射框架,因为我们不喜欢编写管道代码,而且我们可能会很懒惰:-)

http://en.wikipedia.org/wiki/Interface_segregation_principle

https://github.com/AutoMapper/AutoMapper

关于使用DTO和域模型的stackoverflow的众多讨论之一:https : //stackoverflow.com/questions/2680071/dto-or-domain-model-object-in-the-view-layer


1
我会使用自动映射器在这里要小心uglybugger.org/software/post/...
丹尼尔·利特尔

AutoMapper带有内置的单元测试功能,使您可以用一行来验证所有映射例程。这篇文章的作者没有提及。
CodeART 2014年

但是他确实知道并且已经使用过。评论涉及到这一点。
丹尼尔·利特尔

2
许多仅使用一种或两种方法的类通常意味着它们没有内聚性。服务层(如果存在)应该很薄,而大多数逻辑都在模型中。将视图绑定到一个愚蠢的对象似乎毫无意义,无非就是一个属性包。MVC中的模型应该是富域模型,而不是贫乏的martinfowler.com/bliki/AnemicDomainModel.html
Andy

3

在MVC中,模型不仅仅是DTO或一组Managers / Services,它还代表了您的应用程序正在建模的概念。您可以将其视为整个域或业务逻辑,包括状态和行为。现在,我们知道控制器的用途变得更加清楚了。要做的只是将命令转换为模型,然后将结果转换回视图。通常以ViewModels的形式完成,虽然ViewModels不同,但通常与MVC中的Model混淆。

如果您没有定义明确的模型,那么您可能已经到了现在大多数逻辑都驻留在控制器本身中的地步。此时,为了开始减小控制器的大小,您可以开始将此逻辑拉回到管理器或服务对象中。这些服务通常会返回并在类似DTO / Entity的对象上运行。然后,控制器将成为这些服务和视图模型之间的映射层。有关映射的一些好技巧,请查看本文。朋友们不要让朋友使用AutoMapper

至于您的问题,第一个在很大程度上取决于您的应用程序。您需要按照某种方式进行重构,一旦从控制器中删除了逻辑,这种重构就会更加明显。至于测试,在服务内部实例化模型没有问题,但是,如果您发现测试很困难,则可能只是一个信号,您需要将服务分解成更小的部分,每个部分都由一个职责负责。


3

控制器应仅包含对模型的调用(发生业务逻辑的地方),并基于这些调用为视图分配数据(信息或错误消息的对象),因此即使对于非常复杂的页面,控制器也将非常小。变得很大,您应该认为也许应该将该页面扩展到更多页面。

模型仍然可以很大...我发现的解决方案是在控制器内部有一个变量,该变量指示要加载的模型以及针对特定任务的特定模型。

尝试像这样遵守模型-视图-控制器模型:

  • 视图:显示数据
  • 控制器:收集用户输入,向模型询问所请求的数据,然后将其发送回视图
  • 模型:与数据库交互并执行逻辑操作以准备信息

-1

我发现服务对于执行可能需要多个控制器执行的逻辑确实非常有用,或者仅仅是不够具体而不能成为控制器的一部分,除了它使我的控制器变得太大而难以阅读之外,这是事实。 。

当他说“模型(发生业务逻辑的地方)”时,我个人不同意“ aaa”,因为那就是您拥有控制器的全部原因,我认为模型需要是简单的数据抽象器,以便控制器可以执行所需的任务;再次,服务不应参与数据抽象任务...

只是说哟...


1
如果您的模型只是dto,那么您就陷入了贫血领域模型antipattern martinfowler.com/bliki/AnemicDomainModel.html
Andy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.