Patrones GRASP, un vistazo a través de CRIAX I (Experto)
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:
- Experto
- Creador
- Alta Cohesión
- Bajo Acoplamiento
- Controlador
- Polimorfismo
- Fabrica Pura
- Indirección
- No hables con extraños
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
Pregunta 1: Que información hace falta para calcular el total.
- Se deben conocer todas las instancias de
VentaLineaProductode unaVenta. - Sumar todos los subtotales (cada subtotal de
VentaLineaProducto).
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.
- Se deben conocer la cantidad de
VentaLineaProducto(la cantidad de ese mismo producto). - Se debe conocer el precio de
EspecificacionProducto(cuanto vale ese producto). - Multiplicar la cantidad * precio
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.
EspecificacionProductoes el que conoce su precio.
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:
- Llamar al método
total()deVenta, que sumará todos los subtotales, obtenidos a traves de cadaVentaLineaProducto. - Multiplicar la cantidad * el precio en cada método
subTotal()deVentaLineaProducto. - Cada subtotal llamará al método
getPrecio()deEspecificacionProducto.
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/.
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //método getPrecio de la clase EspecificacionProductogetPrecio : function(){ return this.__precio.toFixed(2);}//método subTotal de la clase VentaLineaProductosubTotal : function(){ var subTotal = this.__cantidad * this.__especificacionProducto.getPrecio(); return subTotal.toFixed(2);}//método total de la clase Ventatotal : 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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.4var linea2 = new tienda.model.VentaLineaProducto(producto2,1);//1.25var linea3 = new tienda.model.VentaLineaProducto(producto3,3);//6.6var venta = new tienda.model.Venta();venta.add(linea1);venta.add(linea2);venta.add(linea3);console.log(venta.total());//18.25 |
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.






