Archivo de la categoría: Diseño de Arquitecturas

Introducción a una solución SOA

En este tutorial se introduce al mundo SOA y alguna de las muchas soluciones que se puede implementar.

Empezaremos introduciendo alguno de los conceptos que siempre se repiten SOA, BPM, BPEL, ESB y trataremos de explicar diferenicas y soluciones de los mismos. Terminamos introduciendo un ejemplo genérico para comprender cómo interactuan las tecnologías propuestas.

Debe tener conocimientos de Arquitectura Web (es recomendable el siguiente artítulo) y mucha imaginación 🙂

¿Qué es SOA?

Service Oriented Architecture es un diseño de arquitectura como lo es un diseño  SaaS  (software as a service). Es una forma de estructurar aplicaciones distribuídas de cara a una mayor reutilización de las funciones basándose en la orientación a servicios.

Con SOA se pretende que tengas tus funciones (generalmente) en un web service y que esas funciones  sean llamadas desde tus aplicaciones distribuídas geográficamente.  Además de desacoplar, una gran ventaja es la independencia del lenguaje en el que estén implementados los componentes.

SOA puede tener diferentes soluciones. Cada solución conlleva unas metodologías (BPM), tecnologías (BPMS, ESB) o herramientas específicas (Oracle SOA Suit como solución de PBMS, OSB como solución de ESB, etc) . Vamos a explicar alguno de los conceptos junto algunas soluciones que ofrece el mercado.

En primer lugar observe el siguiente diagrama para comprender la distribución de los componentes se que se van a explicar a continuación:

Solución de arquitectura SOA
Solución de arquitectura SOA

Como “aplicación 1” podemos imaginarnos una aplicación web para los usuarios que administran a los clientes, “aplicación 2” la aplicación web que utilizan los clientes, etc.

Como “servicio1”, “servicio2” podemos imaginarnos que es una función alojada en un web service. En caso de desconocer qué es un web service recomendio la lectura del siguiente artículo. También podemos encontrarnos otro tipo de servicios (como el de correo, impresoras, etc).

Como “negocio” y “procesos” se pretende diferenciar niveles dentro de un modelo.  A continuación completaremos esta definición.

El BUS será el encargado de ofrecer la tecnología para comunicar aplicaciones y servicios.

¿Con qué modelar y procesar los negocios y procesos?

¿Qué es BPM?

Business Process Model es una metodología basada en mejorar la eficiencia y el desempeño de una organización mediante la identificación de procesos de negocio. Por BPM también se conocen todas las herramientas o tecnologías que envuelve la metodología para su análisis, diseño, ejecución, monitorización y control de los procesos.

La diferencia principal con otros modelos es que contempla la interacción humana e integración de aplicaciones. Es decir, como proceso podemos encontrarnos “introducir comentario” operación del usuario como “imprimir factura” operación del sistema.

BPM también se conoce como una disciplina de administración de cara a que las organizaciones cambien el pensamiento centrado en los procesos y que reduzcan su dependencia de estructuras tradicionales de territorio y funcionalidad. Una buena solución BPM debe poder ejecutar un proceso modelado por el área de negocio sin que TI tenga que programar una sola línea de código.

Algunos de los componentes de un BPM son un motor de orquestación, herramientas de análisis, Business Intelligence, motores de reglas, repositorios, simulación, optimización e integración como otros sistemas legados.

Ejemplos de BPMS (sistemas que implementan BPM) son Oracle SOA Suit, IBM BPM, BEA AqueaLogic BPMS)

Un proceso de negocio puede ser abrir contacto, comprobar stock, etc.

¿Qué es BPEL?

BPEL (Business Process Execution Lenguaje) es un estándar del lenguaje utilizado para especificar acciones en los procesos de negocio.  Otro estandar más conocido es UML. Un modelo BPEL es similar a una máquina de estados.

Un modelo BPM puede utilizar BPEL como lenguaje para definir los procesos de un negocio.

¿Qué BUS utilizar?

¿Qué es ESB y OSB? ¿Diferencias?

ESB consiste en un combinado de arquitectura del software que proporciona servicios para arquitecturas complejas a través de un bus. Ofrece la tecnología para orquestar sistemas distribuídos, mezclar tecnologías, etc.e

Oracle Service Bus es la solución de SOA Suit Oracle para conectar, mediar y administrar las interacciones entre servicios heterogéneos, aplicaciones y múltiples instalacias de Enterprice service Bus.

OSB es una solución propia de ESB. OSB está formado de otros ESB ya que la solución de Oracle se puede comunicar con otros sistemas que utilicen ESB.

Alguna de las características que destancan estos buses: más rápido y productivo. También ofrecen un transporte nativo para aplicaciones empaquetadas y una serie de elementos que garantizan la seguridad en la red.

¿Con qué comunicar la capa de un servicio con otros servicios, bases de datos y aplicaciones?

¿Qué es EJB? ¿Qué es Tuxedo? ¿Diferencias?

EJB (Enterprice Java Bean) es un API para el estándar de construcción de aplicaciones de negocio basadas en JEE. Lo que permite es proporcionar un modelo de componentes al lado del servidor que  controla las transacciones, persistencia, seguridad, comunicación junto con CORBA, eventos mediante JMS, etc.  Ojo! no hay que confundirse con Java Bean que hace de contenedor de objetos pero no pueden utilizarse en invocación remota.

Tuxedo (Transaction for Unix , Extended by Distributed Operations) es una plataforma middleware que se utiliza para gestionar procesos transaccionales de procesos distribuídos en entornos de programación distribuída (definición de la Wikipedia) .  EJB y Tuxedo ofrecen la misma solución con diferente arquitectura.  EJB es un API (conjunto funciones y procedimientos que ofrece una biblioteca para ser usado por otro software como capa de abstracción),  mientras que Tuxedo es un middleware (plataforma de middleware para comunicarse con otras aplicaciones, software, redes, servicios).

Conexión entre Tuxedo/EJB con WDSL

No existe conexión. Tuxedo o EJB se encarga de llevar las transacciones o llamadas al modelo en el lado del servidor mientras que WDSL se utiliza para modelar el proceso de negocio. WDSL tiene su conexión con el lenguaje BPEL que es el que define los procesos del negocio que se está desarrollando.

Por ejemplo, una vez definido el leguaje del flujo de negocio (comprobar si hay strock, si -> facturar , no -> fin) un proceso BPEL se expone al resto como si de un servicio web se tratara y debe tener su propio descriptor WSDL. Tendremos tantos WSDL como procesos BPEL se definan.

Para tener una visión más detallada véase el siguiente artículo de Adictos al trabajo.

Ejemplo genérico

Existe una empresa muy bonita y muy hermosa en la que deciden  rediseñar la arquitectura de forma que reutilicen muchas funciones en diferentes aplicaciones que disponen distribuídas. Para desacoplar esto lo que se hace es diseñar una arquitectura SOA en la que las funciones pasan a estar en los servicios web para llamarla desde cualquier aplicación.  Estos servicios los alojan en diferentes web service  y con un lenguaje distinto de programación.

Un equipo de negocio que describe detalladamente el proceso negocio de una actividad a modo narrativo.

Un equipo de arquitectura recibe las descripciones y transforma que para un proceso en concreto, necesita los siguientes servicios:

  •  Abrir un contacto
  • Generar factura
  • Enviar factura

¿Cómo implementamos todo esto? Tendremos que nutrirnos de muchas herramientas y tecnologías orientadas a SOA para dar una solución.

En el siguiente diagrama vemos la estructura de nuestra arquitectura final. En la parte de arriba están las aplicaciones, en medio el bus que conecta y realiza el flujo de información y abajo los servidos web que contienen los servicios que necesitaremos para realizar un negocio de una aplicación.

Esquema SOA
Esquema de solución SOA

Centrándonos en la aplicación. ¿Qué haremos? Definiremos mediante una máquina de estados los servicios que hemos dicho que nuestra aplicación necesita siguiendo el model BPM y el lenguaje BPEL. Herramientas como Netbeans con OpenESB permiten crear módulos BPEL que contienen definidos los procesos mediante estados. Otra herramienta es JDeveloper de Oracle también nos permiten generar diagramas BPEL.

Los diagramas BPEL se traduce por la propia herramienta en un fichero WDSL. Este fichero WDSL contendrá la lógica de llamadas al estilo “llama al web service A que contiene el servicio “Abrir factura”.  Para ejecutar estos procesos nos valdremos de herramientas como el BPEL Process Manager que utiliza Oracle.

Desde la aplicación al servidor viajaran por el bus, más en contreto un ESB que contiene lógica más compleja para poder comunicar servicios de diferentes lenguajes.

Los servicios se tendrán que nutrir de la base de datos. Cuando nosotros llamamos a “Abrir contacto” necesitaremos obtenerlo de la base de datos.  Para ello existen más tecnologías. EJB es un API para el desarrollo de aplicaciones en java JEE. Lo que hace para el programador es abstraer los problemas de persistencia, transacciones, etc. Este API se alimenta de más soluciones como CORBA, JMS, etc. Es una capa próxima al servidor para abstraer la lógica y comunicar servicios, aplicaciones y bus.

¿Proximos pasos?

  • Profundizar en modelos BPM y lenguaje BPEL.
  • Implementar el ejemplo como el que muestra el siguiente post.

Bibliografía:

Se agradece comunicar comentarios, opiniones, consejos y erratas.

Si te parece interesante compartir es vivir.

Introducción a la arquitectura web

En este mini-tutorial se explica toda la infraestructura que hace falta  para que desde un fichero html puedas ver el resultado en un navegador web.

Una web está formada por texto, imágenes, información almacenada en bases de datos, etc.

Un programador genera ficheros desde herramientas de programación. En este turorial se responde a cómo y con qué infraestructura se necesita para su visualización.

Introducción a la arquitectura web

Para que el usuario quiera ver una página web debe hacer uso de un  navegador. Este navegador lanza peticiones HTTP  que por debajo tiene TCP y de la misma forma accederá al servidor.

Arquitectura web
Arquitectura web

¿Cómo funcionan las peticiones HTTP?

¿Qué es HTTP 1.0?

Cuando lanzas una petición por HTTP mandamos un paquete de información y nos devuelve otro paquete de información.

Los métodos de petición más extendidos son GET y POST.

La petición GET es a través de URL mientras que la petición POST es encapsulada por HTTP.

¿Qué es el protocolo HTTP 1.1? ¿En qué se diferencia con HTTP 1.0?

La gran diferencia de HTTP 1.0 y HTTP 1.1 es que con esta última versión se puede hacer peticiones a otros servidores que escapen a nuestra configuración de Apache. Por ejemplo si en nuestra página web tenemos una foto sacada de otra página web, la petición GET sabe a qué servidor hacer la petición y redirigirla.

El paquete HTTP nos puede devolver un error. Los más comunes que veremos son 404 (Page not fount) y 301. El sitio ha sido redireccionado.

En el mismo enlace de la wikipedia aparece el listado completo de códigos que nos puede devolver HTTP.

¿Qué es un servidor web?

¡Ojo! Servidor web no es lo mismo que servicio web. (web service). Veamos las diferencias.

Un Servicio web o web service es una tecnología que utiliza un conjunto de protocolos y estándares que sirven para intercambiar información entre aplicaciones. Un ejemplo: si yo quiero saber el tiempo que hace en Zaragoza, me puedo valer de un Web Service de otro programador para obtener dicha información.  En este post lo explican muy bien.

Un servidor web o servidor HTTP es un programa informático que procesa una petición en el lado del servidor.  El código que recibe el cliente es compilado y ejecutado en un navegador web. Por ejemplo un Servidor web Apache.

Si se está liando más es necesario  dar un paso a atrás en comprender qué es un Servidor.  Un servidor es un nodo que ofrece servicios para otros clientes en una red. Ejemplo de servidores: servidor web, servidor de bases de datos, servidor de fax, servidor de correo, etc.

¿Qué hace un servidor HTTP Apache?

Si montamos la arquitectura servidor HTTP Apache esta formado por módulos que yo activo o desactivo como puede ser el módulo php, rewrite, etc (véase todos los módulos aquí) y por una configuración para que sepa qué hacer con cada tipo de fichero. Por ejemplo, si Apache recibe una petición hola.phg -> es un nime/types y sé que tengo que devolver el .png con la imagen.

Mime type es un protocolo para saber interpretar un objeto o un archivo de una forma o de otra.

Un ejemplo de módulo: en Apache podemos configurar mod_rewrite. Es un módulo que sirve para personalizar nuestras URL de peticiones. Para saber más aquí hay una guía básica.  Aquí puedes saber si lo tienes activado o no.

¿Qué es mod_rewrite?

Por ejemplo que si todas nuestras peticiones vienen GET /hola/mundo podemos crear un patrón de redirección para que lo interprete como esta petición GET/ index.php?/hola/mundo

¿Para qué sirve mod_rewrite?

De esta forma evitamos que si alguien pone en nuestra web index.php?/hola/mundo no acceda a nuestro contenido de forma arbitraria.

Ejemplo genérico

Ahora. Tenemos nuestra página web. ¿Qué pasa cuando lanzamos la petición www.google.com?

Le pediremos a apache que interprete nuestro PHP y nos servirá por separado los mime types text/html, image/pneg, text/javascript.

De hecho. Siguiendo la imagen de debuger de Firebug podemos diferenciar las peticiones HTML, CSS, JS, XHR, Imágenes, etc que está pidiendo al servidor para que me las muestre en mi local.

En la siguiente imagen vemos cómo lanza la petición para obtener el logo de google.

También estamos descargando ficheros javascript porque javascript se ejecuta en nuestro navegador. Y en un momento determinado de nuestra navegación de la página web, se ejecutará.

¿Qué necesita nuestro navegador?

Nuestro navegador por tanto necesitará al menos:

El servidor web también nos devuelve una estructura DOM. La podemos observar también desde el debuger.

¿Pero qué es DOM?

Es una estructura que se acaba de actualizar con tu petición. Obtiene todos los elementos identificados y estructurados en forma de árbol.

¿Para qué sirve un DOM?

¿Qué utilidad podemos sacarle al DOM? Poder acceder a cualquier elemento de esta estructura en un momento asíncrono. Si por ejemplo pulsamos un botón y queremos que ese botón cambie de color, no hace falta refrescar toda la página. Podemos acceder al botón por medio del identificador y cambiar sus propiedades del HTML y así no hace falta refrescar toda la página.

¿Cómo modifico un elemento del DOM?

Por medio de Javascript .

Siguiendo con el ejemplo de cambiar las propiedades de un botón sin tener que refrescar el código, podemos llamar una función de nuestro javascript que nos hemos traído desde el servidor web  y cambiar las propiedades.


<script type="text/javascript">// <![CDATA[
function bgChange(bg)
{
document.body.style.background=bg;
}
// ]]>

<h2>Change background color</h2>
Mouse over the squares!
<table style="width: 300; height: 100;">
<tbody>
<tr>
<td style="background-color: khaki;" onmouseover="bgChange(this.style.backgroundColor)" onmouseout="bgChange('transparent')"></td>
<td style="background-color: palegreen;" onmouseover="bgChange(this.style.backgroundColor)" onmouseout="bgChange('transparent')"></td>
<td style="background-color: silver;" onmouseover="bgChange(this.style.backgroundColor)" onmouseout="bgChange('transparent')"></td>
</tr>
</tbody>
</table>

Complicando las cosas.

¿Qué pasa si queremos obtener los datos del usuario?

Los datos del usuario están en una base de datos. Es decir, estos datos están en servidor y los queremos traer hasta nuestro navegador.

Por medio de AJAX obtendremos los datos del servidor.

Si esta vez queremos que el botón al pulsarlo nos traiga un listado de países, es necesario AJAX.

AJAX es una técnica no un lenguaje. Extraigo la definición de la wikipedia:

“AJAX, acrónimo de Asynchronous JavaScript And XML (JavaScript asíncrono y XML), es una técnica de desarrollo web para crear aplicaciones interactivas o RIA (Rich Internet Applications). Estas aplicaciones se ejecutan en el cliente, es decir, en el navegador de los usuarios mientras se mantiene la comunicación asíncrona con el servidor en segundo plano. De esta forma es posible realizar cambios sobre las páginas sin necesidad de recargarlas, lo que significa aumentar la interactividad, velocidad y usabilidad en las aplicaciones

Ajax es una tecnología asíncrona, en el sentido de que los datos adicionales se solicitan al servidor y se cargan en segundo plano sin interferir con la visualización ni el comportamiento de la página. JavaScript es el lenguaje interpretado (scripting language) en el que normalmente se efectúan las funciones de llamada de Ajax mientras que el acceso a los datos se realiza mediante XMLHttpRequest, objeto disponible en los navegadores actuales. En cualquier caso, no es necesario que el contenido asíncrono esté formateado en XML.

Ajax es una técnica válida para múltiples plataformas y utilizable en muchos sistemas operativos y navegadores dado que está basado en estándares abiertos como JavaScript y Document Object Model (DOM).” Wikipedia.

Con Ajax también modificados el contenido del DOM sin actualizar la página




<script type="text/javascript">// <![CDATA[
function loadXMLDoc()
{
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();
}
// ]]></script></pre>
<div id="myDiv">
<h2>Let AJAX change this text</h2>
</div>
<pre>
<button onclick="loadXMLDoc()" type="button">Change Content</button>


De esta forma desde nuestra página web, lanzamos una función ajax donde le indicamos a que módulo, función y parámetros pasarle para que nos devuelva nuestro listado de la base de datos. Accederá a la función. Pero, ¿qué tiene que devolver para que me entienda AJAX? puede devolver HTML o un JSON.

¿Cómo obtener la información que me devuelve AJAX?

¿Qué es JSON?

JSON es un objeto que puedo enviar para interpretarlo en diferentes partes de mi página.

En php lo creamos así.

$obj = new StdClass();
$obj->rowsTotal    = $total;
$obj->data = $users;
$this->JSON($obj);

¿Para qué sirve un JSON?

Para comunicar información. Por ejemplo. Cuando invocamos a AJAX nos puede devolver un JSON. Es información estructurada que garantizamos que nuestro destinatorio nos entienda.

Siguiendo con el ejemplo de obtener el listado de paises vamos a ver un ejemplo con javascript que contemplan AJAX para objener los datos y JSON para comunicarlos a donde quiera.

// Función que a partir de un tipo de configuración. Llama al controlador para obtener los datos de esa configuración que ha cambiado. Devuelve el JSON con los cambios del html


$.fn.loadCountryOrganizations = function(){
$("#parent_country_organization_id").attr("disabled","disabled");
$("#parent_country_organization_id").html("
Cargando...
");
$.getJSON(
urlLoadCountryOrganizations,
{
country_configuration_id: $("#country_configuration_id").val()

},

function(data){

var sHTML = "";

$.each(data, function(idx, value){

sHTML += "
"+value+"
";
});
$("#parent_country_organization_id").html(sHTML);
          $("#parent_country_organization_id").removeAttr("disabled");
}
);
}

Vemos que hemos obtenido el objeto JSON con getJSON.

La sintaxis es

$(selector).getJSON(url,data,success(data,status,xhr)).

Ejemplo genérico del flujo

En el siguiente diagrama podemos hacernos una idea del flujo del intercambio de información que tiene nuestra arquitectura web usando un navegador, un servidor web, Javascript, PHP y AJAX.
Arquitectura web basada en PHP, JavaScript & AJAX.
Arquitectura web basada en PHP, JavaScript & AJAX. Imagen obtenida del siguiente post.

¿Proximos pasos?

  • Modelo MVC.
  • Profundizar en JavaScript, AJAX, JQuery, JSON.

Bibliografía:

Se agradece comunicar comentarios, opiniones, consejos y erratas.

Si te parece interesante compartir es vivir.

Cómo utilizar el patrón de diseño Factory en un caso de ladrones de un país. Fácil y sencillo como la vida misma

Imaginemos aleatoriamente y usando la imaginación que existe un país llamado “OtrasDesvirtudes”.

En este país roban los banqueros, los políticos, los jueces y miembros de la real-desvirutd. El gobierno-desvirtud ha hecho una aplicación  (encargada al hijo del dirigente) para que puedan robar(); Los usuarios se autentifican y aparece un botón enorme “ROBAR A LOS PRINGADOS DE SIEMPRE QUE PAGAN DIGNAMENTE SUS IMPUESTOS”.

Lo que pasa! que cada uno en función de su puesto, roba de diferente forma:

– Los banqueros (altos dirigentes): piden rescate monetario para hacerse unas pensiones vitalicias de cifras orbitales para finalmente, declarar suspensión de pagos.

– Los políticos: Se quedan comisiones por asignaciones de obra, rectificar terrenos y viajes inexistentes.

– Los jueces: sobornos y viajes inexistentes.

– La real-desvirtud: crea empresas que no existen para recibir subvenciones.

Caos!!! tenemos distintos robos para distintas personas!! cómo lo haremos de forma transparente!! de forma que sea sólo “robar” y que cada uno se las apañe como mejor pueda robar.

La persona que hace la aplicación letal, se le ocurre la brillante idea, de aparte cobrarles más por facinerosos, contratar a su “amigo informático” para que le haga la aplicación de gratis.

El “amigo informático” dados sus conocimientos letales utilizar el patrón de diseño Factory. La idea aplicada a Java, sería de la siguiente forma:

Una clase abstracta RobarFactory().

public abstract class RobarFactory {

    private static int defaultFactoryType = 1;

    public static final int BANQUERO = 1;

    public static final int POLITICO = 2;

    public static final int JUEZ = 3;

    public static final int REAL-DESVIRTUD = 4;



    /**

     * Establece el tipo de factoria por defecto

     * @param type Tipo de factoria de los aceptados

     */

    public static void setDefaultFactoryType(int type){

        defaultFactoryType = type;

    }


    /**

     * Devuelve el Factory adecuado para el tipo establecido por defecto

     * @return Factory del tipo establecido

     * @throws Exception

     */

    public static RobarFactory getRobarFactoryDefault() throws Exception{

        return getRobarFactory(RobarFactoryType);

    }


    /**

     * Devuelve el Factory para el tipo indicado en el parametro type

     * @param type Tipo de Factory a utilizar

     * @return Factory del tipo indicado

     * @throws Exception

     */

    public static RobarFactory getRobarFactory(int type) throws Exception{

        DAOFactory factory = null;

        switch(type){

            case RobarFactory.BANQUERO

                factory = new BANQUEROFactory();

                break;

            case RobarFactory.POLITICO

                factory = new POLITICOFactory();

                break;

                

            default:

                throw new TAsistoException(“ERR-0003”, “No existe una factoria para el indicado: ” + type);

        }

        return factory;

    }

    


    //metodos abstractos que todas las factorias deberán implementarlos

    /**

     * Devuelve el Dinero robado

     * @return Dinero robado

     */

    public abstract Dinero robar();

Ya tenemos la factoría hecha. ¿Dudas? Con lo fácil que es robar!

Cuando se autentifican se pone setFactoryDeflautType al tipo de la persona y devolveremos su factoria con getRobarFactory(). Porque ojo! todos roban de diferente forma. Por ejemplo: se autentifica el político, se pone setFactoryDeflautType a 1 y se cargará su factoría POLITICOFactory()

Pero su función no es robar(); es robarPolítico(); lo que pasa que queremos que en la aplicación aparezca un sólo robar(), ya que el objetivo es que se unan más miembros (factorías) en el futuro y que se añadan nuevas funciones propias como estafar(), defraudarHacienda(), etc.

Así que implementamos las funciones abstractas, en este caso, robar()

/**

 *

 * @author llacarra

 */

public class POLITICOSFactory extends RobarFactory {


    /**

     * Devuelve el Robar para trabajar con usuario en una base de datos Mysql

     * @return Dinero robado

     */

   @Override

    public Dinero robar(){

        return new robarPolitico();

    }

   

   @Override

    public Dinero estafar(){

        return new estafarPolitico();

    }

Así una factoría con sus funciones por cada miembro ladrón del país. 

De esta forma. El amigo informático ha conseguido que la aplicación llame a un sólo “robar()” y que por medio de la factoría abstraiga la lógica de la función. En algún sitio, deberá estar implementada la función de estafarPolitico(), o en esta misma clase puede estar la función desarrollada.

Se puede hacer que desde la misma base de datos cargue esa configuración, de forma que dependa menos de la aplicación.

Así da igual que miembro del país acceda… que robará igualmente, fácilmente, e independientemente de su puesto.  Bravo, bravísimo!!!