¿ Eventos o señales ?



El sistema de eventos de ActionScript 3 ha sido objeto críticas en los últimos tiempos. Indudablemente es una de las piezas claves sobre las que se sustenta el desarrollo de aplicaciones Flex/Flash y de ahí su amplia utilización. A continuación resumiremos las más relevantes.

Los eventos.

Los eventos se identifican mediante un tipo de dato “String”, definido como una constante pública y estática, el mismo dato que se utiliza para registrar un manejador para ese evento. Eso implica que como desarrolladores debemos ser cuidadosos en escoger un valor que identifique de forma única al evento, de lo contrario podemos observar un comportamiento que no es el esperado en nuestras aplicaciones.

La semántica de este valor es otro elemento a tener en cuenta. Si estamos construyendo un API o un componente que será utilizado por otros desarrolladores es muy importante escoger un valor que exprese lo que representa el evento en sí, no solamente la palabra que representa la acción, sino también el tiempo verbal adecuado, para evitar confusiones acerca del momento en que se despacha el evento.

Si queremos crear eventos personalizados, que porten información relevante del contexto en el que los estamos utilizando tenemos que heredar de “Event”, no hay una interface IEvent o algo similar que permita que una clase del dominio pueda actuar como evento.

Una vez que hayamos heredado de “Event” debemos sobrescribir el método clone, para que cuando el despachador de eventos redespache el evento (en caso que sea necesario) obtenga una copia del evento original. Quiere esto decir que si en nuestra aplicación tenemos muchos eventos personalizados terminaremos escribiendo bastante código (aunque tenemos como alternativa utilizar la clase “DynamicEvent”, no se recomienda esta opción ya que no podremos hacer chequeo de tipos en tiempo de compilación y detectar errores de asignación, etc).

Los despachadores de eventos.

El método addEventListener, de la clase “EventDispatcher” tiene la siguiente definición:

[ftf w=”500″ h=”100″]
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
[/ftf]

El argumento “useWeakReference” es muy utilizado cuando se quiere que el mecanismo de recolección de basura elimine los objetos que contienen manejadores de eventos, pero como vemos es el último argumento en la lista. De modo que si frecuentemente utilizamos un valor “true” en este argumento y los valores por defecto en los argumentos “useCapture” y “priority”, el método se invocaría de la forma:

[ftf w=”500″ h=”100″]
objeto.addEventListener (TIPO_DEL_EVENTO, manejador_del_evento, false, 0, true);
[/ftf]

Al parecer, es común entre los desarrolladores invocar el método de esta forma, por lo cual se agradecería mucho que la lista de argumentos fuera:

[ftf w=”500″ h=”100″]
addEventListener(type:String, listener:Function, useWeakReference:Boolean = false, useCapture:Boolean = false, priority:int = 0):void
[/ftf]

En la clase “EventDispatcher” no existe un método que permita eliminar todos los manejadores de eventos de una sola vez.
Si se hereda de “EventDispatcher” a fin de crear un despachador personalizado y modificar su comportamiento, como un control personalizado de los manejadores de eventos, nos encontramos que no podemos acceder a la lista de manejadores, la clase tiene un diseño cerrado.

Por otra parte, aunque existe la interface “IEventDispatcher”, crear una clase que haga un tratamiento personalizado de los manejadores de eventos y que implemente la interface no funcionaría del todo, ya que la propiedad “target” de la clase “Event” es de solo lectura y solo la clase “EventDispatcher” es capaz de asignarle valor. De modo que la clase “Event” y “EventDispatcher” se diseñaron para trabajar juntas.

aS3-signals.

Existe un proyecto denominado as3-signals que plantea una alternativa al sistema de eventos de ActionScript 3 y que tiene en cuenta todos los inconvenientes anteriores. El proyecto está inspirado en el sistema de eventos de C# y en las signals/slots de Qt. La idea central es que en vez de tener un objeto (“EventDispatcher”) capaz de despachar cualquier tipo de evento a cuanto manejador se haya registrado, se utilizan objetos que contienen su propia lista de manejadores y cuya semántica representa un evento en específico. De esta forma el evento está identificado por el objeto en sí y no por un tipo de dato “String”, como ocurre en la clase “Event” y sus derivadas.

Un objeto “Signal” se define como un mini despachador específico para un solo evento, que contiene su propia lista de manejadores. Cuando se crea un objeto de este tipo se especifican los tipos de datos de los argumentos del método “dispatch”, que es el que invoca a los manejadores que se hayan registrado. De este modo el número de argumentos de los manejadores deben coincidir con los especificados en la creación del objeto.

Como funcionalidad distintiva tiene que permite eliminar todos los manejadores a una vez, a través del método “removeAll”, permite registrar un manejador que sea invocado una sola vez y luego automáticamente eliminado de la lista de manejadores, mediante el método “addOnce”, y permite conocer en cada momento la cantidad de manejadores registrados.
Básicamente el flujo de trabajo sería:

1. – Crear el objeto “Signal”:

[ftf w=”500″ h=”100″]
public var userLogged:Signal = new Signal(Boolean);
[/ftf]

O heredando de “Signal”

[ftf w=”500″ h=”200″]
public class UserLogged extends Signal{
public function UserLogged(){
super(Boolean);
}
}

public var userLogged:UserLogged = new UserLogged();
[/ftf]

En este caso el objeto representaría si el usuario ha ingresado a la aplicación, sería el equivalente a

[ftf w=”500″ h=”100″]
public static const USERLOGGED:String = “USERLOGGED”;
[/ftf]

si estuviéramos utilizando un evento personalizado.

2. – Adicionar manejadores

[ftf w=”500″ h=”100″]
userLogged.add(userLoggedHandler);
[/ftf]

O, si queremos que el manejador se invoque solamente una vez y sea eliminado de la lista automáticamente después de invocado:

[ftf w=”500″ h=”100″]
userLogged.addOnce(userLoggedHandler);
[/ftf]

La sintaxis del manejador quedaría:

[ftf w=”500″ h=”100″]
private function userLoggedHandler( value:Boolean ):void
[/ftf]

3. – Despachar el evento

[ftf w=”500″ h=”100″]
userLogged.dispatch(true);
[/ftf]

Cualquier intento de invocar el método “dispatch” con un argumento que no sea “Boolean” o con 0 o más de un argumento causará una excepción de tipo “ArgumentError”.

En el proyecto se incluyen cuatro tipos de “Signals”,

  • “Signal”: Representa el comportamiento básico, que hemos descrito anteriormente.
  • “DeluxeSignal”: Este tipo de “Signal”, a diferencia del anterior, permite asociar el evento a un objeto en particular, el que se pasa en el constructor; de modo que si el argumento del método “dispatch” es de tipo “IEvent”, encapsulará información del objeto asociado, y el propio objeto “DeluxeSignal”, la cual estará disponible en los manejadores. Permite además asignar prioridades a los manejadores.
  • “NativeSignal”: Permite encapsular un evento nativo de ActionScript, el constructor toma como argumento un “EventDispatcher, un “String” que identifica el tipo del evento y un “Class” que identifica la clase del Evento (“Event” por defecto). Cuando se registra un manejador se registra en el “EventDispatcher”, el mismo que se utiliza para despachar los eventos. Todas las funcionalidades básicas, como eliminar todos los manejadores a la vez, registrar y despachar manejadores que se invocan una sola vez, etc., se ejecutan sobre el “EventDispatcher”. Permite también asignar prioridades a los manejadores. Esta clase da la posibilidad de un manejo homogéneo de eventos dentro de la aplicación.
  • “NativeRelaySignal”: Ofrece las mismas funcionalidades que “NativeSignal”, pero se diferencia de ésta en que tiene su propio mecanismo para despachar eventos, no delega esta responsabilidad en el “EventDispatcher” que se pasa como argumento en el constructor, como sucede con “NativeSignal”.

Las “Signals” en el contexto de la Inversión de Control.

Normalmente cuando usamos el sistema de eventos de ActionScript el flujo de trabajo consiste en crear un evento (de la clase “Event”) asignándole su tipo en el constructor y despacharlo usando un “EventDispatcher”, ó en muchos casos, creando eventos personalizados (heredando de “Event”), asignar alguna carga útil y despacharlo. Constantemente estamos creando y despachando eventos.

El flujo de trabajo de las “Signals” hace que sea muy conveniente utilizarlas con frameworks que utilicen Inversión de Control, en este caso solo debemos crear el objeto “Signal” como un singleton en el framework (no es necesario implementar el patrón Singleton, solamente se debe indicar al framework que cree una sola instancia de la clase y que devuelva siempre la misma referencia), e inyectar la referencia en cuanto componente sea necesario (vistas, modelos, comandos, mediadores, etc.), de esta manera disminuiríamos notablemente la tarea de creación de objetos relacionada con los eventos, algo que siempre resulta costoso.

Conclusiones.

El proyecto as3-signals ofrece una alternativa interesante al sistema de eventos de ActionScript que podemos utilizar en nuestros proyectos y que puede beneficiarse del uso de frameworks de Inversión de Control.

7 Comentarios

  1. Sergi Dote Teixidor

    Un artículo muy interesante Nono.
    He estado programando muchos años con C++ combinado con las librerías Qt y conozco bien el concepto de signal/slot, que, como bien dices es la manera que tiene de tratar los eventos. No he probado este framework, que nos ofrece la portabilidad del concepto signal/slot al mundo actionscript, por lo que no puedo opinar, aunque tiene buena pinta.

    Es verdad que los Events AS han recibido bastantes críticas, aunque bien usados no tienen porque dar muchos problemas.

    Tendría que probar este framework para ver como poder programar ciertas cosas que nos ofrecen los eventos de flex, como por ejemplo el bubbling para poder trasladar un evento a las capas superiores.

  2. Pingback: Tweets that mention MadeInFlex » Blog Archive » ¿ Eventos o señales ? -- Topsy.com

  3. Pingback: AS3 Signals una Eficiente Alternativa | www.riactive.com

  4. Dano

    Para mí, el manejador de eventos de Flash es de lo mejor que he visto.

    El problema es que es tan bueno y flexible, que la gente le ha dado pésimos usos.

    Dentro de los peores uses que he visto es:
    La gente “bindea”(sabemos que el binding the MXML realmente se transforma en listeners) todo, absolutamente todo.

    Utilizan el bubbling en un componente que tiene como 30 padres.

    No remueven listeners cuando no son necesarios.

    Y entonces nos quejamos que porque el sistema consume muchos recursos.

    Creo que bien utilizados, no hay porque remplazarlos por otra cosa. Yo me centraría en explicar las méjoras prácticas para eventos, en lugar de utilizar señales.

    Sin embargo, no deja de resultar atractivo e interesante, conocer otras alternativas a los eventos de Flash.

    Gracias por compartir,

  5. InKiev

    Creeo que en relacion al comentario que hace Dano, sería bueno hacer un ejemplo y/o compartir algunas direcciones donde se ejemplifique de lo que esta hablando, saludos.

  6. Alejandro HR

    Completamente de acuerdo con Dano. He utilizado técnicas similares a las que usa as3-signals en un mini-framework creado para microsites / banners / apps móviles y he terminado por volver a los eventos nativos, poniendo especial cuidado en su buen uso.

    Entre otros motivos, el principal es por el tamaño del SWF final. No le hecho la culpa al framework, ya que en ocasiones es más rápido y práctico para desarrollar, sino al compilador de flash/flex que duplica el código y usa un sistema de compresión… arcaico.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Acerca de Made In Flex

Made In Flex es una comunidad de desarrolladores de Apache Flex creada en 2006.

Apache Flex, anteriormente conocido como Adobe Flex, es un SDK (kit de desarrollo de software) para crear aplicaciones enriquecidas - multiplataforma basadas en Adobe Flash donado por Adobe a la fundación Apache in 2011 y promocionado a proyecto de primer nivel en Diciembre de 2012.

Actualmente estamos cambiando muchos aspectos del sitio web para ofrecer un sitio útil para toda la comunidad que tenga en cuenta las necesidades actuales.

Últimas Fotos

Instalador de Apache Flex

Entrar o Registrase