为什么Angular JS中的依赖注入比手动管理依赖更好?

时间:2014-04-26 13:54:03

标签: javascript angularjs dependency-injection

特别谈到DI功能我不是Angular的粉丝,而且我对Angular使你的代码更容易测试的想法并不是真的太相信,或者甚至让它更容易编写更可测试的代码。

在我看来,你最终得到了许多额外的抽象层,实际上是间接的,只是为了支持一些魔法" - 即,自动实例化函数参数名称。没有那个功能 - 就是:神奇地获得一个$ http或$ car的实例,或者当你的函数被调用时的任何东西 - 它似乎并没有提供那么多。

在使这些调用显式化的过程中,它有多少额外的努力,以及减少多少间接和魔法?你最终得到的是一个全球性的" (从你的应用程序的角度来看)命名空间......所以手动操作真的只有一些方便。

来自文档:

myModule.factory('greeter', function($window) {
  return {
    greet: function(text) {
      $window.alert(text);
    }
  };
});
function MyController($scope, greeter) {
  $scope.sayHello = function() {
    greeter.greet('Hello World');
  };
}

这里的魔力是" greeter" 根据参数的名称自动注入,对吗?我假设它对于$ scope来说是相同的,虽然据我所知,所有控制器都应该将$ scope作为第一个参数,所以可能不是这样。

一个非神奇的例子:

function MyController() {
  var scope = myApp.get('scope');
  var greeter = myApp.get('greeter');
  scope.sayHello = function() {
    greeter.greet('Hello World');
  }
}

正如您所看到的,我只是添加了一个" .get()"获取依赖项的方法。我理解Angular完全可以实现这一点 - 但这不是我所读过的文档所提出的主要案例。

非魔法测试:

function myControllerTest() {
  var scope = {};
  var greeter = { greet: function() {} };
  myApp.set('scope', scope);
  myApp.set('greeter', greeter);
  // ... run an actual test on MyController here
}

我并没有真正对Angular做过任何重大的事情,但随着我变得越来越老,越来越谦虚,我发现我越来越不喜欢魔法了。我非常高兴添加(比如说)多20%的行代码,以避免间接级别,这意味着无论框架或语言如何,我都无法轻松浏览代码。

有人可以给出一个合理的例子,说明角度对DI的影响与某些基本约定相比没有相对无问题吗?我错过了什么好处"魔法"只是为了避免明确定义依赖关系?

2 个答案:

答案 0 :(得分:3)

依赖注入是在经典OOP文献中说出所谓“隔离”的一种奇特而新的方式。这意味着对象不应该了解外部世界。它是封装的补充原则,它说外部世界不应该知道对象的内部运作。实际上,这意味着如果使用依赖注入,则不使用全局变量。依赖注入不是一个框架,它是一个设计原则。 Angulars DI框架只是为了让它更容易。正如您所指出的那样,使用DI经常会引入间接性。这是你支付的价格。如果你不同意,那就完全没问题了。 DI肯定会让你的代码更难理解很多情况。然而,它产生了更多可组合和模块化的软件。

在你的'非魔法'版本中,你基本上引入了'服务定位器'。这导致对myApp的依赖。从DI的角度来看,这种依赖性是最糟糕的,因为它是隐藏的,间接的和全球的。 '隐藏'意味着它不是函数参数。只有在阅读代码本身时才会看到它。间接意味着,你真正关心的是greeter,但你所依赖的是myApp。全球应该很明显。有很多争论为什么全局变量一般都很糟糕,但是对于测试,问题是你的测试彼此共享状态。您不能以这种方式单独运行测试。这可能导致“测试片状”,这意味着某些测试有时会失败,有时则不会,这取决于另一个测试。

答案 1 :(得分:0)

首先,我完全理解你的观点。

今天我发现自己在使用任何js框架方面都非常有选择性。他们似乎无处不在,其中很多人,你的20%以上真的会更好,并避免那些额外的层。

由于我对这一切都比较新,所以我不想在这里与你争辩......让我也对Angular发表意见。

支持像javascript这样的技术对新手来说非常具有挑战性,而且我觉得很容易从错误的脚开始,而没有人在路上瞎了一下。 特别是如果您的目标是在应用程序中达到某种程度的复杂性。

我们都知道好的模式提供了一个坚实的基础,而且正是在我第一次看到它时,Angular吸引了我的注意力。

一切都在那里。简单,纤薄,快速,易于入手和理解。背后的概念和模式是众所周知的,并且对我来说很有意义(DI,MVC,TDD,模块化,关注点的良好分离,强大的绑定策略),尽管我还不知道如何使用javascript实现它们那个时候。

所以基本上它让我开始,让我开始很好。今天我比以前知道的更多,我看到很多其他框架说再见,原因与你指出的相同。但是Angular留了下来,最初的架构对我来说太棒了!

也许如果我有时间,我会选择一个自己的角度,只是为了它的一脚......但是当我想到它时,我想我不会让它变得太多不同。 那为什么要这么麻烦?

此外,社区发展迅速,文档非常好,每个角落都有帮助!

我知道你在这里谈论DI和可测试性,但这只是你从Angular获得的一小部分。仅出于此目的,我确信您可以很好地完成替代方案:)

顺便说一下,谈论可测试性时,请看一下角度情节跑步者,我知道它已经停止了(Lord知道为什么?!?)但是......

这是一种魔力!