How much can I stretch RequireJS to provide dependency injection for my app? As an example, let's say I have a model that I want to be a singleton. Not a singleton in a self-enforcing getInstance()-type singleton, but a context-enforced singleton (one instance per "context"). I'd like to do something like...
require(['mymodel'], function(mymodel) {
...
}
And have mymodel be an instance of the MyModel class. If I were to do this in multiple modules, I would want mymodel to be the same, shared instance.
I have successfully made this work by making the mymodel module like this:
define(function() {
var MyModel = function() {
this.value = 10;
}
return new MyModel();
});
Is this type of usage expected and common or am I abusing RequireJS? Is there a more appropriate way I can perform dependency injection with RequireJS? Thanks for your help. Still trying to grasp this.
This is not actually dependency injection, but instead service location: your other modules request a "class" by a string "key," and get back an instance of it that the "service locator" (in this case RequireJS) has been wired to provide for them.
Dependency injection would involve returning the MyModel constructor, i.e. return MyModel, then in a central composition root injecting an instance of MyModel into other instances. I've put together a sample of how this works here: https://gist.github.com/1274607 (also quoted below)
This way the composition root determines whether to hand out a single instance of MyModel (i.e. make it singleton scoped) or new ones for each class that requires it (instance scoped), or something in between. That logic belongs neither in the definition of MyModel, nor in the classes that ask for an instance of it.
(Side note: although I haven't used it, wire.js is a full-fledged dependency injection container for JavaScript that looks pretty cool.)
You are not necessarily abusing RequireJS by using it as you do, although what you are doing seems a bit roundabout, i.e. declaring a class than returning a new instance of it. Why not just do the following?
define(function () {
var value = 10;
return {
doStuff: function () {
alert(value);
}
};
});
The analogy you might be missing is that modules are equivalent to "namespaces" in most other languages, albeit namespaces you can attach functions and values to. (So more like Python than Java or C#.) They are not equivalent to classes, although as you have shown you can make a module's exports equal to those of a given class instance.
So you can create singletons by attaching functions and values directly to the module, but this is kind of like creating a singleton by using a static class: it is highly inflexible and generally not best practice. However, most people do treat their modules as "static classes," because properly architecting a system for dependency injection requires a lot of thought from the outset that is not really the norm in JavaScript.
Here's https://gist.github.com/1274607 inline:
// EntryPoint.js
define(function () {
return function EntryPoint(model1, model2) {
// stuff
};
});
// Model1.js
define(function () {
return function Model1() {
// stuff
};
});
// Model2.js
define(function () {
return function Model2(helper) {
// stuff
};
});
// Helper.js
define(function () {
return function Helper() {
// stuff
};
});
// composition root, probably your main module
define(function (require) {
var EntryPoint = require("./EntryPoint");
var Model1 = require("./Model1");
var Model2 = require("./Model2");
var Helper = require("./Helper");
var entryPoint = new EntryPoint(new Model1(), new Model2(new Helper()));
entryPoint.start();
});
If you're serious about DI / IOC, you might be interested in wire.js: https://github.com/cujojs/wire
We use a combination of service relocation (like Domenic describes, but using curl.js instead of RequireJS) and DI (using wire.js). Service relocation comes in very handy when using mock objects in test harnesses. DI seems the best choice for most other use cases.
Not a singleton in a self-enforcing getInstance()-type singleton, but
a context-enforced singleton (one instance per "context").
I would recommend it only for static objects. It's perfectly fine to have a static object as a module that you load using in the require/define blocks. You then create a class with only static properties and functions. You then have the equivalent of the Math Object that has constants like PI, E, SQRT and functions like round(), random(), max(), min(). Great for creating Utility classes that can be injected at any time.
Instead of this:
define(function() {
var MyModel = function() {
this.value = 10;
}
return new MyModel();
});
Which creates an instance, use the pattern for a static object (one where values are always the same as the Object never gets to be instantiated):
define(function() {
return {
value: 10
};
});
or
define(function() {
var CONSTANT = 10;
return {
value: CONSTANT
};
});
If you want to pass an instance (the result of using a Module that have return new MyModel();), then, within an initialize function, pass a variable that capture the current state / context or pass on the Object that contains information on state / context that your modules needs to know about.
Related
I wanted to know if its good practice to use it like following since I used a global field cacheObj
I need to parse the data and share it between other modules,any module can take any property but only the first module which called to this parser is responsible to provide the data to parse(I need to do this parse just once and share properties in different modules)
This code is from other SO post and I want to use it
var Parser = require('myParser'),
_ = require('lodash');
var cacheObj; // <-- singleton, will hold value and will not be reinitialized on myParser function call
function myParser(data) {
if (!(this instanceof myParser)) return new myParser(data);
if (!_.isEmpty(cacheObj)) {
this.parsedData = cacheObj;
} else {
this.parsedData = Parser.parse(data);
cacheObj = this.parsedData;
}
}
myParser.prototype = {
//remove `this.cacheObj`
getPropOne: function () {
return this.parsedData.propOne;
},
getPropTwo: function () {
return this.parsedData.propTwo;
}
};
module.exports = myParser;
It kindda looks like the Context Object pattern, which is used for maintaining state and for sharing information. Some consider it a bad practice and prefer Singleton when it comes to share the object between layers, but if suites your case (in the same module) - my advice is to use it.
UPDATE
The main reason why you shouldn't use ContextObject through your layes is because it binds all sub-systems together( one object is referencing everything else). While Singleton is not just for creating objects, it is also services as access point that can be loaded by the corresponding sub-system. Having a Singleton represent every service access point allows for seamless vertical integration of cooperating components/modules. Simple code example:
Singleton:
// returns the "global" time
var time = Clock.getInstance().getTime();
Context object:
// allows different timezones to coexist within one application
var time = context.getTimezoneOffset().getTime();
I am building an application using Durandal and I have the need to share some functionality across view models.
I have 5 screens to build and they are all virtually the same screen except that in the activate function they will call to a different api end points but otherwise the view and view models will be identical.
Is there a pattern that I should be following to structure this correctly to promote code reuse?
If the views and the view models are identical except for calling different api actions, what about just taking in a parameter as part of the route? Then in the activate function, you can switch on the parameter. The route values can be designated so that your url is relevant, like [http://site/page/subtype], where subtype is the parameter (instead of using numeric values)
Regarding inheritance, depending on the features you need, there's so many ways to do JavaScript inheritance it can be a little confusing. There are some full-featured inheritance models provided by libraries such as base2 and Prototype. John Resig also has an inheritance model that I've used successfully.
In general, I prefer to stick to simpler solutions when it comes to JS inheritance. If you need a pretty much the full set of inheritance features, those libraries are good to consider. If you only really care about accessing a set of properties and functions from a base class, you might be able to get by with just defining the view model as a function, and replacing the function's prototype with the desired base class. Refer to Mozilla's Developer Docs for good info on inheritance.
Here's a sample:
//viewModelBase
define(function (require) {
"use strict";
function _ctor() {
var baseProperty = "Hello from base";
function baseFunction() {
console.log("Hello from base function");
}
//exports
this.baseProperty = baseProperty;
this.baseFunction = baseFunction;
};
//return an instance of the view model (singleton)
return new _ctor();
});
//view model that inherits from viewModelBase
define(function (require) {
"use strict";
function _ctor() {
var property1 = "my property value";
function activate() {
//add start up logic here, and return true, false, or a promise()
return true;
}
//exports
this.activate = activate;
this.property1 = property1;
};
//set the "base"
var _base = require("viewModelBase");
_ctor.prototype = _base;
_ctor.prototype.constructor = _ctor;
//return an instance of the view model (singleton)
return new _ctor();
});
Keep in mind this example all results in what effectively is a singleton (i.e. you'll only get the same instance, no matter how many times you require() it)
If you want a transient (non-singleton) just return _ctor. Then you'll need to instantiate a new instance after you require() it.
One more note, in general, functions should be defined on the prototype, not within the constructor function itself. See this link for more information on why. Because this example results in only a single instance, it's a moot point, so the functions are inside the constructor for improved readability and also the ability to access the private vars and functions.
I've been hoping to use inheritance in Meteor, but I couldn't find anything about it in the documentation or on Stack Overflow.
Is it possible to have templates inheriting properties and methods from another abstract template, or class?
I think the short answer is no, but here's a longer answer:
One thing I've done to share functionality among templates is to define an object of helpers, and then assign it to multiple templates, like so:
var helpers = {
displayName: function() {
return Meteor.user().profile.name;
},
};
Template.header.helpers(helpers);
Template.content.helpers(helpers);
var events = {
'click #me': function(event, template) {
// handle event
},
'click #you': function(event, template) {
// handle event
},
};
Template.header.events(events);
Template.content.events(events);
It's not inheritance, exactly, but it does enable you to share functionality between templates.
If you want all templates to have access to a helper, you can define a global helper like so (see https://github.com/meteor/meteor/wiki/Handlebars):
Handlebars.registerHelper('displayName',function(){return Meteor.user().profile.name;});
I've answered this question here. While the solution doesn't use inheritance, it allow you to share events and helpers across templates with ease.
In a nutshell, I define an extendTemplate function which takes in a template and an object with helpers and events as arguments:
extendTemplate = (template, mixin) ->
helpers = ({name, method} for name, method of mixin when name isnt "events")
template[obj.name] = obj.method for obj in helpers
if mixin.events?
template.events?.call(template, mixin.events)
template
For more details and an example see my other answer.
Recently, I needed the same functionality in my app so I've decided to create my own package that will do that job out of the box. Although it's still work in progress, you can give it a go.
Basically, the entire method is as follows:
// Defines new method /extend
Template.prototype.copyAs = function (newTemplateName) {
var self = this;
// Creating new mirror template
// Copying old template render method to keep its template
var newTemplate = Template.__define__(newTemplateName, self.__render);
newTemplate.__initView = self.__initView;
// Copying helpers
for (var h in self) {
if (self.hasOwnProperty(h) && (h.slice(0, 2) !== "__")) {
newTemplate[h] = self[h];
}
}
// Copying events
newTemplate.__eventMaps = self.__eventMaps;
// Assignment
Template[newTemplateName] = newTemplate;
};
In your new template (new_template.js) in which you want to extend your abstract one, write following:
// this copies your abstract template to your new one
Template.<your_abstract_template_name>.copyAs('<your_new_template_name>');
Now, you can simply either overwrite your helpers or events (in my case it's photos helper), by doing following:
Template.<your_new_template_name>.photos = function () {
return [];
};
Your will refer to overwritten helper methods and to abstract ones that are not overwritten.
Note that HTML file for new template is not necessary as we refer to abstract one all the time.
Source code is available on Github here!
Could someone explain the fundamental difference between:
define(['backbone'], function(Backbone) {
MyModel = Backbone.Model.extend({
});
});
define(['backbone', 'models/mymodel'], function(Backbone){
var app = Backbone.View.extend({
initialize: function() {
var model = new MyModel();
}
});
});
and:
define(['backbone'], function(Backbone) {
var MyModel = Backbone.Model.extend({
});
return MyModel;
});
define(['backbone', 'models/mymodel'], function(Backbone, MyModel){
var app = Backbone.View.extend({
initialize: function() {
var model = new MyModel();
}
});
});
In the former, the first module simply defines MyModel. In the latter, it's created as a variable and returned, and the second module needs to have it put in the parameters when imported.
RequireJS examples I see around seem to vary between the two, but I don't really understand the difference - does one return an instance and the other a constructor?
In my application I didn't even notice that I was actually using both ways in different places, and I think it was causing problems. I was using a lot of
self = this
self.model.doSomething
inside my views and models, and as my app got bigger, I started getting errors because there were conflicts with definitions of self.
Short Version: 1st version == wrong.
Medium Version: The first one bypasses Require entirely by using global variables, while the second one actually uses Require.
Long version:
The way Backbone modules work is that you run "define", pass it a function (and usually an array of dependencies also), and whatever gets returned from that function is defined as that module. So if I do:
// Inside foo.js
define([], function() {
return 1;
});
I've defined the "foo" module to be 1, so if elsewhere I do:
define(['foo'], function(foo) {
alert(foo); // alerts 1
});
Your first version doesn't return anything, so it's not actually creating a Require module at all.
How does it work then? Well, in that version you do:
MyModel = Backbone.Model.extend({
NOT:
var MyModel = Backbone.Model.extend({
So that's really the same as doing:
window.MyModel = Backbone.Model.extend({
Then when the second part of the code runs, it access window.MyModel, and works ... but it's completely bypassing Require.js in the process.
I think the most important thing to takeaway is: ALWAYS DECLARE (ie. var) YOUR JAVASCRIPT VARIABLES. I don't agree with everything Crockford says, but he's dead right on this one. You will get lots of bugs (with Require and without) if you don't make this a habit.
Beyond that, the next most important thing is probably: ALWAYS RETURN SOMETHING FROM THE FUNCTION YOU PASS TO define. There are certain special cases where you don't want to return anything, but unless you are deliberately trying to solve one of those cases you should always return something to define the module.
Finally, if you're using Require, every variable in your code should either:
Come from the define function (ie. it should be an argument variable from the function that you pass to define), or
It should be declared (ie. var-ed ) inside that file
If you use JSLint or 'use strict'; (as Valentin Nemcev suggested), or if you use an editor like Eclipse, your tools can help you ensure this (and in fact make it easy to ensure).
MyModel = Backbone.Model.extend({});
Here you are not returning a constructor, you are defining a global variable and accessing it later in different module.
Actually it is wrong, it works by accident. You should return your modules from define and access them via parameters in other modules.
Like this:
return Backbone.Model.extend({});
You should use strict mode to avoid problems with global variables in JS.
Also, constructor in JS is just a function that is meant to be run with new. Backbone extend always returns a constructor function, and you create a model instance by calling the constructor with new, like you are doing in both examples.
So I'm writing a whole bunch of vendor-specific files in node which all have a similar controller pattern, so it makes sense for me to cut them out and put into a common file.
You can see my common controller file here: https://gist.github.com/081a04073656bf28f46b
Now when I use them in my multiple modules, each consecutively loaded module is overwriting the first. This is because the file is only required once and passed dynamically through to each module on load (this allows me to add extra modules and these modules are able to add their own routes, for example). You can see an example module here: https://gist.github.com/2382bf93298e0fc58599
You can see here on line 53 I've realised that we need to create a seperate instance every time, so I've tried to create a new instance by copying the standardControllers object into a new object, then initialising the new object. This has zero impact on the code, and the code behaves in exactly the same way.
Any ideas guys? I'm in a bit of a jam with this one!
First thing I'd do is try to make things simpler and reduce coupling by invoking the single responsibility principle, et al.
http://www.codinghorror.com/blog/2007/03/curlys-law-do-one-thing.html
Put those Schemas into their own files, eg
models/client.js
models/assistant.js
models/contact.js
I've also found that embedded docs + mongoose is generally a PITA. I'd probably promote all those to top level docs.
You don't need to enclose your object's keys in quotes.
routes = {
list: function() {} // no quotes is aok
}
Also 'list' in typical REST apps is called 'index'. Anyway.
Ok, I'd break this up differently. Since you're requiring stuff from the index.js file in the middleware, they become tightly coupled, which is bad. in fact, I think I'd rewrite this whole thing so it was tidier. Sorry.
I'd probably replace your 'middleware' file with an express-resource controller
https://github.com/visionmedia/express-resource (built by author of express). This is a good framework for restful controllers, such as what you're building. The auto-loader is really sweet.
You may also want to look at: http://mcavage.github.com/node-restify/ It's new, I haven't tried it out, but I've heard good things.
Since what you're building is basically an automated mongoose-crud system, with optional overriding, I'd create an express-resource controller as your base
/controllers/base_controller.js
and it might look like
var BaseController = function() {} // BaseController constructor
BaseController.prototype.index = function() {
// copy from your middleware
}
BaseController.prototype.show = function() {
// copy from your middleware
}
BaseController.prototype.create = function() {
// copy from your middleware
}
// etc
module.exports = BaseController
Then I'd do something like:
/controllers/some_resource_controller.js
which might look something like:
var BaseController = require('./base_controller')
var NewResourceController = function() {
// Apply BaseController constructor (i.e. call super())
BaseController.apply(this, arguments)
}
NewResourceController.prototype = new Base()
NewResourceController.prototype.create = function() {
// custom create method goes here
}
module.exports = NewResourceController
Then to use it, you can do:
var user = app.resource(myResourceName, new ResourceController());
…inside some loop which sets myResourceName to be whatever crud you're trying to set up.
Here's some links for you to read:
http://tobyho.com/2011/11/11/js-object-inheritance/
http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/
Also, it sounds like you're not writing tests. Write tests.
http://www.codinghorror.com/blog/2006/07/i-pity-the-fool-who-doesnt-write-unit-tests.html