Angular.js - Javascript Dependency Injection - javascript

I read about DI and DI in Angular.js.
From what I understand DI in Angular.js means that Angular.js is allowing controller, factory, service, or others, to specify dependencies, without the need of creating the dependency.
Questions:
In some point dependency has to be created, making the place where the dependency was created not DIed, how do I understand this?
What if I have:
var thing = function(dep){
this.dep = dep || new depCreator();
}
is this DIed? or depends whether dep is passed to the function?
From what I see, DI means allow to set a dependency, being it in a function or object, at the end, would it mean to separate initialization/configuration/data from other parts of the program(logic? although we could have also initialization logic)?:
var dep1 = 'qwe';
var thing = function(dep){ this.dep = dep; }
var diedThing = new thing(dep1);
This would allow to set dep1 in a configuration file, for example.
If the plain JavaScript implementing DI is:
var thing = function(dep){
this.dep = dep;
}
instead of
var thing = function(){
this.dep = new depCreator();
}
Is this right?
But what if depCreator depends on configuration files(or an extracted configuration), would this be DIed?
When I read that Angular.js has(?) DI, is it correct to think that this DI means that Angular.js creates and searches dependencies for me? is there another meaning?
Lastly, if DI is so complex, but means just to separate configuration from implementation(or logic?), why not call it single responsibility principle, i.e. the method does what the method does, the configuration does what the configuration does, and so on.
At the end, DI is to me a subjective concept, which is how do you imagine and split responsibilities in some application, is this even near to correct?
Sorry for the long question.

The place where the dependency is created does not depend on it. It's sole purpose is usually to create the "thing" and register it with the DI subsystem. There is nothing weird or suspicious about that.
Why would you want to do this? Maybe instead depend on a service that creates the object for you if you need more flexibility.
DI means dependency injection - exactly that, you don't create the thing you depend on yourself. Instead you ask for it and voila, it is made available to you. You don't need to know how to create it, who created it etc.
If depCreator depends on the configuration files then that is fine. It can use them. Prior to registering dep with the DI subsystem it can do just about anything. That is what you would do, create a service/factory depCreator that would register dep and make it available for other components of your app.
No question mark. Angular has a DI subsystem and it is actually one of the core ideas behind angular. Angular provides many components for you out of the box ready to be injected, the rest you have to create and register on your own.
I don't know if I would say DI is complex. Maybe it is tricky to implement, I wouldn't know, but once you learn to use it you will not want to go back. DI in angular might just be the easiest to use I have ever seen. It's so good it's sort of transparent. After a while you don't even notice it's there and it works so well.
Your last remark is sort of correct I think. It is in a way about separation of concerns the way I see it. But there are many, many good resources out there that explain DI so I will not elaborate here. As always I would recommend reading ng-book for more angular specific details.

Related

Accessing an Angular service that may or may not exist

I'm working on an Angular project at the minute that is designed to very modular - sections of the app can be enabled and disabled for different clients using Webpack. This structure is working nicely for me so far, but one issue I've run into is working out how to handle services that might not always be present.
My current solution is pretty simple - I use $injector.has() to check if the service currently exists, and if so, I use $injector.get() to grab it:
function initialize($injector) {
if ($injector.has("barcode")) {
let barcode = $injector.get("barcode");
// Do stuff with the barcode service
}
}
This seems to work - however, I can't find much information on the use of this pattern and whether or not it has any potential downsides.
So, my questions are:
Are there any caveats to using the injector this way that I should be aware of?
Is there a better/more idiomatic way of doing this?
This is probably the best way to accomplish what you want; however, in doing this, note that you are moving from Dependency Injection (DI) to Service Locator pattern.
The following from the Angular 2 docs is quite relevant (emphasis mine):
We avoid this technique unless we genuinely need it. It encourages a careless grab-bag approach such as we see here. It's difficult to explain, understand, and test. We can't know by inspecting the constructor what this class requires or what it will do. It could acquire services from any ancestor component, not just its own. We're forced to spelunk the implementation to discover what it does.
Framework developers may take this approach when they must acquire services generically and dynamically.
(Aside: It's worth having a read over what's coming for dependency injection in Angular 2 -- Optional dependencies, Factory providers, etc.)
Angular 1's docs on the matter make reference to it running afoul of The Law of Demeter (which is of course more of a guideline than a Law, right?).
In any case, just some additional things to be aware of:
You won't be warned (by having errors thrown) of circular dependencies where this is used; in fact, this is often a technique people use to get around these warnings.
Since you now have a dependency on $injector in addition to what you inject with it, your unit tests will either need to mock $injector, or use something like module('moduleThatIsUsingInjectorExplicitly', function($provide) { $provide.value('barcode', barCodeMock);}.
As mentioned in the quote above, your code will be a little less clear since these 'optional' dependencies are not defined in the usual places.
Plenty of other reading out there on Service Locator pattern, and contrasting it with DI. Interesting enough, but practical implications for us are probably limited, especially as JavaScript's lack of Interface/Abstract and Angular 1's implementation of DI mean there are fewer real points of difference.

Node js, split up files without having to pass dependencies around?

This may be just me lacking a 'bigger picture' so to speak, but I'm having trouble understanding why exporting modules is needed to just split up files.
I tried doing something like this:
//server.js
var app = require('koa')();
var othermodule1 = require('othermodule1')();
var othermodule2 = require('othermodule2')();
var router = require('./config/routes')();
app.use(router.routes());
//routes.js
module.exports = require('koa-router')()
.get('*', function*(next){
othermodule1.something;
})
realizing that routes.js does not have access to 'othermodule1' after calling it from serverjs. I know that there's a way to pass needed variables during the require call, but I have a lot more than just 2 modules that I would need to pass. So from my probably naive perspective, this seems somewhat unnecessarily cumbersome. Someone care to enlighten me or is there actually a way to do this that I missed?
Each node.js module is meant to be a stand-alone sharable unit. It includes everything that it needs to do its job. That's the principle behind modules.
This principle makes for a little more overhead at the start of each module to require() in everything you need in that module, but it's only done once at the server startup and all modules are cached anyway so it isn't generally a meaningful performance issue.
You can make global things by assigning to the global object, but they that often breaks modularity and definitely goes against the design spirit of independently shareable modules.
In your specific code, if routes needs access to othermodule1, then it should just require() it in as needed. That's how modules work. routes should just include the things it needs. Modules are cached so requiring it many times just gives every require() the same module handle from a cache.
This is an adjustment in thinking from other systems, but once you get use to it, you just do it and it's no big deal. Either require() in what you need (the plain shareable module method) or pass something into a module on its constructor (the push method) or create init() methods so someone can initialize you properly or call some other module to get the things you need (the pull method).

ES6 exports/imports use-case, compared to traditional namespacing

I don't understand WHY and in what scenario this would be used..
My current web setup consists of lots of components, which are just functions or factory functions, each in their own file, and each function "rides" the app namespace, like : app.component.breadcrumbs = function(){... and so on.
Then GULP just combines all the files, and I end up with a single file, so a page controller (each "page" has a controller which loads the components the page needs) can just load it's components, like: app.component.breadcrumbs(data).
All the components can be easily accessed on demand, and the single javascript file is well cached and everything. This way of work seems extremely good, never saw any problem with this way of work. of course, this can (and is) be scaled nicely.
So how are ES6 imports for functions any better than what I described?
what's the deal with importing functions instead of just attaching them to the App's namespace? it makes much more sense for them to be "attached".
Files structure
/dist/app.js // web app namespace and so on
/dist/components/breadcrumbs.js // some component
/dist/components/header.js // some component
/dist/components/sidemenu.js // some component
/dist/pages/homepage.js // home page controller
// GULP concat all above to
/js/app.js // this file is what is downloaded
Then inside homepage.js it can look like this:
app.routes.homepage = function(){
"use strict";
var DOM = { page : $('#page') };
// append whatever components I want to this page
DOM.page.append(
app.component.header(),
app.component.sidemenu(),
app.component.breadcrumbs({a:1, b:2, c:3})
)
};
This is an extremely simplified code example but you get the point
Answers to this are probably a little subjective, but I'm going to do my best.
At the end of the day, both methods allow support creating a namespace for a piece of functionality so that it does not conflict with other things. Both work, but in my view, modules, ES6 or any other, provide a few extra benefits.
Explicit dependencies
Your example seems very bias toward a "load everything" approach, but you'll generally find that to be uncommon. If your components/header.js needs to use components/breadcrumbs.js, assumptions must be made. Has that file been bundled into the overall JS file? You have no way of knowing. You're two options are
Load everything
Maintain a file somewhere that explicitly lists what needs to be loaded.
The first option is easy and in the short term is probably fine. The second is complicated for maintainability because it would be maintained as an external list, it would be very easy to stop needing one of your component file but forget to remove it.
It also means that you are essentially defining your own syntax for dependencies when again, one has now been defined in the language/community.
What happens when you want to start splitting your application into pieces? Say you have an application that is a single large file that drives 5 pages on your site, because they started out simple and it wasn't big enough to matter. Now the application has grown and should be served with a separate JS file per-page. You have now lost the ability to use option #1, and some poor soul would need to build this new list of dependencies for each end file.
What if you start using a file in a new places? How do you know which JS target files actually need it? What if you have twenty target files?
What if you have a library of components that are used across your whole company, and one of they starts relying on something new? How would that information be propagated to any number of the developers using these?
Modules allow you to know with 100% certainty what is used where, with automated tooling. You only need to package the files you actually use.
Ordering
Related to dependency listing is dependency ordering. If your library needs to create a special subclass of your header.js component, you are no longer only accessing app.component.header() from app.routes.homepage(), which would presumable be running at DOMContentLoaded. Instead you need to access it during the initial application execution. Simple concatenation offers no guarantees that it will have run yet. If you are concatenating alphabetically and your new things is app.component.blueHeader() then it would fail.
This applies to anything that you might want to do immediately at execution time. If you have a module that immediately looks at the page when it runs, or sends an AJAX request or anything, what if it depends on some library to do that?
This is another argument agains #1 (Load everything) so you start having to maintain a list again. That list is again going to be a custom things you'll have come up with instead of a standardized system.
How do you train new employees to use all of this custom stuff you've built?
Modules execute files in order based on their dependencies, so you know for sure that the stuff you depend on will have executed and will be available.
Scoping
Your solution treats everything as a standard script file. That's fine, but it means that you need to be extremely careful to not accidentally create global variables by placing them in the top-level scope of a file. This can be solved by manually adding (function(){ ... })(); around file content, but again, it's one more things you need to know to do instead of having it provided for you by the language.
Conflicts
app.component.* is something you've chosen, but there is nothing special about it, and it is global. What if you wanted to pull in a new library from Github for instance, and it also used that same name? Do you refactor your whole application to avoid conflicts?
What if you need to load two versions of a library? That has obvious downsides if it's big, but there are plenty of cases where you'll still want to trade big for non-functional. If you rely on a global object, it is now up to that library to make sure it also exposes an API like jQuery's noConflict. What if it doesn't? Do you have to add it yourself?
Encouraging smaller modules
This one may be more debatable, but I've certainly observed it within my own codebase. With modules, and the lack of boilerplate necessary to write modular code with them, developers are encouraged to look closely on how things get grouped. It is very easy to end up making "utils" files that are giant bags of functions thousands of lines long because it is easier to add to an existing file that it is to make a new one.
Dependency webs
Having explicit imports and exports makes it very clear what depends on what, which is great, but the side-effect of that is that it is much easier to think critically about dependencies. If you have a giant file with 100 helper functions, that means that if any one of those helpers needs to depend on something from another file, it needs to be loaded, even if nothing is ever using that helper function at the moment. This can easily lead to a large web of unclear dependencies, and being aware of dependencies is a huge step toward thwarting that.
Standardization
There is a lot to be said for standardization. The JavaScript community has moved heavily in the direction of reusable modules. This means that if you hope into a new codebase, you don't need to start off by figuring out how things relate to eachother. Your first step, at least in the long run, won't be to wonder whether something is AMD, CommonJS, System.register or what. By having a syntax in the language, it's one less decision to have to make.
The long and short of it is, modules offer a standard way for code to interoperate, whether that be your own code, or third-party code.
Your current process is to concatenate everything always into a single large file, only ever execute things after the whole file has loaded and you have 100% control over all code that you are executing, then you've essentially defined your own module specification based on your own assumptions about your specific codebase. That is totally fine, and no-one is forcing you to change that.
No such assumptions can be made for the general case of JavaScript code however. It is precisely the objective of modules to provide a standard in such a way as to not break existing code, but to also provide the community with a way forward. What modules offer is another approach to that, which is one that is standardized, and one that offers clearer paths for interoperability between your own code and third-party code.

Managing globally needed services in web applications

I struggle to find a statisfying solution on how to expose service instances whose methods need to be accessed through multiple parts of my applications.
The situation
First things first, by a 'service', I mean an instance of a function that holds properties & methods which are exposed through an API.
Consider a REST service whose purpose it is to provide convenient methods to access REST points on a server. I would make the following assumptions on that service:
It must be available throughout the application. It is likely that as the app grows, there will be new components that need access.
There is no need of multiple instances of this service. We can consider it a singleton.
My solutions
I can think of 2 possible solutions:
Concatenating scripts & utilizing the global object
I could combine all my script files (e.g rest.service.js, app.js) into a single file and create an object property on the global object (like App).
Then, I could attach service instances to this object. This allows me to do something like this from everywhere within the app:
App.restService.get()
However, even if I wrap each service in an IIFE, i still have to add some variables on window in order to retrieve instances.
Using commonJS / AMD modules
I could require() my service instances from everywhere by using require.js / browserify
The issues
Now I got a headache because on the one hand, people are telling me that polluting the global object is bad practice. Singletons are bad practice also.
On the other hand, we make a lot of effort to 'uglify' scripts, each byte saved considered an enhancement. Using browserify would lead to the same script injected in multiple files, though (I'm using web-components, therefore I've got a lot of isolated scripts). Not mentioning the fact that I have no idea on how to provide a state-safe service using browserify.
So how should I approach this problem?
How should I expose standard services that may or may not be instantiated multiple times? How should I implement state-safe ones?
Just a starting point (but too long to be a comment) I really enjoy the strategy used by AngularJs, where you always instantiate services within a container - and every time you instantiate something you also specify which modules should be injected into it:
angular.module('myApp.services', []); // the second argument are the dependencies (an empty array
At any point, you can retrieve your modules and add functionalities:
var services = angular.module('myApp.services');
services.factory('yourServiceName', //
['other', 'service', 'dependencies'],
function(other, service, dependencies){
other.doStuff();
service.doStuff();
dependencies.doStuff();
[..]
});
You can then inject your module in other modules
var myApp = angular.module('na', ['yourServiceName'])
In angular, the app is instantiated by the framework itself - but I guess you can develop a entry point for your app, so that you can use your services.
..unfortunately, I do not know exactly how this pattern is implemented - probably all the modules are stored within an instance of the application, so the global namespace is not polluted.
This problem also confuses me a lot, I think there are two points I can figure out:
1) There must be an entry point for each service in global, otherwise it is impossible to get the one you need everywhere. It's not good to add many things in global, but I think service reference is the one deserved.
2) Config the service object other than initialization, for example, they can be only one ajax service object with different configuration to do different things. There are objects, so they can be merged and extended.
This is an interesting topic, I would like to see more opinions about, not just management of services, also other resources like templates, objects, files, etc.

Dependency Injection vs. Managed Dependencies vs. Global Object

I'm working within a Javascript + BackboneJS (an MVC framework) + RequireJS framework, but this question is somewhat OO generic.
Let me start by explaining that in Backbone, your Views are a mix of traditional Views and Controllers, and your HTML Templates are the traditional MVC Views
Been racking my head about this for a while and I'm not sure what the right/pragmatic approach should be.
I have a User object that contains user preferences (like unit system, language selection, anything else) that a lot of code depends on.
Some of my Views do most of the work without the use of templates (by using 3rd party libs, like Mapping and Graphing libs), and as such they have a dependency on the User object to take care of unit conversion, for example. I'm currently using RequireJS to manage that dependency without breaking encapsulation too much.
Some of my Views do very little work themselves, and only pass on Model data to my templating engine / templates, which do the work and DO have a dependency on the User object, again, for things like units conversion. The only way to pass this dependency into the template is by injecting it into the Model, and passing the model into the template engine.
My question is, how to best handle such a widely needed dependency?
- Create an App-wide reference/global object that is accessible everywhere? (YUK)
- Use RequireJS managed dependencies, even though it's generally only recommended to use managed dependency loading for class/object definitions rather than concrete objects.
- Or, only ever use dependency injection, and manually pass that dependency into everything that needs it?
From a purely technical point of view, I would argue that commutable globals (globals that may change), especially in javascript, are dangerous and wrong. Especially since javascript is full of parts of code that get executed asynchronously. Consider the following code:
window.loggedinuser = Users.get("Paul");
addSomeStuffToLoggedinUser();
window.loggedinuser = Users.get("Sam");
doSomeOtherStuffToLoggedinUser();
Now if addSomeStuffToLoggedinUser() executes asynchronously somewhere (e.g. it does an ajax call, and then another ajax call when the first one finishes), it may very well be adding stuff to the new loggedinuser ("Sam"), by the time it gets to the second ajax call. Clearly not what you want.
Having said that, I'm even less of a supporter of having some user object that we hand around all the time from function to function, ad infinitum.
Personally, having to choose between these two evils, I would choose a global scope for things that "very rarely change" --- unless perhaps I was building a nuclear powerstation or something. So, I tend to make the logged in user available globally in my app, taking the risk that if somehow for some reason some call runs very late, and I have a situation where one user logs out and directly the other one logs in, something strange may happen. (then again, if a meteor crashes into the datacenter that hosts my app, something strange may happen as well... I'm not protecting against that either). Actually a possible solution would be to reload the whole app as soon as someone logs out.
So, I guess it all depends on your app. One thing that makes it better (and makes you feel like you're still getting some OO karma points) is to hide your data in some namespaced singleton:
var myuser = MyApp.domain.LoggedinDomain.getLoggedinUser();
doSomethingCoolWith(myuser);
in stead of
doSomethingCoolWith(window.loggedinuser);
although it's pretty much the same thing in the end...
I think you already answered your own question, you just want someone else to say it for you : ) Use DI, but you aren't really "manually" passing that dependency into everything since you need to reference it to use it anyways.
Considering the TDD approach, how would you test this? DI is best for a new project, but JS gives you flexible options to deal with concrete global dependencies when testing, ie: context construction. Going way back, Yahoo laid out a module pattern where all modules were loosely coupled and not dependent on each other, but that it was ok to have global context. That global context can make your app construction more pragmatic for things that are constantly reused. Its just that you need to apply that judiciously/sparingly and there need be very strong cases for those things being dynamic.

Categories