0

Inyección de Dependencias en CRIAX-SDK III

26Jun
en CRIAX-SDK, Documentación, Herramientas, Javascript, SDK, Tutoriales, XUL


Tomo como plantilla para redactar este post y otros sobre el mismo tema, del libro Desarrollo agil con Symfony 2.1 de Javier Eguiluz. Específicamente el Apendice B: Inyección de Dependencias (pag 577).

5. Inyección de Dependencias en CRIAX-SDK

Como conocimos el final del post anterior, hacer uso de la inyección de dependencias en las aplicaciones CRIAX es incluso más sencillo de lo que se ha explicado en las secciones anteriores. De hecho, en la mayoría de los casos sólo debes programar tus clases y después añadir unas pocas líneas en un archivo de configuración JSON (se encuentra en resource/persistence). El contenedor que incluye CRIAX se encarga de procesar esa configuración y prepara todas las dependencias entre clases.

6. Utilizando servicios desarrollados por terceros

Dentro de una aplicación desarrollada con la plataforma, el término servicio hace referencia a cualquier clase/objeto manejada por el contenedor de inyección de dependencias. En la práctica los servicios son clases JS que realizan cualquier tarea global dentro de la aplicación.

Cuando desarrollas una aplicación, lo habitual no es definir servicios en el contenedor de inyección de dependencias, sino utilizar los servicios que incluye el SDK.

Observa el siguiente código de una clase imaginaria:

 /**
  * Modelo para Default
  *
  * @class Default
  * @public
  * @extends qx.criax.domain.DomainModel
  * @author Nilmar Sanchez Muguercia
  * @namespace inyeccion.model
  * @copyrigth
  * @license
  * @version 0.0.1
  *
  */

qx.Class.define("inyeccion.model.Default",
{
    extend : criax.domain.DomainModel,

    /**
     * @property
     */
    properties :
    {

    },

    /**
     * metodo de inicializacion de la clase
     *
     * @constructor
     * @public
     * @param params {array}: arreglo de parametros iniciales
     *
     */

    construct : function(params)
    {
        this.base(arguments);
    },

   /**
     * @method
     */
    members :
    {
        /**
         *  metodo para el ejemplo del contenedor
         *
         * @method action
         * @public
         * @param
         * @return
         *
         */

        action : function(){
            var driverDb = this.container().get("connection");
            console.log(driverDb);
        }
    }
});

El código anterior es un buen ejemplo de cómo funciona y qué ventajas tiene el uso de un contenedor de inyección de dependencias. Los controladores que heredan de la clase criax.mvc.Controller  y modelos que heredan de criax.domain.DomainModel, en CRIAX disponen de un acceso directo al contenedor a través del método this.container().get().

De forma muy simple se puede observar como se obtiene el driver de conección a la base de datos y como se muestra su nombre por consola.

Tu código no sabe cómo crear un objeto de la petición. No sabe ni qué clase hay que instanciar ni de qué otras clases depende ni qué parámetros utiliza para su configuración. Todo ese trabajo es responsabilidad del contenedor. La instrucción this.container().get(“connection”) indica que tu código quiere hacer uso de un servicio llamado connection. El contenedor de CRIAX busca entre todos los servicios definidos aquel que se llame connection y realiza todas las tareas necesarias para instanciar el objeto correspondiente y entregártelo. Además de que tu código se vuelve extremadamente conciso y sencillo, observa la flexibilidad que ofrece el contenedor.

Siguiendo con el código anterior, observa cómo crear un mensaje de log con el contenedor de CRIAX-SDK en el Application:

...
var container = criax.dic.DiContainer.getInstance();
var logger = container.get("logger");

logger.info("Mensaje de informacion");
logger.error("Mensaje de error");
...

Por supuesto si es desde un controlador o modelo

...
var logger = this.container().get("logger");

logger.info("Mensaje de informacion");
logger.error("Mensaje de error");
...

Otra vez tu código sólo pide al contenedor que devuelva servicios .get(“logger”), sin preocuparse de cómo se crean, o las dependencias que tienen con otras clases.

El servicio logger por ejemplo debe saber si los mensajes de log se guardan en un archivo, en una base de datos o si se envían por correo electrónico. Si se guardan en un archivo, también debe conocer por ejemplo su ruta. Así que cuando utilices servicios creados por terceros (o servicios propios de CRIAX) lo primero que debes hacer es configurarlos adecuadamente.

Las opciones de configuración disponibles para los servicioos y sus posibles valores se indican en el archivo README.txt del directorio resource/services. El servicio logger por ejemplo se configura mediante las siguientes opciones:

...
{
    id:"file",
    clazz:"inyeccion.model.File",
    arguments:[["logs.txt"]],
},
{
    id:"logger",
    clazz:"inyeccion.model.Logger",
    call:{1:["setManager","@file"]}
 }
...

Si más adelante quieres cambiar el archivo de los mensajes de log, sólo debes modificar la opción arguments, del servicio file, pero el código de la aplicación sigue siendo .get(“logger”).

Para ello el código de la clase File y Logger, casi no varian:

Clase File:

var File = criax.chromeless.lib.File;
var AppPath = criax.chromeless.lib.AppPath;
 var Path = criax.chromeless.lib.Path;

 /**
  * Modelo para File
  *
  * @class File
  * @public
  * @extends qx.criax.domain.DomainModel
  * @author Nilmar Sanchez Muguercia
  * @namespace inyeccion.model
  * @copyrigth
  * @license
  * @version 0.0.1
  *
  */

qx.Class.define("inyeccion.model.File",
{
    extend : criax.domain.DomainModel,
    implement : inyeccion.model.ISaveLog,//que implemente la interfaz ISaveLog

    /**
     * @property
     */
    properties :
    {
    	/**
    	 * propiedad para el archivo
    	 *
    	 * @name __file
    	 * @private
    	 *
    	 */
    	__file : {}
    },

    /**
     * metodo de inicializacion de la clase
     *
     * @constructor
     * @public
     * @param params {array}: arreglo de parametros iniciales
     *
     */

    construct : function(params)
    {
        this.base(arguments);

        var appPath = new AppPath();
		//archivo de logs en el directorio drecursos
		var resorcePath = appPath.getResourceDir();
		var path = new Path(resorcePath);
		var logFilePath = path.join(params[0]);

        var file = new File(logFilePath);
        this.__file = file.open("w");
    },

   /**
     * @method
     */
    members :
    {
        /**
         *  metodo para escribir en el log
         *
         * @method write
         * @public
         * @param content {String}
         * @return
         *
         */

        write : function(content){
        	this.__file.write(content+" ");
        	this.__file.flush();
        }
    }
});

Clase Logger:

 /**
  * Modelo para Logger
  *
  * @class Logger
  * @public
  * @extends qx.criax.domain.DomainModel
  * @author Nilmar Sanchez Muguercia
  * @namespace inyeccion.model
  * @copyrigth
  * @license
  * @version 0.0.1
  *
  */

qx.Class.define("inyeccion.model.Logger",
{
    extend : criax.domain.DomainModel,

    /**
     * @property
     */
    properties :
    {
    	/**
    	 * manager para guardar los logs
    	 *
    	 * @name __manager
    	 * @private
    	 *
    	 */
    	__manager : {}
    },

    /**
     * metodo de inicializacion de la clase
     *
     * @constructor
     * @public
     * @param params {array}: arreglo de parametros iniciales
     * params[0] = manager
     *
     */

    construct : function(params)
    {
        this.base(arguments);
    },

   /**
     * @method
     */
    members :
    {
        /**
         *  metodo para mostrar un log de informacion
         *
         * @method info
         * @public
         * @param message {String}: mensaje de informacion
         * @return
         *
         */

        info : function(message){
            this.__manager.write("INFO: "+message);
        },

        /**
         *  metodo para mostrar un log de error
         *
         * @method error
         * @public
         * @param message {String}: mensaje de error
         * @return
         *
         */

        error : function(message){
            this.__manager.write("ERROR: "+message);
        },

        /**
         *  metodo para establecer el manager de los logs
         *
         * @method setManager
         * @public
         * @param manager {inyeccion.model.ISaveLog}
         * @return
         *
         */

        setManager : function(manager){
        	//ver que el objeto pasado implementa la interfaz ISaveLog
        	criax.oop.TypeHinting.tHInterface(inyeccion.model.ISaveLog,manager);
            this.__manager = manager;
        }
    }
});

Esta filosofía de programación se denomina SOA, las siglas en inglés de Arquitectura Orientada a Servicios. Este es uno de los paradigmas de programación más utilizados y probados en el ámbito de la ingeniería del software.


Source de la aplicación: solo crear un proyecto llamado inyeccion y sustituir el directorio source, por el adjunto descompactado.

Source

0 MB

Bonificación

Readme de como crear servicios en CRIAX-SDK. Incluido en el skeleton de la aplicación cuando es creada en el directorio app/resource/services/.

Readme.txt

En el próximo post estaremos viendo como crear servicios propios en CRIAX-SDK.

Dejar un comentario