0

Patrones GRASP, un vistazo a través de CRIAX I (Experto)

12Jun
en CRIAX-SDK, Javascript, Tutoriales

Holas comunidad, si ya se estoy súper perdido, pero bueno por cuestiones de trabajo, el tiempo se me había reducido bastante y me era muy complicado, publicar, pero bueno ahora ya un poco más liberado de nuevo a la carga. Quisiera comenzar con una serie de artículos sobre los patrones GRASP, codificando los ejemplos mediante CRIAX, si el proyecto no esta muerto, de hecho se está trabajando en la próxima versión 1.4 que trae unas cuantas sorpresitas, pero en otros post, hablaré de ello, sin más adelante.

Introducción

El presente artículo pretende dar un acercamiento breve sencillo y práctico a los patrones GRASP desde CRIAX. Está dividido en 9 partes, cada una dedicada a un patrón específico.

Los patrones GRASP(Patrones de Asignación de Responsabilidades), son quizás uno de los patrones más básicos en el mundo de la programación. Ellos son 9:

  1. Experto
  2. Creador
  3. Alta Cohesión
  4. Bajo Acoplamiento
  5. Controlador
  6. Polimorfismo
  7. Fabrica Pura
  8. Indirección
  9. No hables con extraños

Los patrones se codifican en un formato estructurado que describe el problema y su solución y se les asigna un nombre.

Los patrones GRASP no introducen ideas novedosas, son una mera codificación de los principios básicos más usados. Describen los principios fundamentales de la asignación de responsabilidades a objetos.

1- Experto

Solución: asignar una responsabilidad al experto en información: la clase que cuenta con la información necesaria para cumplir la responsabilidad.

Para saber que se necesita hacer:

«Que información hace falta para …(hacer, obtener, determinar)…»

El objeto que tenga dicha información «o que a través de él podamos tener dicha información» es el experto en la información.

El cumplimiento de una responsabilidad requiere a menudo información distribuida en varias clases, esto significa que hay muchos experto parciales que colaboran en la tarea. Siempre que la información se encuentre distribuida en varios objetos, estos habrían de interactuar a través de métodos para compartir el trabajo. Trabajar con el patrón Experto conserva el encapsulamiento, soporta un bajo acoplamiento y brinda soporte a una alta cohesión. Este es el más importante patrón táctico.

Otras formas de designar este patrón:

  • juntar responsabilidades y la información
  • lo hace el que conoce
  • animación
  • lo hago yo mismo
  • unir los servicios a los atributos que se operan

Ejemplo

En una tienda de ventas de productos se desea conocer el gran total de la venta:

Quién es el responsable de conocer el gran total de la venta

Venta de productos. Patrón Experto

Venta de productos. Patrón Experto

Pregunta 1: Que información hace falta para calcular el total.

  1. Se deben conocer todas las instancias de VentaLineaProducto de una Venta.
  2. Sumar todos los subtotales (cada subtotal de VentaLineaProducto).

Como Venta contiene la información de todos los subtotales, Venta asume la responsabilidad de experto en información del total.

Se puede crear un método llamado total() en la clase Venta que lleve a cabo este trabajo.

Pregunta 2: Que información hace falta para calcular el subtotal.

  1. Se deben conocer la cantidad de VentaLineaProducto (la cantidad de ese mismo producto).
  2. Se debe conocer el precio de EspecificacionProducto (cuanto vale ese producto).
  3. Multiplicar la cantidad * precio

Como VentaLineaProducto contiene la cantidad y el producto específico, VentaLineaProducto asume la responsabilidad de experto en información para el subtotal.

Se puede crear un método llamado subtotal() en VentaLineaProducto que multiplique la cantidad del producto por su precio.

Pregunta 3: Que información hace falta para obtener el precio del producto.

  1. EspecificacionProducto es el que conoce su precio.

Como EspecificacionProducto conoce su precio, asume la responsabilidad de experto en información para el precio del producto.

Se puede crear un método llamado getPrecio() en EspecificacionProducto que devuelva el precio del producto.

Conclusión

Para calcular el total de la venta:

  1. Llamar al método total() de Venta, que sumará todos los subtotales, obtenidos a traves de cada VentaLineaProducto.
  2. Multiplicar la cantidad * el precio en cada método subTotal() de VentaLineaProducto.
  3. Cada subtotal llamará al método getPrecio() de EspecificacionProducto.
Venta productos. Métodos de experto en información

Venta productos. Métodos de experto en información

Codificación

Para llevar a cabo la codificación comenzamos traduciendo el diagrama optenido a código. Vamos desde lo más simple a lo más complejo comenzando por EspecificacionProducto, VentaLineaProducto y terminando por Venta.

Para crear las clases abrimos el vendor Criax-IDE, /path_to_Criax/Criax/vendors/Criax-IDE/spket (.exe o .bin) y creamos un nuevo proyecto llamado tienda, a diferencia de lo que se piensa la ruta del proyecto en el IDE no será el directorio raíz de la aplicación sino /path_to_tienda/tienda/source/class/tienda/.

Para profundizar más en la traducción de diagramas UML (de clase) a clases en CRIAX leer el artículo POO en CRIAX-SDK.

Comenzamos creando en el namespace model, la clase para EspecificacionProducto. Para ello en el IDE seleccionamos el directorio model y allí dentro creamos un archivo llamado EspecificacionProducto.js, con la ayuda de los snippets creamos una clase modelo:

qx.Class.define("tienda.model.EspecificacionProducto",
{
    extend : qx.core.Object,

    properties :
    {
        __descripcion : {},
        __precio : {}
    },

    construct : function(descripcion, precio)
    {
        this.base(arguments);
        this.__descripcion = descripcion;
        this.__precio = precio;
    },

    members :
    {
        getPrecio : function(){

        }
    }
});

Continuando con la clase de VentaLineaProducto:

qx.Class.define("tienda.model.VentaLineaProducto",
{
    extend : qx.core.Object,

    properties :
    {
        __cantidad : {},
        __especificacionProducto : {}
    },

    construct : function(especificacionProducto,cantidad)
    {
        this.base(arguments);
        criax.oop.TypeHinting.tHClass(tienda.model.EspecificacionProducto,especificacionProducto);
        this.__especificacionProducto = especificacionProducto;
        this.__cantidad = cantidad || 1;
    },

    members :
    {
        subTotal : function(){            

        }
    }
});

Por último la clase Venta:

qx.Class.define("tienda.model.Venta",
{
    extend : qx.core.Object,

    properties :
    {
        __fecha : {},
        __hora : {},
        __ventasLineas : {}
    },

    construct : function()
    {
        this.base(arguments);
        this.__ventasLineas = [];
        this.__hora = this.__fecha = new Date();
    },

    members :
    {
        add : function(ventaLinea){
            criax.oop.TypeHinting.tHClass(tienda.model.VentaLineaProducto,ventaLinea);
            this.__ventasLineas.push(ventaLinea);
        },

        total : function(){

        }
    }
});

Una vez generado todo el código del diagrama, queda ponerle el cuerpo a los métodos:

//método getPrecio de la clase EspecificacionProducto
getPrecio : function(){
    return this.__precio.toFixed(2);
}

//método subTotal de la clase VentaLineaProducto
subTotal : function(){
    var subTotal = this.__cantidad * this.__especificacionProducto.getPrecio();
    return subTotal.toFixed(2);
}

//método total de la clase Venta
total : function(){
    var total = 0;
    for(var i=0;i<this.__ventasLineas.length;i++){
        total = total + Number(this.__ventasLineas[i].subTotal());
    }
    return total.toFixed(2);
}

De esta manera ejecutando el código creado en el main de Application:

var producto1 = new tienda.model.EspecificacionProducto("Primer producto",5.2);
var producto2 = new tienda.model.EspecificacionProducto("Segundo producto",1.25);
var producto3 = new tienda.model.EspecificacionProducto("Tercer producto",2.2);

var linea1 = new tienda.model.VentaLineaProducto(producto1,2);//10.4
var linea2 = new tienda.model.VentaLineaProducto(producto2,1);//1.25
var linea3 = new tienda.model.VentaLineaProducto(producto3,3);//6.6

var venta = new tienda.model.Venta();
venta.add(linea1);
venta.add(linea2);
venta.add(linea3);

console.log(venta.total());//18.25

El código aquí mostrado es puramente didáctico.

Hasta aquí la primera parte del articulo de los patrones GRASP, espero dejen sus impresiones. En el próximo artículo estaremos hablando del patrón Creador.

Etiquetado en:

Dejar un comentario

¿Eres humano? Entonces resuelve esta operación: * Límite de tiempo se agote. Por favor, recargar el CAPTCHA por favor.