Pregunta

Algún código puede decir más de mil palabras:

/**
 * 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;
};

Los objetos de recursos son ValueObjects considerados inmutables.Devuelven un nuevo objeto en una operación de suma.Ahora, en lugar de simplemente llamar a "nuevo recurso (argumentos)" para crear el nuevo objeto a devolver, creé uno nuevo basado en el objeto anterior.Esto también permite la herencia.

Cuando comencé a usar esto en todos mis ValueObjects (en caso de que quiera heredar de ellos en algún momento en el futuro), comencé a pensar un poco más en esto.

JavaScript no permite objetos inmutables.Sin embargo, los objetos son vulnerables al sobrescribir un método directo o llamar a su constructor.Todo lo que puedo hacer es decidir que estos son malos hábitos.Desafortunadamente, el "congelamiento" de ECMAScript5 aún no está aquí, aunque mi patrón es compatible con él.

Ahora que tengo este "mal estilo" de llamar al constructor de un objeto inmutable junto con esta duplicación de código, estoy pensando en crear una nueva función para encapsular este procedimiento:

Object.recreate = function(proto, constructor, args) 
{
    var obj = Object.create(proto);
    constructor.apply(obj, args);
    return obj;
};

Y por lo tanto:

Resource.prototype.plus = function(resource) 
{
    // if ... {throw ...}
    return Object.recreate(this, Resource, 
            [this.getAmount() + resource.getAmount(), this.getType()]);
};

Quizás alguien tenga una mejor idea para el nombre de esta función.'Recrear' es lo que pensé primero.¿Qué opinas de este patrón?¿Es una sobreabstracción?¿Debo guardar esto para las clases de las que estoy seguro heredaré?¿Me perdí algo importante?

Editar:Veo que olvidé mencionar algo importante que no se refleja actualmente en este artículo.Los ValueObject se clonan fácilmente con Object.create.Sus miembros privados son inmutables.Pero ¿qué pasa con los miembros privados cambiantes?Si se llama a set() en el clon, ¡establece el objeto prototipo original dentro del cierre!Como mi Object.recreate recrea el cierre, este problema se resuelve.

Entonces, ¿existe una mejor manera de heredar con variables privadas?¿Por qué todo el mundo usa azúcar para la creación de clases?He leído tanto sobre el prototipismo que todavía no lo domino.

¿Fue útil?

Solución

Volviendo a esto después de años, puedo decir que el código que escribí entonces tenía fallas al mezclar conceptos.En realidad, JavaScript puede proporcionar verdaderas variables privadas mediante cierre.Pero dado que los ValueObjects son inmutables de todos modos, ese estado privado no se puede cambiar y ocultarlo complica demasiado las cosas.

Además, el ingenioso Object.recreate es una especie de "método de fábrica" ​​demasiado abstracto, que uno debe declarar por separado para cada clase si lo necesita.

¡Usa la composición sobre la herencia!Crockford brinda excelentes conocimientos sobre JavaScript: https://crockford.com/javascript/prototypal.html

Otros consejos

Creo copia o clon sería un nombre mejor. Este artículo explica los mecanismos para la creación de este tipo de funciones genéricas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top