miércoles, 23 de enero de 2008

Eventos en Flex

Los eventos en AS3 son a mi parecer la clave que permite crear RIAs interactivas, agradables y completas.
Un evento es generado la mayor cantidad de veces por la interaccion del usuario (tambien conocido como gestos) con el sistema (un boton, un campo de texto, cualquier interaccion que se haga por mouse o teclado). Algunos eventos son generados por el sistema automaticamente.
Los eventos son maneras eficaces para realizar aplicaciones con un acoplamiento bajo, esto debido a que la comunicacion se da a traves de ellos, un componente dispara un evento y solo se preocupa por eso. Si algun otro componente o contenedor ocupa de ese componente recibira el evento y procedera a realizar la funcionalidad que requiera con ese evento y la informacion que el contenga, sin conocer absolutamente nada del componente ni siquiera saber quien lo envio.
Otra cosa muy interesante de los eventos es que uno puede crear sus propios eventos customizados, descendiendo de la clase Event. Aqui un ejemplo:

package{
import flash.events.Event;

public class miEvento extends Event{
public static const AGREGAR_PERSONA:String = "AgregarPersona";

public var nombre:String;
public var apellidos:String;
public var action:String;

public function miEvento(action:String,nombre:String,apellidos:String,bubbles:Boolean=false,cancelable:Boolean=false){
super(action,bubbles, cancelable);
this.action = action;
this.nombre = nombre;
this.apellidos = apellidos;
}

override public function clone():Event{
return new EventoEvent(action, nombre, apellidos, evento);
}
}
}

En este ejemplo simple y chapucero, se pasan dos variables, nombre y apellidos que seran seteadas por el disparador del evento y que podran ser recolectadas por cualquier componente O o contenedor que este interesado en recibirlo. Nota, se pueden incluir clases para encapsular la informacion o incluso clases de cualquier tipo que se hayan creado.

Existen 3 fases de propagacion, durante los eventos:

1. Capturing: De arriba a abajo.
Un componente dispara un evento y Flex se encargara de buscar desde el contenedor mas afuera de ese objeto (generalmente el application) hasta el contenedor directo del componente mismo. Cada vez que va cambiando de componente, la variable currentTarget del event va cambiando. Cabe aclarar que los eventos tienen dos propiedades importantes: target y currentTarget.
El target en los eventos de AS3 se refiere al que emitio o disparo el evento y el currentTarget se refiere al nodo u objeto que se esta chequeando por EventListeners. No se, talvez a los de Adobe no les dio mas para ponerle otros nombres pues es algo confuso... Con estas dos propiedades podemos averiguar quien hizo quien y quien va a encargarse de...
Ejemplo:
Tenemos esto:
Application -->
Canvas -->
Button

El Capturing buscaria por event listeners en este orden: Application, Canvas.
Si existieran mas capas arriba del button, pues se revisaria en cada una de estas si tenian event handlers en cada una de ellos. El default del capturing es false.

2. Targeting:

Es el mas sencillo, solo se revisa por event listeners dentro del componente que dispara el evento, como cuando se define en el boton la propiedad click="funcion()". Esto ademas indica que el target y currentTarget son los mismos.

3. Bubbling: De abajo para arriba.
Es el contrario al Capturing
Ejemplo:
Tenemos esto:
Application -->
Canvas -->
Button

El Bubbling buscaria por event listeners en este orden: Canvas, Application.
Flex buscara event listeners hasta que se le permita. Puede ser que llegue hasta al application o puede ser que se le pare en el contenedor siguiente al componente que despacha el evento, en este caso el Canvas. El default del bubbling es false.

Tanto para capturing como para bubbling, es posible el parar la propagacion desde un listener que se quiera, con stopPropagation() y stopImmediatePropagation().

Lo mejor en la propagacion es ver cual es la que mejor sirve para su aplicacion para optimizar tiempos. Por ejemplo si solo ocupa targeting, deje bubbling y capturing en false. Si ocupa capturar un evento solamente desde el contendor del componente, pues user bubbling. Si lo ocupa hacer desde mas afuera, pues hagalo con capturing. Si ocupa capturar el evento por alguien mas que el target y no usen bubbling o targetting no se va a poder capturar los eventos lanzados a no ser que agregue el listener al contenedor, pero no siempre se puede hacer.

Esto es algo muy basico, pero necesario y que hay que estar revisando casi todos los dias para comprenderlo mejor. Cuando se dominen los eventos en Flex, estoy seguro que tendra un 80% de lo escencial dominado.

miércoles, 16 de enero de 2008

Patron de Comando en Actionscript

Patron de Comando:

Es un patron de comportamiento, que nos permite eliminar el acoplamiento entre objetos.
Ejm:

Objeto A ocupa invocar un servicio del Objeto B. Generalmente se hace a traves de la invocacion directa del servicio ObjetoB.method();
Eso genera un acoplamiento alto, debido a que de esa forma, Objeto A ocupa saber los metodos del Objeto B y si los mismos se llegaran a cambiar alteraria (nombre, firma, etc) la compilacion del Objeto A daria error y habria que modificarlo ahi o en cualquier otro objeto que invoque ese servicio.
Para evitar esto, se procede a crear una clase intermedia (el command), que sera la que conocera todo acerca de la clase B y la cual sera invocada por la Clase A, para ejecutar la tarea.
El Command no se preocupa por la respuesta que se genera o a quien debera retornarla, solo ejecutarla.
Esto se hace a traves de la definicion de una Interfaz con el metodo execute (o ejecutarAccion o ejecutar o como se quiera, pero que todos los comandos implementen ese metodo)

Ejemplos:

Sin Command:

ObjetoA -- invoca metodo --> ObjetoB

Con Command:

ObjetoA -- invoca execute --> Command -- invokes metodo --> ObjetoB

La ejecucion de la accion es desconocida por el que la inicio y eso permite que no exista acoplamiento entre componentes ni objetos y que al mismo tiempo las modificaciones que se hagan mas adelante, no generen errores en clases o componentes que ya estaban listos.
Esto es basicamente lo que sucede con Cairngorm y los comandos que se implementan dentro del framework.

Ejemplo de Codigo (la sintaxis no esta chequeada contra el compilador ni con Cairngorm):

Interface Command

package com.ejemplos.patrones.ejemplo{
public interface ICommand{
public function ejecutar():void; //No devuelve ningun tipo de valor
}
}

Clase CommandoLlamarClaseB

package com.ejemplos.patrones.ejemplo{
public class CommandoLlamarClaseB implements ICommand{

public function ejecutar:void{
var claseB:ClassB = new ClassB();
claseB.llamadoEnClaseB();
}

}
}


Clase A

package com.ejemplos.patrones.ejemplo{
public class ClassB{
public function llamarClaseB():void{
var comando:ICommand = new CommandoLlamarClaseB();
comando.ejecutar();
}
}
}

Clase B

package com.ejemplos.patrones.ejemplo{
public class ClassB{
public function llamadoEnClaseB():void{
trace("Desde Clase B");
}
}
}