namespacing a JavaScript class but retaining the same 'this' - javascript

I'm building a fairly large node.js client library and I'd like to be able to 'namespace' portions of it to keep it more organized. For example:
var client = new Client(config);
client.activities.get(activityId, function(activity) {
...
});
...
client.user.get(userId, function(user) {
...
});
I'm currently trying to do something like this in the module:
function Client(config) {
this.config = config;
}
Client.prototype.activities = require('./activities');
Client.prototype.user = require('./user');
module.exports = Client;
but when 'get' is called in the activities 'submodule', the "this" is for the module, of course, and not the outer Client function. Basically, both of the submodules need access to the outer configuration information ('config' in this example). What is the best practice around doing this in node.js?

I think a modeling issue with the plan you have is that new X() copies each property reference of X.prototype to the new item; for instance, X.myFunction is the exact same reference as X.prototype.myFunction; but does NOT create a new copy of myFunction.
It sounds like if activities is a part of a Client (the same way StreetAddress might be), you actually want activities to be a Class, not a module, and for Client to create a new instance of it when it's constructed. That's not really something that prototype is useful for. If I'm wrong, maybe you could show an example of a basic operation activities would be used for.

Related

Allow modules access to functions/variables defined in server that requires them?

Here's a basic example of what I'm trying to do:
ModuleA.js
module.exports = {
doX () {
console.log(data['a']);
}
}
ModuleB.js
module.exports = {
doX () {
console.log(data['b']);
}
}
server.js
let data = { a:'foo', b:'bar' };
let doX = {};
doX['a'] = require('./ModuleA.js').doX;
doX['b'] = require('./ModuleB.js').doX;
doX['a'](); // Should print 'foo'
doX['b'](); // Should print 'bar'
In the actual implementation there would be many more variables to pass in than just data, so passing that to the functions isn't a viable solution.
This almost works, but the functions in the modules need access to functions and variables at the top level of the server file. I know I could global.variable all of my variables and functions but I'd rather not, as I've only seen people recommend against that. Of course I could pass every single variable and function in each function call, but that would look ridiculous and brings up way too many potential problems. I was hoping I could pass a reference to the server's namespace, by passing this or something, but that didn't work. I could register every function and variable on some object and pass that around, but that's inconvenient and I'm trying to refactor for convenience and organization. I think I could read in the module files and eval them, as seen here, but I would much rather use the standard module.exports system if possible.
I'll summarize my comments into an answer.
Your data variable is local to server.js and is not accessible to your other two modules. I'd suggest you pass it to them when you load those modules as a means of sharing it with them. That design pattern is typically called a "module constructor" if you want to read more about it.
Passing data from one module to another is how you achieve shared data with separate modules without using globals. That's how you do it. Since you've now rejected the usual design pattern, there's not much else we can do without understanding a lot more about the real problem so we can go further outside your box and suggest a better design than the path you're down.
Abstracting hardware to have a common set of methods sounds like a perfect fit for subclasses where each piece of hardware has its own subclass, all with the same interface. Shared data could be in the base class.
You can pass a lot of variables at once if you make them properties of an object and pass just the object. Then, both places can reference the same properties on the same object and you can pass an infinite number of properties by passing one object. There is no way to pass a modules namespace. You have to create your own object with properties on it and pass that. You can create such an object and then set that object into the base class and then all your derived classes can have access to that object.
In short:
module.exports = {
doX () {
console.log(data['a']);
^^^^ this variable is not available here. You should pass it as argument to make it available.
}
}

JavaScript: Is the nesting of constructor instances inside a constructed 'wrapper' problematic?

Hopefully this question won't be flagged as too subjective but I'm newish to OOP and struggling a bit when it come to sharing data between parts of my code that I think should be separated to some extent.
I'm building a (non-geo) map thing (using leaflet.js which is superduper) which has a map (duh) and a sidebar that basically contains a UI (toggling markers both individually and en masse, searching said marker toggles as well as other standard UI behaviour). Slightly confused about organisation too (how modular is too modular but I can stumble through that myself I guess). I am using a simple JSON file for my settings for the time being.
I started with static methods stored in objects which is essentially unusable or rather un-reusable so I went for nested constructors (kinda) so I could pass the parent scope around for easier access to my settings and states properties:
function MainThing(settings) {
this.settings = options;
this.states = {};
}
function SubthingMaker(parent) {
this.parent = parent;
}
SubthingMaker.prototype.method = function() {
var data = this.parent.settings.optionOne;
console.log(data);
this.parent.states.isVisible = true;
};
MainThing.prototype.init = function() {
this.subthing = new SubthingMaker(this);
// and some other fun stuff
};
And then I could just create and instance of MainThing and run MainThing.init() and it should all work lovely. Like so:
var options = {
"optionOne": "Hello",
"optionTwo": "Goodbye"
}
var test = new MainThing(options);
test.init();
test.subthing.method();
Should I really be nesting in this manner or will it cause me problems in some way? If this is indeed okay, should I keep going deeper if needed (maybe the search part of my ui wants its own section, maybe the map controls should be separate from DOM manipulation, I dunno) or should I stay at this depth? Should I just have separate constructors and store them in an object when I create an instance of them? Will that make it difficult to share/reference data stored elsewhere?
As regards my data storage, is this an okay way to handle it or should I be creating a controller for my data and sending requests and submissions to it when necessary, even if that data is then tucked away in simple JSON format? this.parent does really start to get annoying after a while, I suppose I should really be binding if I want to change my scope but it just doesn't seem to be an elegant way to access the overall state data of the application especially since the UI needs to check the state for almost everything it does.
Hope you can help and I hope I don't come across as a complete idiot, thanks!
P.S. I think the code I posted works but if it doesn't, its the general idea I was hoping to capture not this specific example. I created a much simpler version of my actual code because I don't want incur the wrath of the SO gods with my first post. (Yes, I did just use a postscript.)
An object may contain as many other objects as are appropriate for doing it's job. For example, an object may contain an Array as part of its instance data. Or, it may contain some other custom object. This is normal and common.
You can create/initialize these other objects that are part of your instance data in either your constructor or in some other method such as a .init() method whichever is more appropriate for your usage and design.
For example, you might have a Queue object:
function Queue() {
this.q = [];
}
Queue.prototype.add = function(item) {
this.q.push(item);
return this;
}
Queue.prototype.next = function() {
return this.q.shift();
}
var q = new Queue();
q.add(1);
q.add(2);
console.log(q.next()); // 1
This creates an Array object as part of its constructor and then uses that Array object in the performance of its function. There is no difference here whether this creates a built-in Array object or it calls new on some custom constructor. It's just another Javascript object that is being used by the host object to perform its function. This is normal and common.
One note is that what you are doing with your MainThing and SubthingMaker violates OOP principles, because they are too tightly coupled and have too wide access to each other internals:
SubthingMaker.prototype.method = function() {
// it reads something from parent's settings
var data = this.parent.settings.optionOne;
console.log(data);
// it changes parent state directly
this.parent.states.isVisible = true;
};
While better idea could be to make them less dependent.
It is probably OK for the MainThing to have several "subthings" as your main thing looks like a top-level object which will coordinate smaller things.
But it would be better to isolate these smaller things, ideally they should work even there is no MainThing or if you have some different main thing:
function SubthingMaker(options) {
// no 'parent' here, it just receives own options
this.options = options;
}
SubthingMaker.prototype.method = function() {
// use own options, instead of reading then through the MainThing
var data = this.options.optionOne;
console.log(data);
// return the data from the method instead of
// directly modifying something in MainThing
return true;
this.parent.states.isVisible = true;
};
MainThing.prototype.doSomething = function() {
// MainThing calls the subthing and modifies own data
this.parent.states.isVisible = this.subthing.method();
// and some other fun stuff
};
Also to avoid confusion, it is better not to use parent / child terms in this case. What you have here is aggregation or composition of objects, while parent / child are usually used to describe the inheritance.

unit testing nested objects in javascript/node

I have an object called NetFlowStorage that contains methods to access a specific elasticsearch index. My constructor looks like:
function NetFlowStorage() {
this.host = 'localhost:9200';
this.shards = '4';
this.replicas = '0';
this.index_name = 'flow_track2';
this.client = null;
}
Inside of the object I have a method called connect which, when called, will make the connection and store the elasticsearch client object in the this.client property (if there isn't one already there). This way all of the object methods can get access to the elasticsearch client by using this.client
First question, is this an appropriate pattern? If not, what is preferable?
Second question (and the one that drove me here), how would I mock calls to things like this.client.index({}) I'm just starting to mess around with unit testing and mocks under node/js so I don't really have a preference in terms of framework (currently using mocha/chai/sinon)
Full code is here if you want to see in more detail.
For something like this I would use dependency injection.
You want to decouple the NetFlowStorage class from the actual elasticsearch client:
function NetFlowStorage(esClient) {
this.host = 'localhost:9200';
this.shards = '4';
this.replicas = '0';
this.index_name = 'flow_track2';
// if you don't wanna share connections across several instances
// you can instantiate the client here otherwise you can pass the
// client instance
this.client = esClient; // or new esClient({ host: this.host })
}
This way you won't even need the elasticsearch as part of the node module and even share a connection across more than one instance (or not?)
This decoupling will also make it easier to mock the esClient as you would inject the mock elasticsearch client in the test itself.
I think that you should pass a config object and a connection object to the method.
So if you would use Jasmine for testing for example you could pass a spy
var client = {index:function(){}}
spyOn(client, 'index');
....
expect(client.index)toHaveBeenCalled();
and to pass it at some point with injection or a singleton to the SUT

Is it possible to spy on or mock the value of a "behind-the-scenes" variable?

Let's say I have code that modifies a variable which is not exposed to the user like this:
var model;
module.exports = {
doSomething: function() {
...
//at some point in the code, modify model
if(/* something happened */) {
model = '123';
},
doSomethingElse: function() {
//use model in some way
}
}
};
If I later want to write a unit test to make sure that model was updated, but I do not have a getter for it, how can I test this? Is this possible to do with Karma/Jasmine/Sinon.js?
It is impossible to check the model value directly because it's hidden in a closure.
You can still write tests for it though: Your "model" will make doSomethingElse behave differently. You can verify that it matches your expectations after calling doSomething. This way, you are also free refactor the internals of your module without changing the test cases.
In general, testing private methods or properties is an antipattern. By making aspects of your implementation private, you're explicitly creating the freedom to change how those implementation details work in the future without changing your public API.
Therefore, in an ideal world, you should not (and in this case, you cannot) test the model value.
That said, we don't always live in an ideal world. So, there are some workarounds that you might consider if you really, really must test private properties and methods.
First, you could look for an environment variable, and export additional properties (by attaching them to the exports).
var model;
module.exports = {
...
}
if(process.env.ENV === 'TEST') {
module.exports.model = model;
}
Second, you can use conventions instead of making things completely private. For example, a common convention is to prefix private entities with _ to signify that they are not part of the public API. This can have varied levels of effectiveness depending on the audience that will consume your API.
Third, you could create accessors for your private variables, and check for the presence of a testing environment in some way (perhaps a global variable, an environment variable, or a variable injected into your module upon instantiation) that only allows access when the test environment is detected.
Fourth, you could allow an "inspector" object to be injected into your module (this object would only be present during testing). I have used this pattern with some success.
module.exports = function(spies) {
...
spies = spies || {};
var model = spies.model;
...
}
...
// instantiate the module in the test
var spies = {};
var mock = new Module(spies);
// do a thing
expect(spies.model).to.eql("foo");
But really, you should reconsider your testing strategy and design.

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);
});
});

Categories

Resources