AngularJS 依赖注入有什么好处? [英] What are the benefits of AngularJS dependency injection?

查看:34
本文介绍了AngularJS 依赖注入有什么好处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 Angular 已经有一段时间了,但我看不出它比我以前的编码方式有什么改进.

首先,我看不出有一个中心对象来保存您的项目有什么问题.毕竟,注入器是一个单例,它将您的依赖项查找到一个中心位置,所以 Angular 确实有一个中心对象,它只是隐藏的.如果使用得当,命名空间并不一定意味着耦合.即使完成了,您也不需要代码的每个对象都与其他对象松散耦合.此外,任何时候你创建一个独立的 JS 脚本,你都必须把它包装到 Angular 中,让它们一起玩得很好.

其次,每次声明所有依赖项都非常冗长(尤其是在缩小时),因此与正确的命名空间相比,从可读性的角度来看没有任何好处.

第三,性能提升很小.这迫使我在任何地方都使用单例,但如果需要,我可以自己做,而且大多数时候,我不需要(网络和 DOM 操作是我的瓶颈,而不是 JS 对象).

最后,我喜欢增强型"HTML 和自动双向绑定,但我看不出注入如何使它比其他框架处理依赖项的方式更好,因为它甚至不提供像 require.js 那样的动态加载.我还没有看到任何我对自己说哦,这是比以前好多了,我明白了"的用例.编码时.

您能否向我解释一下这种技术选择给项目带来了什么好处?

我现在只能看到一个:约定和最佳实践执行.创建一个 lib 生态系统是一件大事,但目前我在 Angular 社区中看不到它的成果.

解决方案

对我来说 Angular 的依赖注入是如何改进我的项目的,我将在这里列出.我希望这将向您展示 OTHERS 如何从中受益,但是如果您组织良好且经验丰富的 JS 开发人员,那么对于您来说可能情况并非如此.我认为在某些时候,这只是开发您自己的工具和编码指南的问题.

统一的声明式依赖解析

JS 是一种动态语言(那是新的,是吧?)它赋予了程序员很大的权力,甚至更多的责任.组件可以通过传递各种对象以各种方式相互交互:常规对象、单例、函数等.它们甚至可以使用其他组件甚至没有提到要使用的代码块.

JS 从来没有(而且很可能永远不会)像其他语言(Java、C、C#)那样有一种统一的方式来声明公共、私有或包(模块)范围.当然有封装逻辑的方法,但是问任何一个语言的新手,他根本不知道如何使用它.

我喜欢 DI(不仅在 Angular 中,而且在一般情况下)的事实是,您可以列出组件的依赖项,并且您不会为这种依赖项是如何构建的而烦恼.这对我来说非常重要,尤其是 Angular 中的 DI 允许您解析两种类型的组件:这些来自框架本身(如 $http),或自定义组件(如我最喜欢的 eventBus 我用来包装 $on 事件处理程序).

我经常查看服务的声明,通过查看依赖关系,我就知道它做了什么以及它是如何做的!

如果我要构建和/或使用组件本身深处的所有这些对象,那么我将始终必须彻底分析实现并从各个方面检查它.如果我在依赖项列表中看到 localStorage,我就知道我正在使用 HTML5 本地存储来保存一些数据.我不必在代码中寻找它.

组件的使用寿命

我们不再需要担心某些组件的初始化顺序.如果A 依赖于B,那么DI 将确保BA 需要时准备就绪.>

单元测试

在使用 DI 时模拟组件很有帮助.例如,如果您有控制器:function Ctrl($scope, a, b, c, d) 那么您会立即知道它依赖什么.您注入适当的模拟,并确保所有与您交谈和聆听您的控制器的各方都是隔离的.如果您在编写测试时遇到问题,那么您很可能搞砸了抽象级别或违反了设计原则(直径定律、封装等)

好习惯

是的,很可能您可以使用命名空间来正确管理对象的生命周期.在需要的地方定义单身人士,并确保没有人弄乱您的私人成员.但老实说,如果框架可以为你做,你需要吗?直到我学会了 Angular,我才以正确的方式"使用 JS.并不是我不在乎,我只是没有必要,因为我只是在几个星期的 UI 中使用 JS,主要基于 jquery.

现在它不同了,我得到了一个很好的框架,它迫使我有点跟上良好的实践,但它也给了我很大的力量来扩展它并利用 JS 的最佳功能.

当然,可怜的程序员仍然可以打破最好的工具,但是根据我最近阅读 D. Crockford 的JS 的好部分"所学到的知识,人们正在用它做一些令人讨厌的事情.多亏了 jQuery、Angular 等出色的工具,我们现在有了一些不错的工具,可以帮助编写优秀的 JS 应用程序并在这样做时坚持最佳实践.

结论

正如您所指出的,您至少可以通过做以下三件事来编写好的 JS 应用程序:

  1. 命名空间 - 这避免向全局命名空间添加内容,避免潜在的冲突并允许在需要时轻松解析适当的组件
  2. 创建可重用的组件/模块 - 例如,通过使用功能模块模式并显式声明私有和公共成员
  3. 管理组件之间的依赖关系 - 通过定义单例,允许从某些注册表"中检索依赖关系,不允许在不满足某些条件时执行某些操作

Angular 只是通过以下方式做到这一点:

  • 拥有 $injector 来管理组件之间的依赖关系并在需要时检索它们
  • 强制使用同时具有 PRIVATE 和 PUBLIC API 的工厂函数.
  • 让组件直接(通过相互依赖)或通过共享的 $scope 链相互通信.

I have been working with Angular for some time now, and I fail to see how it is an improvement from my previous way of coding.

First, I can't see what's wrong with having a central object to hold your project. After all, the injector is a singleton that looks up your dependencies into a central place, so Angular does have a central object, it's just hidden. Namespacing doesn't necessarily mean coupling, if it's done properly. And even when it's done, you don't need every single object of your code to be loosely coupled with the others. Besides, anytime you create a standalone JS script, you have to wrap it into Angular to make them play nice together.

Second, it's very verbose to declare all your dependencies everytime (especially with minification), so there is no gain from the readability point of view compared to proper namespacing.

Third, the performance gain is minimal. It forces me to use singletons everywhere, but I can do that on my own if I need to, and most of the time, I don't (network and DOM manipulations are my bottleneck, not JS objects).

In the end, I like the "enhanced" HTML and the automatic two-way bindings, but I can't see how the injection makes it any better than the way other frameworks deal with dependencies, given that it doesn't even provide dynamic loading like require.js. I haven't see any use case where I say to myself "oh, this is where it's so much better than before, I see" while coding.

Could you explain to me what benefits this technical choice brings to a project?

I can see only one for now: convention and best practice enforcement. It's a big one to create a lib ecosystem, but for now I don't see the fruit of it in the Angular community.

解决方案

For me there are few aspects of how Angular's dependency injection is improving my projects, which I will list here. I hope that this will show you how OTHERS can benefit from it, but if you are well organised and experienced JS developer, then perhaps it might not be the same case for you. I think at some point this is just the matter of developing your own tools and coding guide.

Unified, declarative dependency resolving

JS is dynamic language (that's new, huh?) which gives a lot of power and even more responsibility to the programmer. Components can interact with each other on various ways by passing around all sorts of objects: regular objects, singletons, functions, etc. They can even make use of blocks of code which were not even mentioned to be used by other components.

JS has never had (and most likely never will) a unified way of declaring public, private or package (module) scopes like other languages have (Java, C, C#). Of course there are ways of encapsulating logic, but ask any newcomer to the language and he will simply don't know how to use it.

What I like about DI (not only in Angular, but in general) is the fact that you can list dependencies to your component, and you are not troubled how this dependency got constructed. This is very important for me, especially that DI in Angular allows you to resolve both kinds of components: these from the framework itself (like $http), or custom ones (like my favorite eventBus which I'm using to wrap $on event handlers).

Very often I look at the declaration of a service and I know what it does and how it does it just by looking at dependencies!

If I was to construct and/or make use of all those objects deep in the component itself, then I would always have to analyze implementation thoroughly and check it from various aspects. If I see localStorage in dependencies list, I know for the fact that I'm using HTML5 local storage to save some data. I don't have to look for it in the code.

Lifespan of components

We don't need to bother anymore about order of initialization of certain components. If A is dependent on B then DI will make sure that B is ready when A needs it.

Unit testing

It helps a lot to mock out components when you are using DI. For instance, if you have controller: function Ctrl($scope, a, b, c, d) then you instantly know what it is dependent on. You inject proper mocks, and you are making sure that all parties talking and listening to your controller are isolated. If you have troubles writing tests then you most likely messed up levels of abstraction or are violating design principles (Law Of Diameter, Encapsulation, etc.)

Good habits

Yes, most likely you could use namespacing to properly manage the lifespan of your objects. Define singleton where its needed and make sure that noone messes up your private members. But honestly, would you need that if the framework can do it for you? I haven't been using JS "the right way" just until I learned Angular. It's not that I didn't care, I just didn't have to since I was using JS just for some tweeks of UI, primarly based on jquery.

Now its different, I got a nice framework which forces me a bit to keep up with good practices, but it also gives me great power to extend it and make use of the best features that JS has.

Of course poor programmers can still break even the best tool, but from what I've learned by recently reading "JS the good parts" by D. Crockford people were doing reeeeeealy nasty stuff with it. Thanks to great tools like jQuery, Angular and others we now have some nice tool which helps to write good JS applications and sticking to best practices while doing so.

Conclusion

As you have pointed out, you CAN write good JS applications by doing at least those three things:

  1. Namespacing - this avoids adding stuff to global namespace, avoids potential conflicts and allows for resolving proper components easily where needed
  2. Creating reusable components / modules - by, for instance, using function module pattern and explicitly declaring private and public members
  3. Managing dependencies between components - by defining singletons, allowing for retrieving dependencies from some 'registry', disallowing of doing certain stuff when certain conditions are not meet

Angular simply does that by:

  • Having $injector which manages dependencies between components and retrieves them when needed
  • Forcing to use factory function which has both PRIVATE and PUBLIC APIs.
  • Let the components talk to each other either directly (by being dependent of one another) or by shared $scope chain.

这篇关于AngularJS 依赖注入有什么好处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆