How should I think about my JavaScript application namespaces? - javascript

I'm building an app that has a single global namespace like so:
var myApp = {};
I then have a bunch of different reusable "modules" comprised of models, views and controllers.
//Bar chart module code
org.example.chart.bar.module
org.example.chart.bar.model
org.example.chart.bar.view
org.example.chart.bar.controller
I also have a big dataSource singleton and a dataManager for loading data to the dataSource:
org.example.data.dataSource
org.example.data.dataManager //populates the dataSource with CSV data
And finally translation strings and settings that should be available across the app:
org.example.static.translations
org.example.static.settings
How would you (re-)organize this so that I have easy access to the application level singletons (such as dataSource, dataManager, translations etc.) and can easily instantiate reusable modules that get scoped under the current application instance?
(Would you for example, already from the beginning, use the same namespace for your "classes" and your app? Or would you perhaps make references like so: myApp.translations = org.example.static.translations?)

No we don't namespace. We write modular code and we use module loaders.
Example of a module loader would be require.js or browserify or seajs.
And an example module would be something like:
(function () {
var jQuery = require("jQuery");
var chart = require("chart");
...
define("moduleName", moduleObject);
})();

There is nothing stopping you adding another name to the class. For example.
org.ds = org.example.data.dataSource;
then you can call
org.ds.getDatasource();
instead of
org.example.data.dataSource.getDatasource();
but both will still work.
EDIT: You could also create other simpler functions that call it taking it out of the oo structure
var dataSource = function () { return org.example.data.dataSource.getDatasource(); };

Consider using something like RequireJS for organizing your modules.
Some excellent resources from Addy Osmani :
http://addyosmani.com/largescalejavascript/
http://addyosmani.com/blog/large-scale-jquery/
http://addyosmani.com/resources/essentialjsdesignpatterns/book/

Related

What happens when using "require()" in Node.js?

Sorry if this is a dumb question but I'm new to JavaScript/Node.js. This code below eludes me and I've done a fair bit of research... My questions below are more specifically related to instantiation.
I don't understand this:
var myApp = require('express');
var myCode = myApp();
How I see that it should be for instantiation:
var myApp = new Express();
var myCode = myApp.insideExpress();
How anonymous function expressions are:
var myApp = function();
var myCode = myApp();
If the word "require" acts as a sort of anonymous function expression, then how are things instantiated in the background? This is very important for making proper patterns, no?
My questions are:
What's happening in the background for the first example, is JavaScript/Node.js instantiating/constructing or not at all?
Are people who do this just creating bad patterns? Why should I use this pattern?
If no instantiation, then why not?
Thanks in advance
const myVar = require("someModule") loads a module from the file system, runs the module initialization code and assigns the module exports to your variable. The module loading sub-system maintains a cache so if it was previously loaded, it is not loaded or run again, the module's exports are just retrieved from the cache and assigned to your variable.
So, when you do this:
var myApp = require('express'); // load express module, assigns exports to myApp
var myCode = myApp(); // calls myApp() function and assigns result to myCode
The first line loads the express module and assigns the exports from that module to your myApp variable. In this particular case (it varies from module to module), the exports from the Express module is a function. So, after that first line of code, myApp contains a function which happens to be a factory function for creating new Express app objects.
The second line of code calls that factory function which returns a new Express app object.
A module can export anything it wants. In the case above, it exported a function, but it's also common to export an object that has a whole bunch of properties which you can then access. You can also export a constructor in which case the caller would then use new with the constructor to create a new object from it.
In the Express module, it did not export a constructor (which is why you don't use new with it). Instead, it decided to export a factory function that, when called, creates and returns a new object. This is just a design decision that can go either way depending upon the needs of the module and the whims of the code writer.
I can't really tell what you're asking here with this code:
var myApp = new Express(); // the express module does not export a constructor
var myCode = myApp.insideExpress();
This would work only if Express was a constructor function. The express module itself does not choose to export a constructor function so this is not how you use the express module. It could have been designed this way, but it was not. They simply made a different design decision when designing it.
For this other case you show:
var myApp = function();
var myCode = myApp();
That first line of code doesn't make any sense. Perhaps you meant for it to have a body to the function:
var myApp = function() { some code here };
var myCode = myApp();
In that case, myApp is being assigned a function expression (which is just one of several ways to declare a function). It's similar, though not exactly the same as:
function myApp() { some code here }
If the word "require" acts as a sort of anonymous function expression, then how are things instantiated in the background? This is very important for making proper patterns, no?
require('someModule) loads a module and returns the exports from the module which can be any Javascript data type. It doesn't act as an anonymous function in any way. require() is an actual function and you are just calling it and getting back its return value. Remember that in Javascript, you can return any data type from a function, include return another function (which is what the express module does).
What's happening in the background for the first example, is JavaScript/Node.js instantiating/constructing or not at all?
No instantiating or constructing. It's just loading a module, running its initialization code and return its exports. Some objects are created by the module loading system that are used for its own housekeeping, but the module itself is just initializing itself and then deciding what it wants to export.
Are people who do this just creating bad patterns? Why should I use this pattern?
Modules are highly useful in node.js development and it is considered good design to use proper module design. There are many, many advantages to good module design such as easier code maintenance, easier code testing, easier code reuse, easier code sharing, no need to create globals in order to share code, etc...
If no instantiation, then why not?
A module decides what it wants to export. It can, in its initialization code, create an instance of an object and export it. It can export a factory function that creates an instance of an object when called. It can export a constructor directly that lets the caller use new with it to create an instance of an object. It can export a utility function that just carries out some function and doesn't create any objects. It can export just data. It can export a plain object with multiple properties on it that have all sorts of possible uses. The possibilities are endless and it entirely depends upon what the purpose is of the module and what it wishes to share with the other module that loaded it.
It's just loading a library or a module into your script. It is not instantiating a new object. It's just making the loaded module's functions etc available to your current script. Here is a good writeup that I found,
http://fredkschott.com/post/2014/06/require-and-the-module-system/
I hope that helps answer your question.

Combining Angular Services with NodeJS Modules

Supposing I have a library written in Javascript to be used in a MEAN stack application.
I wish to use my library both from NodeJS and within Angular.
To remain idiomatic I would like the library to appear as a Module inside node and as a Service within Angular.
the only way I can think to do this is to do something like:
var myLibrary = function(){
var myLib = {};
myLib.myFunc1 = function() {
//Do some cool stuff
};
return myLib;
};
if (typeof module !== 'undefined') {
module.exports = myLibrary();
} else{
var app = angular.module('myApp.services', []);
app.factory('myLibrary',myLibrary);
}
This will work, but it has at least two significant limitations:
The namespace is polluted with the variable "myLibrary"
If within the library I want to use other node modules or Angular services then I can't
I would like to know if anyone knows of a better solution, or if I should give up on using Angular services and use one of the libraries that allows client side Node module functionality.
Having done a bit of searching about this looks like the best solution:
https://gist.github.com/sevcsik/9207267

How to create a utils library in angular

I'm pretty new to Angular. Sorry for the basic question but I couldn't find info about how to write a library in Angular the proper way.
The reason is to benefit from Angular modules as well as testability/mocks.
The library
I am transferring my code to Angular but a big part of my code is written based on a library that I've developed over a couple of months. Imagine something like underscore.
So my initial thought was to wrap it in an angular module like:
angular.module('mylib', [])
.factory('map', map)
.factory('reduce', reduce)
.factory('find', find);
function map (...
Each factory function is testable and stuff. And then use it like:
angular.module('app', ['mylib'])
.controller('MainCtrl', ['$scope', 'map', MainCtrl]);
function MainCtrl($scope, map) {
... do stuff with map ...
This is fine for a couple of functions I guess but my library has over 20 functions and it's just too much boilerplate to define every one of them as a factory and then inject them into my controller.
Second solution
Another way is to have just one factory that returns an object. Kinda like this:
angular.module('mylib', [])
.factory('mylib', mylib)
function mylib () {
var exports = {};
exports.map = function (...
exports.reduce = function (...
exports.find = function (...
return exports;
}
And then use it like this:
angular.module('app', ['mylib'])
.controller('MainCtrl', ['$scope', 'mylib', MainCtrl]);
function MainCtrl($scope, mylib) {
... do stuff with mylib.map ...
But...
Is this a good approach? What would a good way to write a utility library in Angular and use it? Readability and maintainability are important but I prefer not to have so much boilerplate code.
If your library functions are as generic as your example, I wouldn't try to define them as Angular modules in the first place. Write a plain JS library. That will result in less useless boilerplate, and as a bonus your library will also be usable in non-Angular apps. Angular plays along nicely with libraries that are unaware of it, for example by not requiring data objects to implement anything extra (think ko.observable, Backbone Model, etc) to be usable with data binding.
Being an Angular module is not a requirement for testability. The only thing I can think of that Angular could do to improve testability in a generic utility library is the dependency injection (e.g. injecting a mock service for "current time" into a time library for deterministic results). If you don't need any of that, take the past of least complication and just write a plain JS library.
If wrapping the library in an Angular module is an absolute requirement (for instance to not pollute the global namespace with a short namespace for it), I would still write the library in plain JS, put it into a more complicated namespace, and then alias it with an Angular module.
lib/handy-utilities-1.0.js
// Or any other descriptive namespace
var handyUtilities = {
map: function() { ... }
};
app/util.js
angular.module("handyUtilities", []).constant("util", handyUtilities);

Using reflection, dynamically load require module

So I have a small requirejs application that needs to create instances of a dynamic list of classes in runtime. Basically, reflection. I've done quite a bit of reading, but I've been finding a lot of references to Typescript, which I'm not using.
The principal idea is that before requirejs is ready, an array is loaded with a list of classes that will be required. This array is given to requirejs after its main entry point and I hope to create an instance for each entry.
I have done some reading of Ben Nadal's blog here http://www.bennadel.com/blog/2320-extending-classes-in-a-modular-javascript-application-architecture-using-requirejs.htm and I like his pattern and think this would work well for some of the modules I plan to dynamically create.
I had a thought that I could do something like this:-
_.each(loader, function(dep) {
require([dep.name]);
});
With loader being the global loaded with the array list. This doesn't create an instance of the dependency though, which is what I want in this case, like so:-
new Carousel('Delboy');
new Carousel('Rodney');
new Carousel('Grandad');
This, in this example, would create an instance of 3 new carousels, each with a name as passed in via the constructor. I think I am missing something in my understanding, help is appreciated.
Each resolved AMD dependency is an AMD module, which means that it's either a singleton object or a function. In the post by Ben Nadel which you referred to, a distinction is made between "definitions" and "instances". A definition is a singleton, and from a definition (function) you can create multiple instances. In Ben's terminology, RequireJS will only give you the definitions, and it is up to you to create the instances.
So, the following should work for what you're trying to do:
define('Carousel', [], function (name) {
this.name = name;
});
var loader = {};
var carousels = ['Delboy','Rodney','Grandad'];
carousels.forEach(function (carouselName) {
require(['Carousel'], function (Carousel) {
loader[carouselName] = new Carousel(carouselName);
});
});

RequireJS - is there any reason to build a wrapper on it?

I have a question related to the way of using the RequireJs.
Our app should grow a lot in the near feature, so the major problem is to prepare a skeleton that would be followed by the developers involved in the project.
we tried this kind of wrapper on RequireJS(trying to enforce the OOP approach):
//each file will contains such a definition
//this file should be located under: appNamespace/Client/Widget.js
//attaching the class definition to the namespace
with ({public : appNamespace.Client})
{
//using a Class defined in the file: appNamespace/DomainModel/DataTable.js
var dt = using('appNamespace.DomainModel.DataTable');
//Class definition
public.Widget = function(iName)
{
//private variable
var dSort = new dt.SortableTable();
this.Draw = function(iRegion)
{
//public method implementation
}
}
}
Or, we could use the natural RequireJS model like structure:
<pre><code>
//this module definition should be located in the file: appNamespace/Client/Widget.js
define('appNamespace/DomainModel/DataTable', function(dt)
{
function Widget(iName)
{
//private variable
var dSort = new dt.SortableTable();
this.Draw = function(iRegion)
{
//public method implementation
}
}
return Widget;
})
I would prefer the first example because:
1. it will enforce developers to write scripts in a more OOP style
2. it looks like the C# or Java notation - so it will allow a faster switching between the back-end code and the client code
3. I really don't like the model structure because it allows to write any style of code. More of that, it's not enough to define your class, you should define the API that this file is exposing - so you can actually define an API that has no relation to what that file contains.
So - why would I use the second example - the natural RequireJS model style?
Is there anything that I miss?
Any suggestion is welcome

Categories

Resources