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:
Namespacing - this avoids adding stuff to global namespace, avoids potential conflicts and allows for resolving proper components easily where needed
Creating reusable components / modules - by, for instance, using function module pattern and explicitly declaring private and public members
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.
Related
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:
Namespacing - this avoids adding stuff to global namespace, avoids potential conflicts and allows for resolving proper components easily where needed
Creating reusable components / modules - by, for instance, using function module pattern and explicitly declaring private and public members
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.
I come from server side language background (Symfony2). What I know is that dependency injection and service-oriented architectures are specific to object oriented programming. From their documentation:
Structuring your application around a set of independent service
classes is a well-known and trusted object-oriented best-practice.
These skills are key to being a good developer in almost any language.
I am reading now a client-side framework documentation (AngularJS), precisely the dependency injection chapter. Is angularJs written with OOP? Someone please to help me understand.
Thanks for your usual help.
The concept of dependency injection is based on the following ideas:
An entity (object, module, etc.) should not programmatically create the entities it depends upon.
Those dependencies should instead be passed as parameters (injected) instead.
This reduces unwanted coupling and allows other implementations to be substituted more easily (e.g., alternative data sources, stubs or mocks for testing)
As Doug Luce states in his answer, this concept can apply in other programming paradigms as well. The term is most common in object oriented circles because:
The origin of (programming) design patterns was object oriented programming.
Dependency Injection can alleviate the tendency of large object oriented programs to become too tightly coupled, difficult to test and brittle to change.
In some situations, such as pure functional programming, there is less need for something like dependency injection (it tends to happen naturally).
In structural languages without object oriented features, the concept is still very useful (perhaps even more so). Obvious and easily used mechanisms for dependency injection are not agreed upon in (non object oriented) structural languages.
Since JavaScript has both object oriented and functional features, I would expect AngularJS programmers to make full use of these features and use dependency injection when appropriate.
When the concept is called "dependency injection," it's almost always couched in the verbiage of object-oriented patterns. But the idea of passing in a wad of executable code that the function can use only depends on the language system having a way to do that: function types, closures, monads, promises, or whatever might do the trick.
I have an index page with a controller scoped to <body>
I'm finding it very convenient to store objects on the body controller that need to be accessed by multiple views.
My question is, is there anything wrong with doing this? Traditionally, I store such objects in a service, but sometimes I just have random things that i want to persist throughout the session and i'm finding the body controller fits them quite nice. Want to make sure I understand the best practice there, why i might not do that, or why it is actually a fine idea?
The Angular Documentation on Understanding Scopes, says the following:
Nesting controllers using ng-controller results in normal prototypal
inheritance, just like ng-include and ng-switch, so the same
techniques apply. However, "it is considered bad form for two
controllers to share information via $scope inheritance" --
http://onehungrymind.com/angularjs-sticky-notes-pt-1-architecture/ A
service should be used to share data between controllers instead.
I would argue that using a service is easier to test and it is separation of concerns. Also, depending on the number of variables and their names, it will become quite confusing to keep track of the right variables. If you use a service on the other hand, some IDEs (e.g. Webstorm) will be able access the variables with auto-completion.
I would say that in general this is a very bad practice because it goes against one of the golden principles of angularjs, which is to keep the structure and the behavior separated, we can do that thanks to the fact that dependency injection is at the core of angularjs architecture.
In general doing what you are suggesting will make your code to be more difficult to test and reuse, and in the long run more difficult to maintain too.
I am very wary of using an all-inclusive application framework for building my SPA. I have done a lot of reading on the subject, but I haven't found any articles on whether these frameworks are composable or not. I have a long-held architectural belief that frameworks should not try to do too much, rather they should:
do one thing only
do it very well
easily compose with other frameworks
Having said this, I'm trying to think outside the "should I use Angular, Ember, or Backbone" box and ask if there is a way to use more than one. For example, would it be possible to use Angular's templating (which I've heard is awesome) but use also Ember's routing (which supposedly rocks)?
My goal is to make the "all-important SPA framework decision" less important, so that I can change it later. If we go with a mixed approach, it buys us 2 major benefits:
we can rip out the "templating" engine or the "routing" engine or the "whatever" engine individually, and thus not need an entire application re-write to change something we don't like
by figuring out how to make them play nice together, we would be able to switch out individual routes/controllers/views allowing use to switch frameworks/approaches in small granular steps
Would this be a reasonable choice or totally fraught with annoying difficulties?
If the answer is the latter, then these frameworks are fundamentally flawed and I will not be using them.
The innards of both Angular and Ember are tightly coupled. You could do portions of a page with just Ember or just Angular, but mixing the routing/templating/data-binding from one framework to another would be an extremely difficult task.
In AngularJS you can create a cache.
This is essentially nothing more than the equivalent of an ArrayList<T> in Java where you can add/remove items. In Javascript though, you have push and pop to add/remove stuff from an array.
So why would you want to use AngularJS' cache?
https://docs.angularjs.org/api/ng/service/$cacheFactory
You do it for the purpose of reuse and abstraction.
The cache will only exist once, but if you implement it in every controller or service, you are duplicating the same code over and over, making it harder to maintain.
It's also an abstraction, you are basicly creating a module with an interface, which makes your services independent from the implementation behind it.
In example, you could have a cache item that expires, you could either a write the code/logic to remove the expired ones in every single service, or you could have it in a single module you call cache. This way you are reusing code, and making it easy to maintain.
Wether you use theirs, or make your own doesn't matter, the principals are the same.
One reason to use the Angular cache, is so that you don't have to write the same boiler plate everyone else have already implemented a thousand times. You can go straight to your domain and business logic
You also get certain benifits from using a Cache Module.
You don't have to care about the implementation behind the interface. (Program against an interface, not an implementation).
You can inject a different module with different logic behind it, but with the same interface, with DI.
It's easy to maintain.
You can easily extend and expand it, eg. add expiration.
It's easier to make test stubs (see point 2.).
You can easily reuse the module.
The logic is in it's rightful place, and not scattered around.