I have been exploring patterns in various MV* frameworks out there and today noticed a weird one, which seems to cause some issues
Model prototype. has a property collections: []
Collection prototype. has a property models: []
When a collection gets a new model, it is being pushed into collection.models
but the model itself is also decorated to be aware of the collection it is a member of - i.e. the collection instance is pushed into model.collections
.
so model.collections[0]
is a collection that contains a .models[0]
being the model that has a collection property... and so on.
at its most basic:
var A = function() {
this.collections = [];
},
B = function() {
this.models = [];
this.add = function(what) {
what.collections.push(this);
this.models.push(what)
};
};
var model = new A();
var collection = new B();
collection.add(model);
Here's the guilty party in action: https://github.com/lyonbros/composer.js/blob/master/composer.js#L310-313 and then further down it's pushing into models here: https://github.com/lyonbros/composer.js/blob/master/composer.js#L781-784
I suppose there is going to be a degree of lazy evaluation - things won't be used until they are needed. That code - on its own - works.
But I was also writing tests via buster.js and I noticed that all the tests that had reliance on sinon.spy()
were producing InternalError: too much recursion
(FF) or RangeError: Maximum call stack size exceeded
(Chrome). The captured FF was even crashing unresponsively, which I have never encountered with buster test driver before - it even went to 3.5gb of ram use over my lunch break.
After a fair amount of debugging, I undid the reference storage and suddenly, it was all working fine again. Admittedly, the removal of the spy()
assertions also worked but that's not the point.
So, the question is - having code like that, is it acceptable, how will the browsers interpret it, what is the bottleneck and how would you decorate your models with a pointer to the collection they belong in (perhaps a collection controller and collection uids or something).
full gist of the buster.js test that will fail: https://gist.github.com/2960549