Some code may say more than a thousand words:
/**
* Represents an amount of a resource
* @param {number} amount
* @param {string} type
*/
function Resource(amount, type)
{
var nAmount = amount;
var sType = type;
if (amount < 0)
{
throw new IllegalArgumentException("amount has to be positive");
}
/**
* @method Resource
* @return {number} amount of the resource
*/
this.getAmount = function()
{
return nAmount;
};
/**
* @method Resource
* @return {string} resource type
*/
this.getType = function()
{
return sType;
};
}
/**
* Addition of two resources produces a new resource with the sum amount
* the new object uses the old one as prototype
* @param {Resource} resource
* @return {Resource} new Resource object
*/
Resource.prototype.plus = function(resource)
{
if (!(resource instanceof Resource && this.getType() == resource.getType()))
{
throw new IllegalArgumentException("resources don't match.");
}
var newRes = Object.create(this); // create a new object based on the current one
// execute the Resource constructor on it
Resource.call(newRes, this.getAmount() + resource.getAmount(), this.getType());
return newRes;
};
Resource objects are ValueObjects considered immutable. They return a new object on an addition operation. Now instead of just calling "new Resource(args)" to create the new object to return, I created a new one based on the old object. This also permits inheritance.
As I'm starting to use this on all my ValueObjects (just in case I want to inherit from them at some point in the future), I started to think about this a bit more.
JavaScript doesn't allow immutable objects. Yet, Objects are vulnerable by direct method overwriting or calling their constructor. All I can do is to decide that these are bad habits. Unfortunately ECMAScript5 "freeze" is not yet here, though my pattern is compatible with it.
Now that I have this "bad style" of calling the constructor on an immutable object along with this code duplication, I'm thinking of creating a new function to encapsulate this procedure:
Object.recreate = function(proto, constructor, args)
{
var obj = Object.create(proto);
constructor.apply(obj, args);
return obj;
};
And therefor:
Resource.prototype.plus = function(resource)
{
// if ... {throw ...}
return Object.recreate(this, Resource,
[this.getAmount() + resource.getAmount(), this.getType()]);
};
Maybe somebody has a better idea for the name of this function. 'Recreate' is what my first thought was. What do you think about this pattern? Is it an over-abstraction? Should I save this for classes I'm sure I'll inherit from? Did I miss anything important?
Edit: I see I forgot to mention something important which doesn't reflect currently in this article. ValueObject's are easily cloned with Object.create. Their private members are unchangeable. But what about changeable private members? If a set() is called on the clone, it sets the original prototype object within the closure! As my Object.recreate recreates the closure, this problem is solved.
So is there a better way for inheritance with private variables? Why is everyone using sugar for class creation? I've read so much about prototypalism, I still don't have the hang of it.