胖模型/瘦控制器与服务层

我一直在使用.Net开发企业应用程序多年。我的应用程序通常有一个包含映射到SQL数据库表的实体的域模型。 我使用了Repository模式,dependency injection和服务层。

最近我们开始了MVC 3项目的工作,我们有一个辩论放哪个逻辑。 我来到了瘦控制器/ FAT模型架构,想知道服务层如何适应

选项1 – 与服务的模型谈判

控制器很薄,在模型上调用方法。 这些模型“知道”如何从数据库中加载自己并与存储库或服务通信。 例如,customerModel有一个Load(id)方法,并加载客户和一些像GetContracts()这样的子对象。

选项2 – 控制器与服务对话

控制器要求服务检索模型对象。 加载/存储等逻辑在服务层。 该模型是一个纯粹的实体模型,只有数据。

为什么选项1是更好的select,特别是当我们谈论企业应用程序时,我的经验告诉我要分开关注点,保持模型和控制器尽可能的薄,并且有专门的服务来完成业务逻辑(包括数据库交互)

感谢所有的build议和引用良好的资源。

所有这些都取决于您的应用程序的意图和要求。

这就是说,我的build议是“中等规模”(不是当地餐馆,而不是Twitter / Facebook)的networking应用程序。

  1. 精益领域build模

    干燥的POCO风格的对象,最好不知道你的Web应用程序的MVC体系结构,以尽可能松散地从你的特定实现中耦合。甚至可以重新使用外部应用程序,例如通过WCF Web服务的REST API )。

    MVC中的“Model”最准确地表示Controller知道 的模型 ,因此也是View的模型

    在较小的(通常为Tutorial)应用程序中,“应用程序/域模型层”的实体模型通常与控制器发送给View的实例化对象相同。

    在大型应用程序中,开发人员经常使用MVVM体系结构的原则,并开始使用单独的View Model对象。 控制器经常调用与下面看不见的实体一起工作的中间层服务。 在这种情况下,MVC中的M最准确地表示View Model。

  2. 强大的服务层

    这并不意味着肥胖的逻辑,而是写得很好的单一目的的服务。 虽然在模型之外的服务中编写业务逻辑比纯粹的“OOP”更“过程化”,但是对于松散的耦合,testing和灵活的部署(例如n层部署),它有很大的帮助。

    在我个人的实践中,我将数据服务的代码编写在数据层上,我认为POCO对象的行为build模(持久性机制,低级validation等)和更高级别的服务(业务/工作streamfunction) MVC机制。

  3. 精益控制器

    我确定我的控制者只是教练 ,因为它不是 (服务)或玩家 (实体模型或视图模型),而只是决定谁扮演什么angular色和扮演什么angular色。 我的控制器做了两件事:

    1. 调用与实体/域模型交互的服务

    2. 为适当的视图准备一个视图模型。

    即使通过authentication/授权的控制器操作也是通过注入服务/属性完成的。


编辑1:

请记住,这并不意味着您的实体/域模型是或者必须是贫血的。 ORM,存储库和工厂,validation或国家机制是受欢迎的。 它只适用于中等规模的应用程序,MVC中的Model表示控制器的模型,将其交给View

希望这一点能够使那些相信贫血数据模型成为反模式的福勒使徒们冷静下来。 同时,它确实反映了比OOP稍微更加程序化的angular度,在模拟类中包含行为更纯粹。

没有“终极事实”,但是使用这种模式,你会发现构build,testing和部署你的应用程序很容易,同时保持了很多可重用性和可伸缩性。


编辑2:

也就是说,即使是适度规模的应用程序,在架构devise方面(即一个书呆子编写的?)系统太常见了。 例如,用存储库模式包装一个ORM,然后编写服务来使用存储库…所有这些对于分离关注等都是有利的,但是如果你的项目不需要(而且不太可能很快需要)这样的事情,不build立它。 一起跳过版本库,针对ORM编写精简的业务服务(例如查询类),甚至让控制器直接与之交谈,没有任何错误。 这一切都取决于规模。


编辑3:

我想指出的是,这个解释和build议是针对像ASP.Net这样的服务器端MVC架构的上下文,而不是像Knockout或Backbone这样的clent-side框架。

在继续之前,您需要了解更多关于MVC的内容,并讨论将所有内容放在哪里。 那么,如果你想遵循这个模式。 否则,你现在可以停止阅读。

该模式非常松散地定义。 没有什么说控制器,视图或模型应该是什么样的,或者应该如何构造。 该模式只是说,你应该分开的部分,以及他们应该如何互相交stream。 所以让我们来看看它们是什么(我的解释)。

MVC

模型模型可以是任何东西。 它可以是一个web服务,你的仓库,你的服务类或者只是你的域模型。 模型是用来获取所需信息的一切。 将“模型”看作一个层而不是一个单一的对象。

控制器控制器是一个胶水。 它从模型中获取信息并使其适应视图,反之亦然。

查看视图应该只显示用户看到的内容。

请注意,您不应该将模型与视图模型混淆。 微软应该真的命名“模型”文件夹“ViewModels”,因为这就是他们是。 我不会直接在视图中使用“模型”中的信息。 如果不这样做,则意味着如果视图改变,则必须更改模型,反之亦然。

答案

该模型不是一个视图模型,而是一个图层。 模型中的所有内容都用于获取视图所需的信息。 控制器将这些信息放入单个视图模型中。

一个控制器动作可以使用对“模型”的一个或多个调用来组装视图所需的信息。

这意味着如果您想获得易于维护和扩展的应用程序,则您的第二个选项是最正确的。

请注意,可能不需要服务层。 您可以直接从控制器调用OR / M。 但是,如果您发现自己复制代码或变得更胖,只需将逻辑移至服务层即可。 因为您使用的是正确的视图模型,所以只有控制器才会受到该更改的影响。

选项1:你可以认为这个模型==服务。 模型也是业务层。

选项2是一种贫血域模式反模式。 http://en.wikipedia.org/wiki/Anemic_domain_model

选项2就是Fat Stupid丑陋控制器体系结构( 参考这个expression式的作者 )。 这个解决scheme通常违背了MVC的精神,因为它打破了关注的分离。