Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/477.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 客户端MV*-模型是否应具有保存方法?_Javascript_Angularjs_Model View Controller_Knockout.js_Ember.js - Fatal编程技术网

Javascript 客户端MV*-模型是否应具有保存方法?

Javascript 客户端MV*-模型是否应具有保存方法?,javascript,angularjs,model-view-controller,knockout.js,ember.js,Javascript,Angularjs,Model View Controller,Knockout.js,Ember.js,这是一个通用的模式问题,但我已经反复讨论了一段时间了 模型是否应该在MV*中有保存方法? 我经常在Knockout、Ember和Angular之间来回跳跃,但我一直存在的一个问题是,模型是否应该在其类或原型上有一个save方法,该方法知道如何保存更改以减少应用程序对服务的依赖性(也就是说,模型有一个保存服务,所有其他视图模型/控制器通过了解模型继承该服务),或者每个视图模型/控制器都依赖一个服务,该服务有一个特定的方法保存对对象的更改 JavaScript伪代码示例 vs 两者都实现了保存人员的

这是一个通用的模式问题,但我已经反复讨论了一段时间了

模型是否应该在MV*中有保存方法?

我经常在Knockout、Ember和Angular之间来回跳跃,但我一直存在的一个问题是,模型是否应该在其类或原型上有一个save方法,该方法知道如何保存更改以减少应用程序对服务的依赖性(也就是说,模型有一个保存服务,所有其他视图模型/控制器通过了解模型继承该服务),或者每个视图模型/控制器都依赖一个服务,该服务有一个特定的方法保存对对象的更改

JavaScript伪代码示例

vs

两者都实现了保存人员的相同目的,但在示例1中,视图模型/控制器不知道服务或其实现方式,只知道如果要更改人员,则保存它。在示例2中,显然我们不仅要知道保存方法,而且要知道如何实现保存

回答之前请先读一下-
我意识到这是一个基于观点的问题,但如果你能用事实来支持你的观点,它将是事实性的,因此请有参考资料来支持任何主张,这样就不会以“主要基于观点”来结束这一问题。

我个人观点中的简短答案将是你的第二个版本。我通常认为客户端上的viewmodelt基本上是一包数据或属性。服务用于将这些viewmodels持久化/从服务器获取,控制器负责使用服务方法并呈现视图。在Angular.js world中,指令将处理任何特定于DOM的行为,但我认为最终由于UI交互(保存、验证等)将由控制器处理(可能通过调用服务方法)

我在开始使用Angular.js时提出了这一观点,并对他们的开发人员进行了调查。其不足之处在于:

使用控制器可以:

  • 设置viewmodel对象的初始状态
  • 向viewmodel对象添加行为
不要使用控制器来:

  • 操纵DOM-控制器应仅包含业务逻辑
  • 格式输入
  • 滤波器输出
  • 管理其他组件的生命周期(例如,创建 服务实例)
使用服务在应用程序中组织和共享代码和状态。

这取决于模式(而不是基于观点的imo)

  • 第一个示例:具有
    .save
    方法的域对象称为(另请参见)

  • 第二个示例:数据映射层和域层之间的映射器称为A(另请参见)

活动记录模式 引用福勒的话:

在数据库表或视图中封装行、封装数据库访问并在该数据上添加域逻辑的对象

ActiveRecord模式通常擅长于原型设计,有时在对象和DB行之间存在1-1映射的非常小的应用程序中是一个好主意。通常,您希望将持久化对象的逻辑与实际域对象的逻辑分开,因为它们本质上是不同的职责

这是逻辑处理数据持久性的最简单方法之一

例如,这就是主干模型和集合使用其
sync()
方法所做的。这会导致它们持久化到服务器。这通常是您看到大型主干应用程序不使用
sync()的原因
完全支持实现自己的适配器。毕竟,在主干世界中,它强制您的REST API和域对象之间进行1-1映射,有效地使您的域对象和数据传输对象保持一致,这可能会随着应用程序的增长而变得难以维护

存储库模式 再次引用福勒的话:

使用用于访问域对象的类似集合的接口在域和数据映射层之间进行调解

对于大型应用程序来说,存储库通常是一种更好的设计模式,因为它从域对象中删除了持久性逻辑,所以它做得更好

在实现方面,存储库通常如下所示:

但是,对于用户来说,存储库可能类似于:


然而,作为任何抽象,责任的另一个对象有一些开销——随着应用程序的增长,它开始得到回报。如果您使用Angular创建
$resource
,并将其包装在一个服务中,该服务将这些对象从db查询映射到您的域对象(您的数据映射器)然后像查询集合一样查询该服务—这是您的存储库。

我相信angular的设计会让您进入第一个设计(假设
person.save()
的意思是“向REST资源发送HTTP帖子”).对不起,这是基于意见的,你不能通过在问题中承认这一点来阻止问题的结束。这个问题没有很好的明确答案,你只是在试图煽动讨论。即使它不是因为基于意见而关闭的,它也应该关闭,因为它太宽泛了。我们不可能为ev回答这个问题ery用例。@meagar OP在这里讨论了两种非常具体的模式,每种模式在哪里有用,在我看来,这一直是一个研究主题,对每种模式的优缺点都有明确的答案。唯一基于观点的部分是实际使用哪种模式。FWIW,使用存储库进行数据访问。我支持abs牵引,但我现在更喜欢使用命令模式。类似于
var savePersonCommand=new savePersonCommand();savePersonCommand.person=person;savePersonCommand.execute();
。或者地狱,甚至只是作为服务的函数
var person = new Model.Person();
person.name = 'Bill';
person.save();
var personService = require('services/person.service');
var person = new Model.Person();
person.name = 'Bill';
personService.save(person);