【问题标题】:Dependency Injection vs. Managed Dependencies vs. Global Object依赖注入 vs. 托管依赖 vs. 全局对象
【发布时间】:2012-09-23 15:12:31
【问题描述】:

我在 Javascript + BackboneJS(一个 MVC 框架)+ RequireJS 框架中工作,但这个问题有点面向对象。

首先让我解释一下,在 Backbone 中,您的视图是传统视图和控制器的混合,而您的 HTML 模板是传统的 MVC 视图

为此苦苦思索了一段时间,但我不确定正确/务实的方法应该是什么。

我有一个 User 对象,其中包含许多代码所依赖的用户偏好(如单位系统、语言选择等)。

我的一些视图在不使用模板的情况下完成了大部分工作(通过使用 3rd 方库,如映射和图形库),因此它们依赖于 User 对象来处理单位转换,例如例子。我目前正在使用 RequireJS 来管理该依赖关系,而不会过多地破坏封装。

我的一些视图自己做的工作很少,只将模型数据传递给我的模板引擎/模板,这些模板引擎/模板完成工作并且确实依赖于用户对象,同样,用于单位转换之类的事情。将此依赖项传递给模板的唯一方法是将其注入模型,然后将模型传递给模板引擎。

我的问题是,如何最好地处理如此广泛需要的依赖项? - 创建一个可在任何地方访问的应用程序范围的引用/全局对象? (YUK) - 使用 RequireJS 托管依赖项,尽管通常只建议对类/对象定义而不是具体对象使用托管依赖项加载。 - 或者,只使用依赖注入,然后手动将该依赖传递给需要它的所有东西?

【问题讨论】:

    标签: javascript oop model-view-controller backbone.js requirejs


    【解决方案1】:

    从纯粹的技术角度来看,我认为可交换的全局变量(可能会改变的全局变量),尤其是在 javascript 中,是危险和错误的。特别是因为 javascript 充满了异步执行的部分代码。考虑以下代码:

    window.loggedinuser = Users.get("Paul");
    addSomeStuffToLoggedinUser();
    window.loggedinuser = Users.get("Sam");
    doSomeOtherStuffToLoggedinUser();
    

    现在,如果addSomeStuffToLoggedinUser() 在某处异步执行(例如,它执行一个 ajax 调用,然后在第一个完成时执行另一个 ajax 调用),它很可能正在向新的登录用户(“Sam”)添加内容,由到达第二个ajax调用的时间。显然不是你想要的。

    话虽如此,我更不支持拥有一些用户对象,我们一直在从一个函数到另一个函数,无限地传递。

    就我个人而言,不得不在这两种邪恶之间做出选择,我会为“很少改变”的事物选择一个全球范围——除非我正在建造核电站之类的东西。所以,我倾向于让登录用户在我的应用程序中全局可用,冒着风险,如果出于某种原因,某些呼叫运行得很晚,并且我遇到一个用户注销而另一个用户直接登录的情况,某事可能会发生奇怪的事情。 (再说一次,如果流星坠入托管我的应用程序的数据中心,也可能会发生一些奇怪的事情......我也没有防止这种情况发生)。实际上,一个可能的解决方案是在有人注销后立即重新加载整个应用程序。

    所以,我想这完全取决于您的应用。让它变得更好的一件事(让你觉得你仍然得到一些 OO 业力点)是将你的数据隐藏在一些命名空间的单例中:

    var myuser = MyApp.domain.LoggedinDomain.getLoggedinUser();
    doSomethingCoolWith(myuser);
    

    代替

    doSomethingCoolWith(window.loggedinuser);
    

    虽然最后都差不多……

    【讨论】:

    • 值得一提的是,您可以找到一些很好的模式来缓解这个问题,方法是使用 deferreds 坐在可能被异步修改的可交换全局变量前面
    【解决方案2】:

    考虑到 TDD 方法,您将如何测试它? DI 最适合新项目,但 JS 为您提供了灵活的选项来在测试时处理具体的全局依赖关系,即:上下文构造。回顾过去,Yahoo 制定了一种模块模式,其中所有模块都是松散耦合的,并且不相互依赖,但是拥有全局上下文是可以的。该全局上下文可以使您的应用程序构建对于不断重用的事物更加实用。只是您需要明智/谨慎地应用它,并且需要有非常有力的案例来证明这些东西是动态的。

    【讨论】:

      【解决方案3】:

      我认为您已经回答了自己的问题,您只是希望其他人为您说:) 使用 DI,但您并没有真正“手动”将该依赖项传递给所有内容,因为您需要引用它才能使用它无论如何。

      【讨论】:

        猜你喜欢
        • 2019-05-06
        • 1970-01-01
        • 1970-01-01
        • 2016-11-09
        • 1970-01-01
        • 2015-02-12
        • 2023-02-20
        • 2015-07-15
        • 1970-01-01
        相关资源
        最近更新 更多