我正在使用MVC模式构建Web应用程序。遵循这种架构,我们可以看到模型中使用了与数据库交互的所有方法。
但是,如果我必须打电话给其他人在网络上公开的服务会怎样?例如,我想访问Facebook API以获取页面的所有关注者,那么,将这些方法放在哪里?
显然,视图不是一个好主意,因为该模块专用于表示,不应使用控制器来检索数据,而模型通常仅用于与数据库的交互。
那么,您能给我一些提示吗?而且,请问我是否对MVC架构犯了一些错误?
我正在使用MVC模式构建Web应用程序。遵循这种架构,我们可以看到模型中使用了与数据库交互的所有方法。
但是,如果我必须打电话给其他人在网络上公开的服务会怎样?例如,我想访问Facebook API以获取页面的所有关注者,那么,将这些方法放在哪里?
显然,视图不是一个好主意,因为该模块专用于表示,不应使用控制器来检索数据,而模型通常仅用于与数据库的交互。
那么,您能给我一些提示吗?而且,请问我是否对MVC架构犯了一些错误?
Answers:
该模型不限于与数据库交互,该模型负责获取和处理数据。
因此,对于您的视图和控制器而言,如果数据来自数据库或Web服务,甚至是完全随机的,则应该没有区别,因此您应该在模型中进行处理。
MVC是一种表示模式,仅分隔不同的表示层。
这并不意味着该模型必须是统一的意大利面条代码。您的模型本身也可以分层,但是控制器不应该知道数据来自何处。
模型中的公共方法可以采用以下结构(伪代码),可以由控制器调用:
public MyDataClass getData(int id) {
WebServiceData wsData = WebService->getData(id);
DatabaseData dbData = ORM->getData(id);
return new MyDataClass(wsData, dbData);
}
WebService
并且ORM
可能需要接口的实例,可以通过依赖注入将其替换为模拟,但是您的控制器和视图不必出于测试目的而更改。
关于M,V和C有一个常见的(故意的)误解。不是他们扮演的角色,而是他们是什么。
在MVC的原始桌面GUI定义中,它们是modules。通常,一个应用程序具有多个视图,有时在三胞胎中工作,有时具有多种视图和模型,一些控制器可以将它们混合和匹配。
在OTOH的Web框架中,它们往往被看作是层,它们只是其中的一层,并且主要涉及覆盖一些底层抽象层:“模型层对数据库进行抽象”,“视图层实现表示”,“控制器”层处理用户输入”。
因此,我想说您已经有一个专门用于与数据库交互的模型,现在只需创建另一个模型来处理您的源API。如果使它们尽可能相似,则大多数控制器和视图代码都可以与任一模型无缝地协同工作。
对MVC进行任何讨论的部分困难在于,不同的群体选择了它来表示不同的意思。例如,在Rails应用程序中使用的MVC的实现对于编写Swing应用程序的人来说几乎是无法识别的。在某种程度上,MVC仍然是一个定义明确的事物,它更多是一组指导原则(将核心应用程序与其视觉表示分开,提供了灵活的机制以使两者融合在一起),可以通过各种方式实现方法。
确实,有一种趋势是给不同的MVC衍生的设计赋予不同的名称(有关此问题的讨论,请参见Martin Fowler的本文),甚至放弃精确的命名-例如,AngularJS将自己描述为Model-View-Whatever框架。
因此,如果不知道您正在使用哪个版本的“ MVC”,就很难回答。但是,API请求通常是核心应用程序的一部分(如果您决定使用其他视觉表示,则该部分不应更改),在许多实现中,该请求将完全包含在模型中。
在这里,模型描述如下:
模型存储检索到控制器并显示在视图中的数据。每当数据发生更改时,控制器都会对其进行更新。
我想说的是,控制器要么包含调用服务的逻辑,要么调用单独的Service
对象。如果服务是单独的,则可以更轻松地创建测试,例如,如果无法通过网络连接到服务,则某些服务TestService
可以提供Service
本地响应。
您的模型不应包含任何实际代码,而应被视为更多消息或结构,用于管理由控制器操纵并由视图显示的内容。
您的控制器应负责联系任何API,数据库,服务等,以请求更改并管理对模型的任何必要更新。
MVC模式的全部优势在于,它使逻辑(控制器)与视图和状态(模型)脱钩。这样一来,您就可以确保只有控制器中的代码才能产生副作用,因为视图和模型完全不允许更改。
它还可以更好地重用代码,因为可以在各种控制器和视图之间共享模型。