I have a Session
object, of which a single global instance session
holds the current session, which can persist itself to the server, handle undos redos etc.
The session holds an instance of Objects
which is in this example basically a set of Cars
objects. When user changes e.g. a marker on a map representing a car's location, I want to update the corresponding Car
object AND save the session to be able to redo and persist it to the server.
Incomplete diagram:
Code:
function Session(sessionId, objectsSave){
this.objects = new Objects();
if (objectsSave !== undefined)
this.objects.restore(objectsSave);
Session.prototype.saveSession = function() {
var save = this.objects.save();
// persist to server and add to redoStack
}
function Objects() {
this.objects = [];
}
Objects.prototype.restore = function(save){
var objects = [];
save.forEach(function(obj) {
objects.push(Car.prototype.restore(obj));
});
this.objects = objects;
};
function Car(){
this.markerOnMap = new Marker();
this.markerOnMap.onDrag = this.setLocation;
this.markerOnMap.onDragEnd = session.saveSession; // here using the global variable, does not work when instantiating Session with a save object
Car.prototype.setLocation = function(e) {
this.location = e.location;
}
var session = new Session();
The problem emerges (besides the "bad design" feeling) when I want to instantiate a Session
e.g. with data from the server. In Session
constructor I create a new Objects
instance, and restore it with the save, which will create Car
objects, which will try to reference a function of the global variable session
. But session
is not assigned yet, because this code was called from the constructor of Session
.
I could have e.g. changed it to:
this.markerOnMap.onDragEnd = function(){session.saveSession()};
or pass this
from Session
constructor all the way down to the constructor of Car
.
I don't know what is worse, to have a global variable, all circular references, or is there a better solution?
Best Answer
There is indeed a design flaw in your construction process: the
Car
requires theSession
at its creation. This dependency then becomes an issue when theCar
is deserialized during the resort of theSession
.The problem is due to the non respect of the principle of single responsibility: when you construct a
Car
, you should only create the object, and not insert it into some container. This second step should be the responsibility of the function/object that instantiates theCar
for a specific purpose.In your case, I'd recommend to consider the builder design pattern.. This design separates the building of complex objects (here the Session) into building and assembling its parts. This requires that parts can be constructed independently.