【问题标题】:Should be an input data object cloned before it's processed by application logic?是否应该在应用程序逻辑处理之前克隆输入数据对象?
【发布时间】:2017-04-24 03:51:18
【问题描述】:

我从事一个开源项目 - 又名对象文档映射器。 ODMjavascript 中,我面临着一个我难以解决的设计决策(而不是simple,但不是easy)。

ODM 中,您可以定义一个Model 对象,该对象描述您在数据库中的数据文档。创建新的 Model 实例对象时,您可以通过参数传入它的数据值。
伪代码:

var data = {
    username: 'james'
    email: 'james@email.com',
    country: {
        code: 'US',
        city: ''
    } 
};
// In case the data object would not be cloned, it would be mutated by the ODM
var user = new UserModel(data);

现在,我面临的决定是是否在模型中自动克隆 data 对象,然后再由应用程序 (ODM) 处理。我倾向于选择不克隆输入数据。我觉得在javascript 社区中,克隆数据通常比必要的要多,因为它可以为最终用户提供easy(而不是simple)的东西。从我的研究中,我发现一些类似且受欢迎的项目决定克隆数据,但考虑到模型可以具有大型和复杂的数据模式并且没有任何区别,我不确定这是正确的选择如果有数十个 Model 实例对象,我认为这可能是一个问题,例如:数百个 Model 对象。

我很想听听您对该主题的推理,您的选择是什么?
如果您已经看到另一个答案,请不要犹豫,写下您的想法!
谢谢!

【问题讨论】:

    标签: javascript node.js cloning odm


    【解决方案1】:

    如果你一直使用输入对象来保存实体的数据,如果你不克隆对象,你将面临如下问题:

    var UserModel = function(data) {
      this.data = data;
    }
    UserModel.prototype.getUsername = function() {
      return this.data.username;
    }
    
    var data = {username: 'james'};
    var james = new UserModel(data);
    
    data.username = 'john';
    var john = new UserModel(data);
    
    console.log(james.getUsername()); // "john"
    console.log(john.getUsername());  // "john"

    这可能会导致一些可能并不总是显而易见的令人讨厌的错误。


    我认为最简洁的方法是从对象中提取相关信息并将其直接保留为成员属性,而不是克隆:

    var UserModel = function(data) {
      this.username = data.username;
      this.email = data.email;
    }
    UserModel.prototype.getUsername = function() {
      return this.username;
    }
    UserModel.prototype.getEmail = function() {
      return this.email;
    }
    

    更好的是,将属性显式声明为构造函数的参数:

    var UserModel = function(username, email) {
      this.username = username;
      this.email = email;
    }
    

    【讨论】:

    • 感谢您的输入@Timo。在您提出的设计方法中,考虑到数据属性不仅是数据原语,而且是嵌套对象/数组,您并没有避免引起您所描述的相同问题。通过提供太多简单的代码示例,我认为这是我的错误。关于您描述的问题-我想了解的是,为什么要考虑以这种方式使用对象而不先克隆它,然后再将其传递给另一个模型。我们不应该将对象/数组默认视为对内存的引用,而不是假设它的处理方式与原语相同?
    • 不仅处理基元,同样的原则也适用并且复制可能是必要的,除非您将子对象构造成单独的实体。在一个完美的世界里,我的第一个例子永远不会发生。但是,通常最好将枪从您的(API 的)用户手中拿走,而不是让他朝自己的脚开枪并告诉他事后他应该知道得更好。 API 的用户不一定知道任何有关实现细节的信息,他也不必知道。您做出的假设越多,使用您正在设计的 API 就越难。
    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 2018-07-20
    • 1970-01-01
    • 2020-12-08
    • 2011-03-08
    • 1970-01-01
    相关资源
    最近更新 更多