I work on an open source project - object document mapper aka. ODM
in javascript
and am facing a design decision I struggle with (rather simple
but not easy
) .
In the ODM
you can define a Model
object which describes your data document in a database. When creating a new Model
instance object you can pass in it's data values via an argument.
Pseudocode:
var data = {
username: 'james'
email: 'james@email.com',
country: {
code: 'US',
city: ''
}
};
// In case the data object would not be cloned, it would be mutated by the ODM
var user = new UserModel(data);
Now, the decision I'm facing is whether to automatically clone data
object in the Model before it's processed by the application (ODM). I incline to a choice of not cloning the input data. I feel like that in the javascript
community it's quite popular to clone data usually more than it's necessary because it can make things easy
(not simple
) for end-users. From my research I've found out that some similar and popular projects made a decision to clone the data, yet I'm not sure that's the right choice considering a Model can have large & complex data schema and while it does not make any difference in case of tens of Model
instance objects, I think it could be an issue while working with eg.: hundreds of Model
objects.
I'd love to hear your reasoning on the topic and what would be your choise?
In case you already see another answer, please, don't hesitate to write down your thoughts!
Thank you!
If you keep using the input object to hold the entity's data, you will face a problem like the following if you don't clone the object:
var UserModel = function(data) {
this.data = data;
}
UserModel.prototype.getUsername = function() {
return this.data.username;
}
var data = {username: 'james'};
var james = new UserModel(data);
data.username = 'john';
var john = new UserModel(data);
console.log(james.getUsername()); // "john"
console.log(john.getUsername()); // "john"
This may lead to some nasty bugs that may not always be obvious.
Instead of cloning, the cleanest approach in my opinion would be to instead extract the relevant info out of the object and keep it as member properties directly:
var UserModel = function(data) {
this.username = data.username;
this.email = data.email;
}
UserModel.prototype.getUsername = function() {
return this.username;
}
UserModel.prototype.getEmail = function() {
return this.email;
}
Even better, explicitly declare the properties as arguments of the constructor:
var UserModel = function(username, email) {
this.username = username;
this.email = email;
}