Speaking specifically about the DI features I'm not a fan of Angular, and I'm not really too convinced by the idea that Angular makes your code more testable, or even that it makes it easier to write more testable code.
It seems to me that you end up with a lot of extra layers of abstraction, and indeed indirection, simply to support some "magic" - that is, making function parameter names be automatically instantiated. Without that one feature - that is: magically getting an instance of $http, or $car, or whatever when your function is called - it seems that it's not providing all that much.
How much extra effort is it, and how much less indirection and magic is there, in making those calls explicit? What you end up with is a "global" (from your app's point of view) namespace ... so there really is only a bit of convenience in not doing the stuff by hand.
From the docs:
myModule.factory('greeter', function($window) {
return {
greet: function(text) {
$window.alert(text);
}
};
});
function MyController($scope, greeter) {
$scope.sayHello = function() {
greeter.greet('Hello World');
};
}
The magic here is that "greeter" is automatically injected based on the name of the parameter, right? And I'm assuming it's the same for $scope, although as I understand it, all controllers are expected to have $scope as the first parameter so that may not be the case.
An non-magical example:
function MyController() {
var scope = myApp.get('scope');
var greeter = myApp.get('greeter');
scope.sayHello = function() {
greeter.greet('Hello World');
}
}
As you can see, I've simply added a ".get()" method for getting your dependencies. I understand that this is completely possible with Angular - but that isn't the main case suggested by the docs I've read.
A non-magical test:
function myControllerTest() {
var scope = {};
var greeter = { greet: function() {} };
myApp.set('scope', scope);
myApp.set('greeter', greeter);
// ... run an actual test on MyController here
}
I've not really done anything significant with Angular, but as I'm getting older and more curmudgeonly, I find that I dislike magic more and more. I'm perfectly happy adding (let's say) 20% more lines code to avoid levels of indirection that mean I can't easily step through my code, no matter the framework or language.
Can someone give a reasonable example of what angular does with DI that isn't relatively problem-free to do by hand with some basic conventions? Is there a benefit I've missed for "magic" simply so that you avoid explicitly defining your dependencies?
myApp.get('scope')- And which scope might that be? ^^window.alert()to get its argument by itself. There is nothing magical with angular's way of injecting dependencies. It's similar to your 'non-magical' example. Except for the scope and the fact that you have introduced an additional dependency. Btw: You should use the array notation.