sábado, 16 de mayo de 2009

La importancia del Feedback y las pruebas

Recientemente escribi sobre la importancia de recibir feedback en nuestra profesion de infomaticos.
No voy a extenderme mucho al tema, mucho ya lo dije en el post anterior sin embargo hoy quiero hablar un poco sobre la importancia de hacer pruebas y como se relaciona con el feedback.
Veran, las pruebas que hagamos (me gusta usar Fluint para flex y ultimamente estoy probando con Flex Unit 4 - version alpha en este momento) son una forma de feedback para nuestras aplicaciones y para nosotros mismos.
Cuando hagamos cambios grandes o refactoty en nuestro codigo y ejecutemos las pruebas que hayamos realizado sabremos sabremos si los cambios realizados por nosotros han afectado el comportamiento correcto de nuestra aplicacion. Eso tambien es feedback.
Cuando durante el fin de seman un companero de trabajo cambie algo en su codigo y lleguemos el lunes y nada funcione... podemos correr nuestras pruebas y darnos cuenta que es lo que fallo y encontrar la solucion de forma mas rapida (ademas de poder culparlo :o) ). Eso tambien es feedback.
Soy partidario del TDD (Test Driven Development) y reconozco la importancia de las pruebas, como forma de feedback y de asegurar una mejor calidad en mi desarrollo, pero tambien reconozco que a veces el tiempo no alcanza o el cliente no entiende la importancia de estas pruebas. Por eso es necesario ser prudente a la hora de escoger que probar y que no. Como decia una abuela mia "Ni mucho que queme al santo ni tan poco que no lo alumbre". Repito Nada malo con probar, pero tambien ser concientes de nuestros tiempos ya que no siempre tendremos el suficiente tiempo para probar todo.
Mis secciones favoritas para probar, son las que estan en constante cambio y que son criticas:
logica de negocio, acceso a datos (servicios remotos o a base de datos en AIR).
Componentes y vistas me gusta probarlos separados, aislarlos en una aplicacion aparte y probar su funcionamientos, estilos, etc. Eso me provee Feedback. Me gusta aislar las vistas que haga y sus interacciones basicas y proveerlas a quien sea que este a cargo de esa vista, sea el disenador grafico o el encargado del proyecto o cliente del mismo. Que jueguen con la vista por separado en lugar de tener que cargar toda la aplicacion y gastar mas tiempo en proveerme feedback, eso lo pueden hacer en otro momento. Existen herramientas para probar la interfaz como Flex Monkey y Selenium que permite grabar interacciones y ejecutarlas automaticamente. Tambien son validas.
Flex Unit 4 Alpha viene con muchas mejoras y cosas nuevas, verdaderamente lo recomiendo! Aqui mas info

Creando APIs en Actionscript

Recientemente he tenido en mis ratos libres la mania de bajar API's para Actionscript 3 de diferentes servicios que hay por ahi, como Digg, Twitter, Facebook, Salesforce, etc para probarlos, jugar con ellos y hacer alguna aplicacion sencilla con ellos aunque nunca vaya a ser utilizada.
Esto me divierte en realidad y mas importante me ayuda a ver codigo de otras personas, maneras de pensar y de implementar. Creo que es una experiencia enriquecedora. Muchos desarrolladores piensan que ver el codigo de otros es malo, es bajo, es denigrante. Honestamente creo que no! Primero yo escojo de quien veo el codigo y la mayoria de personas que hacen estos APIs son mucho mas competentes que yo! Ademas es una manera de aprender de mejorar y de desarollar mejor. Un claro ejemplo es el acceso que tenemos al framework de Flex. Si algo puedo decir de mi actual trabajo y de los dos maestros de Flex con los que trabajo es que se conocen ese framework de arriba a abajo. De ahi que puedan hacer las cosas que hacen.
Bueno siguiendo con mi fascinacion tan geek de las ultimas semanas, me he puesto a pensar en que requisitos son necesarios para construir un API en ActionScript.

Primero pensemos para que necesitamos realizar un API. Un API es utilizado para ofrecer una serie de servicios que puedan ser invocados por otras aplicaciones con el fin de ejecutar una accion. No es lo mismo que un framework. El API debe ser claro, sencillo y definido. Mejor si esta documentado. Mejor aun si tiene ejemplos. El API debe ser facil de usar, intuitivo y tener todo lo que nuestros futuros clientes vayan a ocupar para interactuar con nuestra plataforma. Incluyendo objetos definidos por nosotros mapeando la informacion de nuestros servicios.

Segundo analicemos la forma en que vamos a entregar nuestra informacion. Aqui desde dos perspectivas distintas:
a) Como se accedera a la informacion que se quiere facilitar (ya pensando en algo mas "fisico"). Esto incluye como se haran los llamados a nuestros servicios: REST Services? Web Services? Remoting? External Calls (como tiene el API de Facebook)? Todo esto debe ser transparente para el usuario de nuestro API. Si acaso lo mas es la opcion de escoger que tipo de canal usar para comunicarse con nuestros servicios, pero la implementacion y demas no debe ser de importancia para el.
b) La forma en que entregaremos la informacion recolectada de nuestros servicios. Si recibimos XML, no podemos pasarle simplemente XML al cliente y dejar que el piense que va a hacer con esa informacion (tecnicamente si podemos, pero no debemos :) ). La creacion de objetos que mapeen nuestro servicio hace que nuestro API sea mas facil de usar.

Tercero consideremos en la naturaleza Asincronima de nuestra plataforma. Cuando hacemos una invocacion a un servicio externo sea por WebService, Remoting o simple REST Services no sabemos cuando vamos a recibir la informacion de vuelta. Esto hace que nuestros APIs no sean tan facil de usar cuando invocamos servicios remotos como hacer:

var misUsuarios:ArrayCollection = miAPI.cargarUsuarios(); //ESTO NO FUNCIONA!!

El metodo cargarUsuarios puede demorar un tiempo (incluso has segundos) en devolvernos esta informacion, asi que la asignacion a mis usuarios no va a ser correcta.

Soluciones:
a) Una forma de hacerlo es pasarle al metodo el arraycollection que queremos cargar y cuando se reciba la informacion se carguen los resultados en esa variable pasada como parametro. Recordemos que nuestros objetos en AS3 se pasan por referencia y no por valor, asi que los cambios que hagamos al objeto pasado por parametro, se reflejaran en nuestro objeto original (a menos que se haga una copia del mismo. En lo personal la siento como valida, pero no es aplicable en todas las ocasiones. A veces ocupamos darnos cuenta cuando algo fue procesado y eso se logra a traves de eventos.

b) Otra forma de hacerlo es atraves del uso de eventos. Cuando nuestra funcion recibe el resultado, esta manda un evento indicando que fue recibido. Anadiendo un event listener a ese evento, podemos procesar esa informacion desde donde queramos. Algo importante es aislar cada llamada o cada proceso de datos por aparte, para que cada llamada despache un solo evento, en lugar de estar llamando handlers de otras locaciones por eventos que se invocan con otros propositos. Por supuesto es importante recordar el removeEventListener una vez que es ejecutado un event handler que no se ocupa tener mas y poner las referencias como weak, pero igual si no se aislan las llamadas pueden crear conflictos.

Esta practica es seguida en el API para Facebook, a continuacion parte del codigo de uno de sus ejemplos:

var call:AddComment = new AddComment(story_id, body);
call.addEventListener(FacebookEvent.COMPLETE, onAddComment);
facebook.post(call);


onAddComment Va a encargarse de utilizar la informacion recibida como se quiera, puesto que ya esta informacion viene procesada y convertida en el tipo de dato que se quiere todo esto cuando se despache el evento de Complete.

c) Otra forma de hacerlo, es aislando el resultado de la funcion invocada y que ella se encargue de manejar el resultado. Esto es como lo que hacen con el API de Digg . Esto es delegar la llamada y el procesamienta del resultado y posterior conversion a objetos normales a un objeto que es devuelto por nuestra funcion invocada. Por ejemplo:

Del API de DIGG

public static function getUser(user:*):UserResponse
{
var request:URLRequest = new URLRequest(getUserURL(user));
return load(request, new UserResponse()) as UserResponse;
}


Esta clase devuelve un UserResponse, que hereda de la clase Response que a su vez es la que hace el llamado al servicio y delega en UserResponse el procesamiento y conversion del resultado en un objeto utilizable en la aplicacion y no simple XML.

Como ven, enfoques distintos, pero el mismo principio aislar la invocacion para que pueda ser tratada como una llamada distinta.

Espero esto pueda ayudar a otras personas que tengan que crear APIs para servicios externos para AS3 o que anden buscando como ingresar a esto de APIs y servicios externos y que puedan de este humilde texto encontrar algo que les ayude
Disfruten...