Is it better to have one large object in JavaScript or many smaller ones?
I'm writing a JS lib that reads chess games to turn the开发者_开发百科m into re playable games, in one single web page there can be many games (one in its own div), what I'm wondering is – thinking about performance – if it's better to have one large object that holds all the moves of all the games or many smaller objects each storing the moves of one game.
I realize that this is perhaps a small point in the whole optimization process but its the one that I want to address now.
Donald Knuth: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil"
Start by designing a data model for your game that is right and natural from a domain modelling point of view.
Build the software.
Then, when you're at a stage in development that analysing performance makes sense, work out some low performance environments you'd like your game to work in, and test in them.
You'll probably find you have no issues, as others have stated in answers to this question.
If you find an issue, profile your code and discover the cause. Optimise the code you need to. Even if you find a performance issue, it's unlikely to be caused by your data model, as long as you've designed it well.
If data model really is a performance issue, only then should you compromise your initial design only to the extent you need to in order to get the performance you need, documentating the compromises you've made, and why you had to.
The best way to take advantage of objects is to use the prototypal pattern in JavaScript. This means you share data with objects, rather than being stingy and saying "That's mine!".
This pattern is all over the place in JavaScript libraries. It looks something like this:
var Template = {
extend: function () {
var F = function () {};
F.prototype = this.prototype;
var instance = new F();
instance.mixin.apply(instance, arguments);
return instance;
},
mixin: function (mixins) {
for (var i = 0, len = arguments.length; i < len; i++) {
for (var k in arguments[i]) if (arguments[i].hasOwnProperty(k)) {
this[k] = arguments[i][k];
}
}
return this;
}
};
This magical class will share data across inheritance chains, and make your object model simpler. Nothing's a class- everything's an Object! This means understanding minutiae of JavaScript, as to not get yourself stuck in sticky goo, but is well worth it.
This means that when you have:
var Koopa = Template.extend({
hasShell: true,
fatalFlaw: 'shell'
});
var Bowser = Koopa.extend({
fatalFlaw: 'tail'
});
The data stored looks as follows:
+-------------------. +---------------------. +---------.
| Bowser |->| Koopa |->| Template |
+--------------------+ +----------------------+ +----------+
|fatalFlaw => 'tail' | | hasShell => true | | mixin |
`-------------------+ | fatalFlaw => 'shell' | | extend |
`---------------------+ `---------+
This design stems from Father Crockford's prototypal inheritance design. And like Knuth says: "Premature optimization is the root of all evil!"
And... if this seems like an off topic answer- it's intended. You should be asking questions of how your design can serve what your needs are. If you do it well, then everything should fall into place. If you don't think it through enough, you can end up with some nasty side effects and stinky code. Do yourself a favor and come up with a design that eliminates any bit of hesitation you have. Browsers do more complicated and CPU intensive things these days than solve chess!
So, my answer is... don't listen to what people say about efficiency, or what's best (even me!). Do what makes most sense to you, in the design of your library. Right now, you're trying to shove a square peg into a round hole. You need to first decide what your needs are, and everything will come naturally after. It might even surprise you!
Small objects are the preferable choice in my eyes.
- From a software engineering perspective, it's much better to have a more modular design with smaller, composable objects rather than one monolithic object. Rather than having one object per game, I would even represent each move as an object.
- Recent JS engines like V8 try to build struct-like objects from "class" definitions. This happens behind the scenes for fast property access. Google explains this in the design of V8. Essentially, if you have several small instances of the same class that is more or less static (that is, each instance of the class has the same properties), V8 can optimize for this case.
Don't worry unnecessarily about performance. Design it in a way that seems natural. Obviously you don't want to put all the moves of all games into a single object, that defeats the purpose of object-oriented design. Go with the second option and have an object for each game. It's highly unlikely that you'll run into any problems unless you're loading several thousand games on a single page.
I think this question is much more about software design than performance. But I'm glad youare addressing it now, avoiding refactoring later.
I think you should think each game as an instance (div) of a ChessGame object. This will facilitate much of the rest of development, as making custom libs and functions to deal with game, also you will have the possibility of threading each game (google for "web workers"), increasing the overall performance.
精彩评论