views:

205

answers:

1

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 addition. 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 some times), I started to think about it a bit more.

JavaScript doesn't allow immutable objects yet, Objects are vulnarable by direct method overwriting or calling the constructor on it. All I can do is to declare them bad habits. Unfornatunately ECMAScript5 "freeze" is not yet here, though my pattern is compatible with it.

Now as I have this "bad style" of calling the constructor on a immutable object and 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 anybody has a better idea for the name of this function, this is what my first though was. What do you think about this pattern? Is it 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 unchangable. But what about changable private members? If a set() is called on the clone, it sets on 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 get the hang of it.

A: 

I think copy or clone would be a better name. This article explains mechanisms for creating such generic functions.

ardsrk
Nice article, but I couldn't get much new out of it. owl.clone is exactly what Object.create is here, and I think that name fits better.I'll edit my question for the case of non-ValueObjects with private variables which collides with "clone/create", but not with my recreate.
Phoscur