Best practices when creating Angular Services - javascript

I was wondering what should be considered when creating Angular services in regards to which module to attach the services too.
For example
var app = angular.module('app', []);
//Add service to app module
app.factory('helloWorld', function() {
return {};
});
//Or create a module for the service, and include the module where needed
var helloWorldModule = angular.module('helloWorldModule', []);
helloWorldModule.factory('helloWorld', function() {
return {};
});
//Or attach is to an existing module that may need it
existingModule.factory('helloWorld', function() {
return {};
});
Should all services created be added to the app module, so I can ensure that I can access the service anywhere if I need to, or should I add it to only the modules that I know that will be using it.
I know that this may be subjective, and based on application structure, basically I am just wondering if it is ever a good idea to add all services to the app module.

As always it depends. If your service is an isolated service that can be shared across different applications and modules then the answer is yes.
If it is relevant only to your current module then no.

Try to maximise the cohesion. If you only have a solution or app it doesn't matter where you place the service, but if you have multiple solutions, maybe during a refactoring process you realise that some services make sense to put them together in the same module.

Related

How to do effective dependency injection in Nodejs?

Let's start with some reference code
var express = require('express');
var app = express();
var session = require('express-session');
app.use(session({
store: require('connect-session-knex')()
}));
I have a couple questions here that I would like to answer in case you know the answer:
Everytime a require is call in Nodejs, is that named dependency injection? Or what is the real meaning of dependency injection?
The reason why I am asking this, is because I've been reading about Node, and I see people people talking about the module or module.export pattern, and I am confuse, the module is the same as dependency?
So, all I need is a clear explanation about dependency injection, and when/where you need to inject a dependency . . .
Dependency injection is somewhat the opposite of normal module design. In normal module design, a module uses require() to load in all the other modules that it needs with the goal of making it simple for the caller to use your module. The caller can just require() in your module and your module will load all the other things it needs.
With dependency injection, rather than the module loading the things it needs, the caller is required to pass in things (usually objects) that the module needs. This can make certain types of testing easier and it can make mocking certain things for testing purposes easier.
Everytime a require is call in Nodejs, is that named dependency
injection? Or what is the real meaning of dependency injection?
No. When a module does a require() to load it's own dependencies that is not dependency injection.
The reason why I am asking this, is because I've been reading about
Node, and I see people people talking about the module or
module.export pattern, and I am confuse, the module is the same as
dependency?
A module is not the same as a dependency. Normal module design allows you to require() just the module and get back a series of exports that you can use. The module itself handles the loading of its own dependencies (usually using require() internal to the module).
Here are a couple of articles that discuss some of the pros/cons of using dependency injection. As best I can tell the main advantage is to simplify unit testing by allowing dependent objects (like databases) to be more easily mocked.
When to use Dependency Injection
When is it not appropriate to use dependency injection
Why should we use dependency injection
A classic case for using a dependency injection is when a module depends upon a database interface. If the module loads it's own database, then that module is essentially hard-wired to that particular database. There is no architecture built into the module for the caller to specify what type of storage should be used.
If, however, the module is set up so that when a caller loads and initializes the module, it must pass in an object that implements a specific database API, then the caller is free to decide what type of database should be used. Any database that meets the contract of the API can be used. But, the burden is on the caller to pick and load a specific database. There can also be hybrid circumstances where a module has a built-in database that will be used by default, but the caller can supply their own object that will be used instead if it is provided in the module constructor or module initialization.
Imagine this code.
var someModule = require('pathToSomeModule');
someModule();
Here, we DEPEND not on the name, but on the path of that file. We are also using the SAME file every time.
Let's look at angular's way (for the client, i know, bear with me)
app.controller('someCtrl', function($scope) {
$scope.foo = 'bar';
});
I know client side js doesn't have file imports / exports, but it's the underlying concept that you should look at. Nowhere does this controller specify WHAT the $scope variable ACTUALLY is, it just knows that angular is giving it something CALLED $scope.
This is Inversion of Control
It is like saying, Don't call me, I'll call you
Now let's implement our original code with something like a service container (there are many different solutions to this, containers are not the only option)
// The only require statement
var container = require('pathToContainer')
var someModule = container.resolve('someModule');
someModule();
What did we accomplish here? Now, we only have to know ONE thing, the container (or whatever abstraction you choose). We have no idea what someModule actually is, or where it's source file is, just that it's what we got from the container. The benefit of this is that, if we want to use a different implementation of someModule, as long as it conforms to the same API as the orignal, we can just replace it ONE place in our ENTIRE app. The container. Now every module that calls someModule will get the new implementation. The idea is that when you make a module, you define the api that you use to interact with it. If different implementations all conform to a single api (or you write an adapter that conforms to it) then you can swap out implementations like dirty underwear and your app will just WORK.
This approach is not for everyone, and some people hate lugging around the container.
My personal opinion, I would rather code to an interface ( a consistent api between implentations ) than code to a concrete implementation.
An actual example of Dependency Injection in node.js
// In a file, far, far, away
module.exports = function(dependencyA, dependencyB) {
dependencyA();
dependencyB();
}
// In another file, the `caller`
// This is where the actual, concrete implementation is stored
var depA = someConcreteImplementation;
var depB = someOtherConcreteImplementation;
var someModule = require('pathToSomeModule');
someModule(depA, depB);
The downside to this, is now the caller needs to know what your dependencies are. Some are comforted by this and like it, others believe it's a hassle.
I prefer this next approach, personally.
If you aren't using babel, or something that changes your functions behind the scenes, you can use this approach to get the angular-style parameter-parsing
http://krasimirtsonev.com/blog/article/Dependency-injection-in-JavaScript
Then you can parse the function you get from require, and not use a container at all.
I use injection-js Dependency injection library for JavaScript and TypeScript with ts-node:
npm i -P injection-js
It's based on the angular2 injector so Injection is super simple.
Here is the typescript version from the README.
import 'reflect-metadata';
import { ReflectiveInjector, Injectable, Injector } from 'injection-js';
class Http {}
#Injectable()
class Service {
constructor(private http: Http) {}
}
#Injectable()
class Service2 {
constructor(private injector: Injector) {}
getService(): void {
console.log(this.injector.get(Service) instanceof Service);
}
createChildInjector(): void {
const childInjector = ReflectiveInjector.resolveAndCreate([
Service
], this.injector);
}
}
const injector = ReflectiveInjector.resolveAndCreate([
Service,
Http
]);
console.log(injector.get(Service) instanceof Service);

angular.js modularization - multiple ng-apps?

I have just started working in angular.js and I have created separate angular applications (using ng-app) for separate modules of my application for modularity sake so that change in one module does not bring down the whole application.
Now, i am running into a issue of redirecting from a search form common across all modules to a particular page (in a specific module). I thought of saving the value in $rootScope, but while debugging, I found that $rootScope is per ng-app, so, it will not work.
Am I wrong in designing the application into separate angular applications and should I move everything back into one ng-app? or is my application structure correct and I should look for another way of passing value?
EDIT: - I think I did not provide enough detail earlier.
My application is structured as follows:
module1
- controller\controller-module1.js
- service\service-module1.js
- css\module1.css
- view\ <multiple html files>
module2
- same structure
I was actually using the service-module to make REST calls to the server till now, rather than sharing data.
All the modules are defined with their separate dependencies in app.js:
angular.module('Module1App', ['Module1App.controller','Module1App.service']);
angular.module('Module2App', ['Module2App.controller','Module2App.service']);
controllers and service of each module are defined in their respective controllers-module.js and service-module.js, which reside in different directories as per the structure above.
So, to include the controller and service of a particular module(of, say, module1), I declare the following in a view of that module
<script src="/APP_GUI/modules/common/service/services-common.js"></script>
<script src="/APP_GUI/modules/reports/service/services-module1.js"></script>
<script src="/APP_GUI/modules/common/controller/controllers-common.js"></script>
<script src="/APP_GUI/modules/reports/controller/controllers-module1.js"></script>
So, if I have to move all ng-controllers (defined in separate directories as per the module structure above) into one ng-app (app.js above), I will basically end up including all the controller.js and service.js in all the html views, which will basically mean that if there is an error in any one of the js files, my entire application will be down (i have tried it out).
So, unless I have misunderstood something, I cannot move all ng-controllers under a single app.js.
I am going to try out using shared services to share data.
Please let me know in case anybody has something to say on my conclusion.
I don't think using many ng-app is a good approach. I suggest you using many ng-controller in separate file instead.
You can keep variables inside objects instead of using $scope, which most tutorials you'll find online don't explain.
For example:
/// Define the app
app = angular.module('MyApp',[]);
///Add a cotroller
app.controller('MyFirstController', ['$scope', function($scope){
/// using 'this' you can write local properties
this.firstLocalProperty = 'first Value is acessible only in MyFirstController';
this.secondLocalProperty = 'second Value is acessible only in MyFirstController';
$scope.firstSharedAppProperty = 'This is Shared between all controllers in app';
}]);
app.controller('MySecondController', ['$scope', function($scope){
/// here you can use shared and local properties, you may access shared things in $scope
this.fistProperty = $scope.firstSharedAppProperty;
}]);
You'll see that
> MySecondController.firstProperty
'This is Shared between all controllers in app'
but
> MyFirstController.firstProperty
'first Value is acessible only in MyFirstController'
MyFirstController.firstProperty keeps it's original value because it's not shared.
Basically, you should use different controllers for different templates instead of using different modules. Using controllers, you may share items between them in the $scope variable. Or you can keep variables private using this reference inside objects.
Take a look in this article and you may understand better this way.
You should be using multiple controllers and then using a common service shared between your services. Services in angular are singletons, so they can be shared over and over and over again, and will be common across the board, including between applications if you inject the shared functionality as another application.
var app = angular.module('firstApp');
app.service('myService', function(){
var self = this;
return{
getValue: function(){return self.value},
setValue: function(value){self.value=value}
}
});
app.controller('firstController', ['myService', function(myService){.....}]);
app.controller('secondController', ['myService', function(myService){....});
var secondApp = angular.module('otherApp',['firstApp']);
secondApp.controller('otherController', ['myService', function(myService){.....}]);
more importantly, if its doing anything more than just storing values you can inject functionality for better testing!

Keeping angularjs decoupled from an application

I'm planning out an application that ideally I'd like to keep decoupled from Angular, so all the dom interaction will go into an Angular layer but the core business logic will be kept in a standalone app that is totally unaware of Angular. The two will communicate via Angular services that are able to send messages to the core application.
The standalone app will most likely use requirejs to handle dependency injection.
What I'm unsure of is how to get a module that may be declared something like this:
define('AppInteractor', ['require'], function(requre){
// Set up interactor functionality
});
Into an Angular service.
My first though was to have some kind of adapter like this:
define(['AppInteractor', 'angular'], function(interactor, angular) {
var app = angular.module('appInteractor', []).service('AppInteractor', interactor);
});
This would register the AppInteractor as a service within an angular module, the problem with this approach seems to be that because requirejs loads things asynchronously the service hasn't been set when the angular code runs. It also seems to end up with angular loading twice which presumably also doesn't help matters.
I've seen a few articles covering loading all Angular components via require but I was hoping there might be simpler way to make this work.
Can anyone recommend how I might make this work?
If you are going to add a service after the main modules initialization, I recommend you add it to your application module
define(['AppInteractor', 'angular'], function(interactor, angular) {
// There is no second parameter, because we are getting an existing
// module, not creating a new one.
var app = angular.module('appModule');
app.service('AppInteractor', interactor);
});
Otherwise, if you want to group all your other logic in a different module, you will need to import the module and add it as a requirement of your application module.
define(['AppInteractorModule', 'angular'], function(interactorModule, angular) {
var app = angular.module('appModule', [interactorModule.name]);
});
I also recommend you use a tool like ES6 (6to5, traceur), browserify or Typescript for your module management, and then compile to AMD. I find it easier and cleaner for development.

Angular services and browserify

I am using AngularJS for a SPA, and I am using browserify to build my application. Now the question came up whether we should write Angular services in the classical way, or simply require them.
As Angular services are singletons, this could be easily done with require as well: Simply expose an object literal, and you're done. Factories are also possible, simply expose a function. And so on ...
The only disadvantage I can currently think of is that I am not able to access other real Angular services from such a file (like, e.g., $http), but with browserify in the background this does not seem to be that important. E.g., you could easily use Node.js's http module for that, thanks to browserify.
So what do you think of this? What are other advantages and disadvantages for this?
PS: Please note that I'm not asking for whether this is good or bad, as this is probably mainly subjective. I'm rather interested which opportunities appear, or which risks I have to deal with.
One disadvantage to doing this is writing unit tests. It will be difficult to mock your dependencies if you are simply requiring them rather than using Angular's dependency injection.
This is somewhat of a dealbreaker for me because one of the many benefits of using Angular is the testability of the framework.
It's bad.
Just use browserify to initially load in all the modules you need.
you miss out on $httpBackend
your code becomes harder to follow, ie, there is very rarely a point to reuse that directives controller
you miss out on $http interceptors
you miss it in being able to modify and interact with other injectables.
The only thing I'd use browserify/webpack/requirejs for in an angular app is two things:
creating js bundle
injecting templates as strings into the angular template cache as a module.
Personally this kind of approach is just a pointless complication.
If you require things like $http you won't have any way to inject dummy/mocks of those services during testing.
Although somewhere you will do the wiring between your super-duper service that needs $http and the place you need it.
The first thing that came into my mind is resolvers in routes. You can even have some helper methods to deal with declaring the same dependencies many times.
Imagine this module:
function SuperResource($http, pathExpression) {}
exports.SuperResource = SuperResource;
exports.superResourceFactory = function(pathExpression) {
return [
'$http',
function() {
return new SuperResource($http, pathExpression);
}];
};
Somewhere you will do:
var myModule = require('./myModule.js');
resolvers: {
usersResource: myModule.superResourceFactory('/users')
}
Or even you could have a user modules that defines the user resource:
var myModule = require('./myModule');
exports.userFactory = ['$http', function() {
return new myModule.SuperResource($http, pathExpression);
}
Yes, these are angular specific helpers in an otherwise angular free code, but at least they're isolated in their own method/name.

Injecting additional mvc logic into ext js app

I'm new to ext js, but went through the getting started guide and have managed to create my own app.
Now I'm building a plugin for an e-commerce system (shopware) and need to dynamically extend an app.
I've managed to add a view by monkey patching an existing controller:
//{extends file="[default]backend/article/controller/main.js"}
//{namespace name=backend/article/view/main}
//{block name="backend/article/controller/main" append}
Ext.define('Shopware.apps.Article.controller.MyApp', {
override: 'Shopware.apps.Article.controller.Main',
openMainWindow: function() {
var me = this,
mainwindow = me.callOverridden();
oldTabCreation = mainwindow.createMainTabPanel;
mainwindow.createMainTabPanel = function() {
mainTab = oldTabCreation.apply(this);
mainTab.add(
Ext.create('Ext.panel.Panel',
{
title: 'Pricify',
layout: 'card'
})
);
return mainTab;
};
return mainwindow;
}
});
//{/block}
This works. I'm not sure, if it's the preferred way, but the View gets loaded at the right place and I'm quite happy (as it costs me several hours).
But there's some way to go.
How would I inject the entire logic here?
My requirements are:
I need a controller, a view and a store/model
Preferably in an own namespace
I want to separate my classes into files.
the file must reside in the plugin folder, not in the original app folder.
I could append code to the app.js file, but as far as I know, I can't attach controllers and views, nor would I know how to autoload the files.
Is there any preferred way of doing so?
EDIT
I'm now building a simple app, that's loaded before and try to inject the controllers that are then available into the app. I'll report back, once I'm ready.
Usually I would do something like this by intercepting controller events (with Ext.ux.Application override) and adding some logic on top of that. Alternatively you could extend existing controller and replace it with your custom one in the whole app, if that's feasible. Otherwise monkey patching could be the only way to extend an existing monolithic application that wasn't written with extensibility in mind.
Also, 4.2 Beta 2 should be available shortly; it includes a whole host of MVC improvements, including something like the override mentioned above. You may want to take a look at it.

Categories