我使用.Net开发了多年的企业应用程序 我的应用程序通常具有包含映射到SQL DB表的实体的域模型。 我使用Repository模式,依赖注入和服务层。
最近我们开始研究MVC 3项目,我们讨论了在哪里放置哪种逻辑。 我来自瘦控制器/ FAT模型架构,并想知道服务层如何适合
控制器很薄,调用模型上的方法。模型“知道”如何从数据库加载自己并与存储库或服务进行通信。 例如。 customerModel有一个Load(id)方法,并加载客户和一些子对象,如GetContracts()。
Controller要求服务检索模型对象。加载/存储等逻辑在服务层中。该模型是纯实体模型,仅包含数据。
为什么选项1会成为更好的选择,特别是当我们谈论企业应用时,我的经验告诉我要分散关注点,尽可能保持模型和控制器的精简,并使用专业服务来做业务逻辑(imcl。数据库交互)< / p>
感谢所有关于良好资源的建议和参考。
答案 0 :(得分:89)
所有这些都取决于您的申请的意图和要求。
那就是说,这是我对“中等规模”(不是本地餐馆,而不是Twitter / Facebook)网络应用程序的建议。
精益领域建模
干POCO样式对象,最好无视Web应用程序的MVC体系结构,尽可能保持与特定实现的松散耦合。甚至可以将类库重新打包用于外部应用程序,例如REST API通过WCF Web服务)。
MVC中的“模型”最准确地意味着控制器知道的模型,因此用于视图的模型。在较小的(通常是教程)应用程序中,“应用程序/域模型层”的实体模型通常与控制器发送到View的实例化对象相同。
在较大的应用程序中,开发人员经常使用MVVM体系结构的原则,并开始使用单独的View Model对象。控制器通常调用与下面看不见的实体一起使用的中间层服务。在这种情况下,MVC中的M最准确地表示视图模型。
强大的服务层
这并不意味着肥胖逻辑,而是写得很好的单一目的服务。虽然在模型之外的服务中编写业务逻辑比纯粹的“OOP”更具“程序性”,但它对松散耦合,测试和灵活部署(例如n层部署)有很大帮助。 p>
在我的个人实践中,我在数据层编写服务,我认为我对POCO对象的行为建模(持久性机制,低级别验证等)和更高级别的服务(业务/工作流功能)接近MVC机制。
精益控制器
我确保我的控制器只是 the coach ,因为它既不是 play (服务),也不是播放器(实体模型)或查看模型),但只是决定谁扮演什么位置和扮演什么角色。我的控制器做了两件事:
调用与实体/域模型交互的服务
为相应的视图准备视图模型。
即使经过身份验证/授权的控制器操作也是通过注入的服务/属性完成的。
编辑1:
请记住,这并不意味着您的实体/域模型是或必须是贫血。 ORM,存储库和工厂,验证或状态机制是受欢迎的。它仅适用于中等规模的应用程序,MVC中的 Model 表示用于控制器的模型,以交付给您的View 。
希望这一点能够让那些认为贫血数据模型成为反模式的福勒使徒们平静下来。与此同时,它 反映的程序角度略高于OOP,在模型化的类中包含行为更为纯粹。
没有“终极事实”,但使用这种模式,您会发现构建,测试和部署应用程序变得容易 - 同时保持了大量的可重用性和可扩展性。
编辑2:
也就是说,即使对于规模适中的应用程序,过度架构(一个单词书呆子组成了?),系统也太常见了。例如,使用存储库模式包装ORM,然后编写服务以使用存储库......所有这些都有利于分离关注点等,但如果您的项目不需要(并且不太可能很快要求)这样的事情,不要建立它。一起跳过存储库,针对ORM编写瘦业务服务(例如查询类),甚至让控制器直接与它对话,也没有错。这一切都取决于规模。
编辑3:
我想要注意的是,这个解释和建议是针对像ASP.Net这样的服务器端MVC架构的上下文,而不是针对像Knockout或Backbone这样的灵活端框架。
答案 1 :(得分:16)
在我们开始讨论将所有内容放在哪里之前,你需要了解更多关于MVC的知识。好吧,如果你想遵循这种模式。否则你现在就可以停止阅读了。
模式定义非常松散。没有任何内容可以说明控制器,视图或模型应该是什么样子,或者它们应该如何构建。该模式只是说明您应该将各个部分分开,以及它们应该如何相互作用。那么让我们再看看它们是什么(我的解释)。
<强>模型强> 模型可以是任何东西。它可以是Web服务,您的存储库,服务类或只是您的域模型。模型是用于获取所需信息的所有内容。将“模型”视为一个层而不仅仅是一个对象。
<强>控制器强> 控制器是胶水。它从模型中获取信息并使其适应视图,反之亦然。
查看强> 视图应该只呈现用户看到的内容。
请注意,不要将模型与视图模型混淆。微软真的应该将“Model”文件夹命名为“ViewModels”,因为它们就是这样。我不会直接在视图中使用“模型”中的信息。如果不这样做,则意味着如果更改了视图,则必须更改模型,反之亦然。
模型不是视图模型,而是图层。模型中的所有内容都用于获取视图所需的信息。控制器获取该信息并将其放入单个视图模型中。
单个控制器操作可能会对“模型”使用一次或多次调用,以便能够汇总视图所需的信息。
这意味着如果您想获得易于维护和扩展的应用程序,那么您的第二个选项是最正确的。
请注意,可能不需要服务层。您可以直接从控制器调用OR / M.但是,如果您发现自己重复代码或获取胖控制器,只需将逻辑移动到服务层即可。除了控制器之外什么都不会受到这种改变的影响,因为你正在使用正确的视图模型。
答案 2 :(得分:0)
选项1: 你可以认为模型==服务。 模型也是业务层。
选项2是Anemic Domain Model反模式。 http://en.wikipedia.org/wiki/Anemic_domain_model
答案 3 :(得分:0)
选项2被描述为Fat Stupid丑陋控制器架构(Reference to author of this expression)。这种解决方案通常违背MVC精神,因为它打破了关注点的分离。