How do I use backbone.js with namespaces? - javascript

I have been trying to get namespaces to work with backbone.js for the last hour or so.
I have read: How do I declare a namespace in JavaScript?
And I tried all approaches. Here is the problem:
Backbone.Controller wants to be initialized through a constructur ("new keyword"), because otherwise Backbone.history won't be set. This is the code that I'm trying to put into a namespace, for example "Site.Controllers"
var MainController = Backbone.Controller.extend({
routes: {
"help": "help", // #help
},
help: function(){}
});
var ws = new MainController
Whenever I try to put the MainController into some namespace, backbone.js complains that MainController is not a constructor - of course it does, because there doesn't seem to be any way to make a namespace "tree" with constructor functions. If you guys want, I can list all the approaches I tried, but it's exactly the same as from the link provided above. I didn't try putting it into closures, because that is suggested to be very slow.

var namespace = {
MainController: Backbone.Controller.extend({ ... }),
HelpController: Backbone.Controller.extend({ ... }),
...
};
I'm confused as to what your trying to achieve. An almost fail proof method of creating a namespace is :
var namespace = (function() {
...
return {
...
};
})();
Also yes closures are indeed slower. But I would not worry about this unless your creating the closures millions of times.

Related

JS: replace function definition before object instantiation

I have outerView and innerView inside my require.js module. They can be described with few statements:
InnerViews is instantiated on OuterView rendering
InnerView calls calculated method on own instantiation
InnerView.calculate method use AJAX, which is undesirable in unit tests (with jasmine)
I need: in my jasmine tests replace innerView.calculate method call with direct call to innerView.handleResults with hardcoded data argument.
Problem: The problem is also that in tests I have access only to outerView. So I need to replace innerView.calculate method definition before the innerView is instantiated.
Question: How to replace innerView.calculated method definition before innerView is instantiated?
Code:
define(".....", function(...) {
var innerView = Backbone.View.extend ({
initialize: function() {
......
calculate(opitons);
},
//I NEED TO REPLACE THIS WITH handleResults(hardcodedData)
calculate: function(options) {
var $this = this;
Utils.doSmth(options).then(
$this.handleResults
);
},
handleResults: function(data) {
....
}
});
var outerView = Backbone.View.extend ({
subViews: [],
render: function() {
subViews[0] = new innerView();
}
});
return outerView;
}
Keep in mind that the BDD philosophy is to test behavior. Ask yourself, do you really want to change how your functions work in your unit tests? By providing an alternate code path, you aren't testing the actual behavior you'll see in production.
For example, what if in your then function you do more complex data massaging than simply calling handleResults(...)? You then need to bring knowledge of this logic into your unit tests so you can mock out the rest of the chain correctly.
It sounds to me like what you really need is a way of mocking the AJAX request, not a way of changing how your code works. There are several ways to accomplish this. Two of the most popular are:
jasmine-ajax -- jasmine-specific
Sinon.JS -- standalone framework for creating spies, mocks, and mock HTTP servers.
I have used Sinon.JS quite a lot for testing XHR-related code paths to great effect.
That looks like a design problem to me. You have a hard-coded dependency on the innerView type in your outerView, and you are hiding it inside a closure (aka module). Worse, that inner, hard-coded dependency is hooked up to the rest of the universe (AJAX call). You'll have to expose the inner view somehow in order to make it testable.
It seems to me that at the very least, you have to open up your outerView like this:
var outerView = Backbone.View.extend ({
subViews: [],
initialize: function (options) {
this.innerView = innerView;
}
render: function() {
subViews[0] = new this.innerView();
}
});
That way, you can at least modify outerview.innerView in your tests before you call render.
And at that point, it is only a small additional step to actually inject the dependency in initialize, perhaps with a default (this.innerView = options && options.innerView || innerView;), if you ever feel the need.

Problems with circular dependency and OOP in AngularJS

AngularJS + OOP is kinda sexy feature to use
Hi, I'm successfully using OOP with AngularJs for some time already (first started with angularjs with oop inheritance in action), the provided approach allows you define your classes as angular services, which you can later extend or inherit from like that:
Application.factory('AbstractObject', [function () {
var AbstractObject = Class.extend({
virtualMethod: function() {
alert("Hello world");
},
abstractMethod: function() { // You may omit abstract definitions, but they make your interface more readable
throw new Error("Pure abstract call");
}
});
return AbstractObject; // You return class definition instead of it's instance
}]);
Application.factory('DerivedObject', ['AbstractObject', function (AbstractObject) {
var DerivedObject = AbstractObject.extend({
virtualMethod: function() { // Shows two alerts: `Hey!` and `Hello world`
alert("Hey!");
this._super();
},
abstractMethod: function() {
alert("Now I'm not abstract");
}
});
return DerivedObject;
}]);
Plunker: http://plnkr.co/edit/rAtVGAsNYggBhNADMeoT
using the described approach gives you the ability to define classes that beautifully integrate into angular infrastructure. You get all sort of nifty features from two worlds - OOP and AngularJs. Dependency injection is free for your classes, and it makes your classes simple, allows putting a lot of boilerplate controller code into some base class that can be later reused.
However
AngularJs infrastructure blocks previously described approach from spreading it's wings on all 100%. The problem occurs when you try to define recursive class definitions (i.e. recursive aggregation), say you have two class definitions like Blog and Tag
Application.factory('Blog', ['Tag', function (Tag) {
var Blog = Class.extend({
tags: function() {
return this.tags;
}
});
return Blog;
}]);
Application.factory('Tag', ['Blog', function (Blog) {
var Tag = Class.extend({
Blogs: function() {
return this.blogs;
}
});
return Tag;
}]);
It won't work because both Blog and Tag are self-referencing themselves causing circular dependency.
P.S
The last thing, I have found kinda ugly solution that solves my problem in my specific case but doesn't work in general and as I said, it isn't pretty:
Application.factory('BlogNamespace', [function () {
var Blog = Class.extend({
tags: function() {
return this.tags;
}
});
var Tag = Class.extend({
Blogs: function() {
return this.blogs;
}
});
return {
Tag: Tag,
Blog: Blog
};
}]);
Question
The above fix won't work because namespaces may also be a subject of circular dependency. This means that it isn't solution to described problem but rather one level deeper problem now.
Any suggestions on how it is possible to solve described problem in general case?
A circular dependency is always the sign of mixing of concerns, which is a really bad thing. Miško Hevery, one of the authors of AngularJS, explains a nice solution on his awesome blog. In short, you probably have a third service hidden somewhere, which is the only part of your code really needed by the two others.
I'm answering my own question just because I've found a technical way of resolving the issue that I have originally posted about. But before that, I strongly encourage you to use Blackhole's suggestion since it allows solving a broader set of problems which are usually caused by bad architecture. Please prefer using his approach first, and return to current one in case that you know what you are doing.
So here goes:
You can use $injector service and inject required definitions at run-time, which is legal from technical point of view, but again according to this post (hard to imagine that it is written in 2008), this is like a black magic, do that and it will strike you back:
Application.factory('Blog', ['$injector', function ($injector) {
var Tag = $injector.get('Tag'); // Here is your tag
...
}]);
Application.factory('Tag', ['Blog', function (Blog) {
...
}]);
Edit
It turned out that current approach is an example of Service Locator pattern, which is IoC Antipattern.
LAST RESORT: NOT ENCOURAGED
In my case the best way to get around a circular-dependency-problem like this in angular, is to trigger function-calls via $rootScope-broadcasts. The other service can then listen to this broadcast and react with the desired function-call. It may not be the most elegant solution but in some cases where the interaction between the services is mainly one-directional anyways, it may be a reasonable alternative. (note that this also allows return-values to be passed back to the broadcasting function via callbacks only)
A pseudo-example of this would be:
angular.module('myApp').factory('service1', ["$rootScope",
function($rootScope) {
function func1() {
// do something
}
$rootScope.$broadcast("callFunc2"); // calls func2 from service 1
return {
func1: func1
}
}
]);
angular.module('myApp').factory('service2', ["service1", "$rootScope",
function(service1, $rootScope) {
function func2() {
// do something
}
service1.func1(); // calls func1 from service 2
$rootScope.on("callFunc2", func2);
}
]);

Where to add Global variables in ExtJS MVC?

I am wondering where to add global variables for an ExtJS Application. I already looked at some suggestions in stackoverflow that mention that you can add them inside app.js. But, can anyone be more specific? My app.js looks something like this:
Ext.application({
launch: function() {..}
});
So, where exactly do the variables go? In the launch function? Outside Ext.application?
Better approach would be to create a separate class to hold such global constants. Then you should just put that constants class as requires in app.js.
Ext.define("App.Constants", {
singleton : true,
BASE_URL : "http://localhost:8080/",
LABLE_HEADER : "geekrai.blogspot",
TIMEOUT : 6000
});
This will ensure that class is loaded and now you can access any property/global value.
I have mentioned the same in detail on my blog : link
Declare your own object namespace and add them there:
Ext.ns('My.Application.Globals');
My.Application.Globals.SomeValue = 5;
My.Application.Globals.SomeText = 'Hello World!';
However globals are usually frowned upon unless absolutely needed, so try and get around using them if you can.
I know you already accepted an answer which is fine. I just wanted to add an MVC way to include namespaced variables available to the app. There is one caveat to these 'globals' - you can not use them in your class definitions. Meaning you can not reference your app in Ext.define({}) methods. They have to be use in initComponent method or later.
So here is what I do:
Ext.application({
name:'MyApp',
appFolder:'js/app',
controllers:[ 'Main' ],
autoCreateViewport : true,
launch:function () {
console.log("App Launched!");
MyApp.app = this; //added this to get reference to app instance. IMPORTANT!
},
//variables used throughout the app
globals:{
myURL:'http://example.com',
magicNum:5
}
});
To use these application wide variables you reference your app namespace and so do not pollute the global space. Like this:
MyApp.app.gloabals.magicNum
Aside from whatever features may be built into Ext, you can always use an immediate function to create a closure:
(function(){
var globalVariable = 'foo';
Ext.application({
launch: function() { alert(globalVariable); }
});
})();

Aliasing a function object in JavaScript

Disclaimer: I am using ExtJS 3, but I don't think it's very relevant to the question, outside of the common use of it's namespacing function.
I have a singleton that's declared in a really long namespace like this:
Ext.ns("REALLY.REALLY.LONG.NAMESPACE");
var Singleton = (function() {
var foo = {
bar: "baz"
};
var privateFunction = function(param){
// ...
return foo;
};
var single = Ext.extend(Object, {
constructor: function(config) {
Ext.apply(this, config);
},
otherFunction: privateFunction,
publicFunction: function (someObject){
// do stuff with someObject
}
});
return single;
})();
// Make it a singleton
REALLY.REALLY.LONG.NAMESPACE.Singleton = new Singleton();
I use it in other modules via calls like REALLY.REALLY.LONG.NAMESPACE.Singleton.otherFunction(); and REALLY.REALLY.LONG.NAMESPACE.Singleton.publicFunction(myObject); . I'm wondering if I can swap out those calls by setting up the client module with an alias to the singleton, i.e. var singleton = REALLY.REALLY.LONG.NAMESPACE.Singleton; , so that I can call singleton.otherFunction();. I'm wondering if this is an anti-pattern , or if there are any pitfalls (memory?) I might run into through this usage.
Thanks StackOverflow!
I'm wondering if I can swap out those calls by setting up the client module with an alias to the singleton
Yes, you can.
I'm wondering if this is an anti-pattern , or if there are any pitfalls (memory?) I might run into through this usage.
No, there aren't any that I can think of and it is faster than calling the fully-qualified version.
Local Alias Pattern
Example:
function somefunc(){
var singleton = REALLY.REALLY.LONG.NAMESPACE.Singleton;
singleton.publicFunction();
};
Or:
(function somfunc(singleton){
}(REALLY.REALLY.LONG.NAMESPACE.Singleton));
Test Results:
http://jsfiddle.net/jMg9A/
There is no issue with creating a reference to the original "object". In many cases we create a namespace to organize our code, but of course, this can lead to really long namespaces that we really don't wish to reference later, thus creating a local reference to that namespace is an excellent idea so that you can change it in one place instead of various places.
I don't really see an ant-pattern here, instead I see an opportunity to make it simpler for yourself and probably a little more manageable from a developer standpoint.

What is meant by “leaking” into global scope?

A while ago, I offered-up a JavaScript design pattern (the Module Pattern - see below) that I got from a John Resig example as part of a solution to someone’s question and I received the following comment:
“…that pattern is a bit over
engineered and not that good. Still
leaking into global-scope. and your
not opening yourself to async loaders.
But it is better then just ad-hoc
coding !”
So…
If “leaking” into global scope means “your object gets appended to the browsers window (object)”…then everything already gets appended (globally):
This “leaks” into global scope:
window.jQuery
…just call: window.jQuery and it resolves as a function();
This “leaks” into global scope:
function HelloWorld() { alert(‘Howdy’); }
…just call: window.HelloWorld() and you will get ‘Howdy’.
This “leaks” into global scope:
var myVariable = 10;
…just call: window.myVariable and you will get 10
If the commenter is correct, then all the above “leak” into global-scope. So, personally, I don’t see a way NOT to “leak” into global-scope as even your form controls exists there (as well).
As such, here are my questions…
What is meant by “leaking” into
global-scope?
Why is that bad?
How do you avoid it?
When wanting to create persistent
custom-objects, why is the Module
Pattern (below) bad?
Design patterns let you encapsulate
complex logic, is encapsulation
suddenly bad simply because we’re
writing in JavaScript?
Or...is this commenter simply wrong?
Here is the Module Pattern I Mentioned Above:
<script type="text/javascript">
var myNamespace = (function($) {
var publicInstances = {};
// ***********************
// myObject
publicInstances.myObject = myObject;
function myObject() {
/// <summary>A pointer to this</summary>
var self = this;
this.someProperty = new String();
this.initialize = function() {
/// your code here
}
this.someMethod = function() {
/// your code here
}
self.initialize();
}
return publicInstances;
})(jQuery);
jQuery(document).ready(function() {
// Use would look like
var myInstance = new myNamespace.myObject();
});
</script>
UPDATED:
I’m satisfied with the answers below and want to thank everyone for taking the time to comment.
TO RECAP THE ANSWERS BELOW:
"Leaking" into global-scope occurs when something used in local-scope is unintentionally made available to the global-scope (e.g. the window object). This is bad because it opens the page to potential naming collisions which could result in variables resolving to unexpected values or types.
Intentionally making a variable global is not considered a "leak". However, properly namespacing the object is required to reduce potential for said naming collisions.
You cannot avoid globally-scoped variables, but you can reduce the above risks by using asynchronous-loaders and defining-modules made available in plug-ins like RequireJS or Curl.
"Leaking" into global scope is when something used in a local scope is unintentionally made available to the global scope. That means assigning to a variable not already defined in the current scope:
function myFunction() {
a=1;
}
myFunction();
alert(a);
//-> 1
It's bad because there could be naming collisions resulting in variables with different values/types than expected. It can also lead to a bug in older Internet Explorers when you forget to use the var keyword for a variable used in a for statement.
I wouldn't class intentionally making a variable global as "leaking", because it's more like you're "pouring" it into the global scope. However, this is still often considered bad practice by some (although I think that's a little melodramatic) because there are still potential naming collisions with current properties of the window object, or variables set by other scripts and libraries.
[[Short story]]
Don't make global variables ever and use an async module loader like requirejs or curl
[[Long story]]
That comment was poorly structured.
There is nothing wrong with the module system. I was complaining about using global variables at all. (I still think the full generic module pattern is bloated).
Whether you should avoid all global variables is a different question and I think a matter of style. You can either use an async loader to pass modules around or using window to pass modules around.
What is meant by “leaking” into global-scope?
What I meant was your creating global variables. Minimising the use of global variables is a pattern. In functional style programming it's possible to have zero global variables but this is a different pattern from using global modules.
Why is that bad?
Having any state globally can cause that state to be corrupted.
How do you avoid it?
You can't. You can minimize the amount of global variables though. To avoid having global state completely you can use asynchronous loaders. These define a few global variables for you that you can then use.
When wanting to create persistent custom-objects, why is the Module Pattern (below) bad?
There is nothing wrong with the module pattern. The problem is storing your module globally. The issue is having global namespaces.
Design patterns let you encapsulate complex logic, is encapsulation suddenly bad simply because we’re writing in JavaScript?
Now that I've cleared up the intent of the comment this question isn't really relevant
Or...is this commenter simply wrong?
The comment was poorly phrased at best. I objected to global namespaces rather than modules, but did not state this properly.
The alternative is using asynchronous loaders and defining modules. These can be narrowed down to two global variables. define and require.
require = function(moduleName, callback)
This will get a module and then return it to you.
define = function(obj)
this defines a module.
The concept here is that you multi file code as follows:
// main.js
require([
"foo.js",
"bar.js",
...,
], function(foo, bar, ...) {
// do stuff
});
//foo.js
(function() {
var namespace = modulePatternCode;
...
define(namespace):
})();
//bar.js
(function() {
var namespace = modulePatternCode;
...
define(namespace):
})();
Your module only "leaks" it's namespace holder so it's pretty acceptable.
Loader example using RequireJS:
Define a utilities module in utils.js:
define(function () {
return {
each: function (iterable, callback) {
// ...
},
map: function (iterable, mapper) {
// ...
}
};
});
Use the above module in another module, say math.js:
define([ "utils" ], function (utils) {
return {
sum: function (numbers) {
var sum = 0;
utils.each(numbers, function (n) {
sum += n;
});
return sum;
},
average: function (numbers) {
return this.sum(numbers) / numbers.length;
}
};
});
And you can use math.js in another file, say main.js:
console.log("About to add 1-3");
require([ "math" ], function (math) {
console.log(math.sum([ 1, 2, 3 ]));
});
You can still have namespaces, and still keep them warm and cozy inside modules:
namespace.js:
define([ "foo", "bar", "moo" ] function (foo, bar, moo) {
return {
foo: foo,
bar: bar,
moo: moo
};
});
Then the rest of the modules can use this namespace during definition:
define([ "namespace" ], function (namespace) {
namespace.foo(42);
});
Or at runtime, in some other module:
define(function () {
return {
initialize: function () {
require([ "namespace" ], function (namespace) {
namespace.foo(42);
});
}
};
});
In the usages above, nothing but define and require are global. Of course, these are just illustrative examples, as there are many different flavors of defining/using modules in RequireJS.

Categories

Resources