

Demystifying AngularJS' dependency injection - adambd
http://bdadam.com/blog/demistifying-angularjs-dependency-injection.html

======
davexunit
Dependency injection: A more hip way to say "function parameters".

Angular is pretty cool overall, but I strongly dislike this part of the
library. Inspecting the names of function parameters and matching them up with
registered services is insane. In practice, you have to specify the
dependencies manually anyhow:

    
    
        foo.service('Bar', ['Baz', function(Baz) { ... }]);
    

This way, parameter names are irrelevant outside of the context of that
function, like they should be. I wish this "feature" was dropped entirely.

~~~
caitp
I think people would take issue with the more explicit forms of function
annotation being the __only__ option, for the simple reason that they're a bit
verbose and ugly. It's very nice for people to be able to just write code that
appears to magically work, without any extra noise.

That said, the dependency injection system in angular.dart is a bit different,
and we'll likely be learning and porting some of that back into AngularJS 2.0
over the coming months.

~~~
davexunit
>I think people would take issue with the more explicit forms of function
annotation being the __only__ option, for the simple reason that they're a bit
verbose and ugly.

I understand the desire to build elegant abstractions via metaprogramming, but
I think is an example of metaprogramming done poorly. This particular feature
was a source of confusion for me and my coworkers when we first started
learning to use Angular. I think that the explicit form is the only sane way,
or at least one of the possible sane ways.

I'll $q.defer() to SICP to explain the principle that is being violated by the
implicit form:

"One detail of a procedure's implementation that should not matter to the user
of the procedure is the implementer's choice of names for the procedure's
formal parameters. ...This principle -- that the meaning of a procedure should
be independent of the parameter names used by its author -- seems on the
surface to be self-evident, but its consequences are profound."

[http://mitpress.mit.edu/sicp/full-text/book/book-
Z-H-4.html#...](http://mitpress.mit.edu/sicp/full-text/book/book-
Z-H-4.html#%_toc_%_sec_Temp_41)

~~~
michaelw
While I agree with what SICP says, the function in this case isn't really a
function. It's not something a caller will ever invoke explicitly. It exists
to provide a closure that can be initialized with the injected parameters.

Pretend for a moment that Javascript had macros (sweet.js where are you?) and
the Angular syntax was more explicit:

    
    
      myModule.provider ProviderName
      inject $scope, $document, SomeOtherDependency
      {
        your code here
      }
    

The last thing you'd expect is a syntax where the injected dependency names
were chosen by the implementor of the provider.

Javascript's greatest weakness is that it's native syntax is poorly suited for
creating language like extensions. The result is that things like modules,
imports, etc. tend to be very verbose and noisy.

~~~
davexunit
>Pretend for a moment that Javascript had macros (sweet.js where are you?) and
the Angular syntax was more explicit:

Well, sure. _If_ and when JavaScript gains hygienic macros (via sweet.js or
otherwise), I will like this sort of notation. However, the reality is that
JavaScript doesn't have macros currently. Thus, I still dislike the magical
dependency notation.

>The last thing you'd expect is a syntax where the injected dependency names
were chosen by the implementor of the provider.

I don't see why this is bad. Several languages allow you to rename things in
imported modules. The two that I can think of immediately are Python and Guile
Scheme. Most of the time there is no reason to rename, but sometimes it is a
good idea to rename for clarity or to avoid name clashes. This is something
that you can already do via the explicit form of dependency injection.

------
andy_ppp
For me (and I realise this won't be popular) - AngularJS is an abomination -
every time google plays with front end code they make every attempt to turn it
into their own language one that has as little relation as possible to the
underlying code that's happening. As we all know, abstractions leak, please
avoid and use one of the many other libraries that people can actually follow
through and debug without having to learn Angular first.

I speak from bitter experience with a product that ended up being two months
late because of the decision by a junior Seb to use Angular - I highly
recommend avoiding it and learning JavaScript properly and then picking the
best tools from NPM that you need.

~~~
michaelw
This has less to do with Angular and more to do with Javascript's general
inability to express a useful DSL for anything.

I think your ad hominem and somewhat hyperbolic complaint would be more
credible if you supplied more concrete examples of how Angular caused your
product to be two months late. I'm not saying you're wrong. I'm just saying
that nothing in your comment actually makes your point.

My team has made very effective use of Angular and far from making us late it
has saved us considerable time.

We treat Angular not as an abstraction or framework but as a toolkit for doing
the following:

    
    
      * Extending the browser's built-in HTML and CSS with our own custom behaviour.
    
      * Two way databinding between our application data and the DOM
    
      * Architecting small testable / mockable components
    

For what it's worth, there are some angular-isms that I truly dislike. In
particular, angular.module is a bug farm for early angular developers. Also,
without ngmin, Angular's "provider" declarations is both noisy and error
prone. The truth howerver, is that these are minor problems and are easily
discovered and fixed immediately.

~~~
andy_ppp
Extends HTML in a very very ugly way.

Impossible to progressively enhance.

It does loads of magic such as dependency injection that is completely
unnecessary. Computer programs are for explaining what is happening to the
next person and Angular makes this more difficult.

There are other JS frameworks that do none of this and solve your problems, I
say use them instead.

Data binding in particular had a really difficult to use syntax for things
like looping. Loads of different attributes that you have look up every time
you need to do something in a template.

Generally people have no idea what the in built components are doing of why
the infinite scrolling can't work well on mobile.

It's really hard to use a JS debugger when I've tried with Angular - maybe you
have had more success than me on this?

You admit Angular comes with some problems out of the box, how are new dev
teams meant to know this automatically?

------
imslavko
Is it really how it is done in Angular? Sounds like it would break if I
introduce a minification step with name mangling.

Edit: I am not really into Angular so I was surprised to see such reflection
on functions. Good to know there are a lot of solutions to that already.

~~~
inportb
It does break if you introduce a minification step with name mangling.

[http://docs.angularjs.org/tutorial/step_05](http://docs.angularjs.org/tutorial/step_05)
(see A Note on Minification)

------
andreypopp
I think this kind of things is much more suitable to be implemented via macros
because 1) it can be implemented with much nicer syntax not abusing function
syntax and 2) it can be done at compile time (I mean true compile time, not in
browser).

Consider the following syntax:

    
    
        // values to inject
        var registry = {
          scope: ...
          http: ...
        }
    
        inject http, scope {
          http.get('/search', {query: scope.query}).then(render);
        }
    

all of these can be done today with sweet.js[1] — see the example
[http://bit.ly/1bjdxWJ](http://bit.ly/1bjdxWJ)

[1]: [http://sweetjs.org](http://sweetjs.org)

------
olenhad
I'm slightly surprised to see regex being used to parse and retrieve arguments
from a function's source code. I would've normally assumed this to be a bad
idea.

~~~
bsimpson
I asked the original author about this at I/O last year shortly after I was
introduced to Angular. I was baffled that they were just using toString and
regexs. On the one hand, there isn't any (obvious) cleaner was to do it. On
the other, it feels so duct taped I couldn't believe it was the foundation of
a Google-sponsored project.

~~~
city41
But it's not a foundation. A production Angular app really shouldn't rely on
this (if for no other reason minification becomes impossible). This flavor of
parameter parsing really only exists for demos and throw away code.

------
latimer
One of Angular's core contributors gave a talk at ng-conf on a new DI system
he's been working on that may eventually make it into Angular.

[http://www.youtube.com/watch?v=_OGGsf1ZXMs](http://www.youtube.com/watch?v=_OGGsf1ZXMs)

------
bsaul
That was the first part of angular that i looked into the source code for,
because i really wondered how theydid it. The fact that they used regexp
realky had me freeze for a while. But then, is it really uglier than AOP in
java ? It's light, it's fast and it has a proven record of working just fine.
So i would much prefer them not relying on dirty te hnics like that, but let's
face it : that would very likely mean not doing it in javascript.

------
kishor_gurtu
If something needs demystifying, that's a design smell.

~~~
ianstormtaylor
Cannot agree more. This is _the_ problem with Angular.

~~~
lukeholder
I agree, its magic gone too far where you are no longer using javascript you
are using angularscript.

