miércoles, 20 de febrero de 2008

Recuperando código Java

La semana pasada me cambiaron el ordenador que uso en el trabajo. Estuve anotando todo lo que quería conservar pero por desgracia se me olvido un pequeño proyecto en java que había iniciado un par de semanas antes y no había subido todavía a Subversión. ¡Vaya! Tanto dar la lata a todo el mundo con las bondades de Subversion y sufro un olvido como este.

El caso es que tampoco era una gran pérdida. Para entendernos, se trataba de un prototipo que había desarrollado en un par de ratos para atacar un webservice de otra compañía y todavía estábamos considerando utilizarlo o no. Una de las opciones era darlo por perdido y decantarnos por la segunda opción que estábamos barajando, pero mi amor propio me obligaba a recuperarlo. Por suerte lo había desplegado en el servidor de producción, así que la situación era que tenía el ejecutable pero no el fuente.

Se me ocurrió entonces buscar algo para hacer ingeniería inversa sobre el ejecutable. Tenía el vago recuerdo de que en java daba bastante buen resultado aunque nunca había profundizado en el tema. Después de una breve búsqueda encontré información sobre "decompilers" y después de un breve vistazo me decanté por JAD. En la propia página del proyecto encontraremos algún entorno gráfico para los que no quieran utilizarlo a modo de comando.


El resultado fue bastante bueno. Pude recuperar el fuente de la docena (aproximadamente) de ficheros de la aplicación y sólo encontré un par de errores generados durante el proceso:
  • El primero me dejaba una instrucción después del return de una de las funciones, por lo que nunca se llegaría hasta ella.
  • El segundo fue un bucle for mal formado sintácticamente.

Una vez corregidos pude reconstruir el proyecto y volver a desplegarlo como otra instancia en el servidor. ¡Todo correcto! Curiosamente, el final de la historia es que hemos desestimado el prototipo y finalmente hemos hecho el cliente del webservice en PHP.


Technorati Tags: , ,

domingo, 17 de febrero de 2008

Symfony vs Zend Framework. 2- Comencemos con Symfony

Artículos de la serie:
  1. Definición del problema
  2. Comencemos con Symfony
En el capitulo anterior planteamos una pequeña aplicación para comparar Symfony y Zend Framework. En este parte empezaremos con el primero de los citados no sin antes recordar que, aunque pueda parecerlo en ciertos momentos, esto no es un tutorial ya que no se citan todos y cada uno de los paso dados para llegar a la aplicación final.

Antes de nada... ¡a leer!

Partiendo de unos conocimientos nulos sobre Symfony, si rebuscamos un poco en su portal web, encontraremos una par de cosas interesantes para hacernos a la idea de cómo empezar a trabajar.

http://www.symfony-project.org/tutorial/1_0/my-first-project
http://www.symfony-project.org/book/1_0/

El primero de los enlaces es un tutorial rápido en el que curiosamente se desarrolla un ejemplo muy similar al nuestro. Es obvio que ha resultado bastante útil a la hora de hacer esta prueba. Las principales diferencias con nuestro caso son:
  • Nuestro requerimiento de utilizar una base de datos MySQL.
  • El diseño de nuestras tablas, que no aprovecha las ventajas de las nomenclaturas predefinidas para los ficheros YAML.
  • Nuestro diseño gráfico que aplicamos de una forma bastante realista (como si un equipo de diseño nos lo entregara maquetado)
El segundo enlace es un libro que podremos consultar en formato html, obtenerlo impreso o, incluso, en formato PDF traducido al español gracias a librosweb.es Si bien no es necesario leerlo por completo para realizar este ejemplo de aplicación, no vendrá mal darle un vistazo rápido y tenerlo a mano para consultar alguna duda.

Además de esto tendremos toda la documentación habitual sobre el API a la que podremos recurrir cuando lo necesitemos

Diseñando la BD

Recordamos el diseño comentado en el capítulo anterior según el cual un artículo podía tener muchos comentarios de lectores:



En Symfony tentemos que plasmar nuestros diseños en YAML, así que para el diagrama anterior el archivo schema.yml correspondiente sería:
propel:
blog_articulo:
_attributes: { phpName: Articulo }
idarticulo: { type: integer, required: true, primaryKey: true, autoIncrement: true }
titulo: varchar(255)
cuerpo: longvarchar
fecha_creacion: {timestamp}
blog_comentario:
_attributes: { phpName: Comentario }
idcomentario: { type: integer, required: true, primaryKey: true, autoIncrement: true }

idarticulo: { type: integer, foreignTable: blog_articulo, foreignReference: idarticulo, onDelete:cascade }
author: varchar(255)
email: varchar(255)
body: longvarchar
fecha_creacion: {timestamp}

Una vez más hay que recordar que había una forma más fácil de hacer esto y es realmente la recomendable, consiste en usar ciertos nombres de campos preestablecidos para claves primarias, claves externas y campos de fecha. La siguiente definición se correspondería con ello:

propel:
blog_articulo:
_attributes: { phpName: Articulo }
id:
titulo: varchar(255)
cuerpo: longvarchar
created_at:
blog_comentario:
_attributes: { phpName: Comentario }
id:
articulo_id:
author: varchar(255)
email: varchar(255)
body: longvarchar

created_at:

Después de ejecutar este paso es natural pensar que alguien que se adentre en este framework deberá familiarizarse con el lenguaje YAML y con Propel. Esto incrementa un poco la curva de aprendizaje. Como anécdota basta decir que el que escribe esto perdió bastante tiempo hasta conseguir hacer funcionar el fichero YAML mostrado anteriormente y todo por culpa de un salto de linea que pasaba inadvertido.

Cargando el resultado en mysql

Como ya tenemos nuestro fichero de descripción de la base de datos, continuaremos generando las clases de nuestro modelo, que quedará alojado en sf_sandbox/lib/model/ y nos permitirá actuar con la base de datos sin utilizar sentencias SQL.

php symfony propel-build-model

Si como es nuestro caso la aplicación parte desde cero y no tenemos la base de datos creada en nuestro servidor, nos vendrá bien utilizar el siguiente comando para generar el archivo de intrucciones SQL que podremos utilizar más tarde:

php symfony propel-build-sql

Gracias al archivo generado y disponible en la ruta data/sql/lib.model.schema.sql podremos importar el diseño de la base de datos a nuestro servidor MySQL. Para ello usaremos la linea de comandos, la opcion restaurar de MySQL Administrator, PHPMyAdmin, etc. Alternativamente podríamos utilizar la instruccion:

php symfony propel-insert-sql

Esta instrucción es útil si lo tenemos todo bien configurado con Symfony para que actúe sobre el serividor MySQL ya que por defecto generará una base de datos SQLite. De hecho en nuestro caso ha sido necesario modificar la configuración para poder trabajar con MySQL.

Un poco de magia

Los formularios de creación, modificación y eliminación de datos, suelen ser una tarea bastante tediosa y monótona. Por suerte Symfony nos puede librar casi por completo de ello, y decimos casí porque es cierto que siempre terminaremos retocando algo de los formularios. Esto lo conseguimos en nuestro caso haciendo lo siguiente:

php symfony propel-generate-crud frontend articulo Articulo
php symfony propel-generate-crud frontend comentario Comentario
php symfony clear-cache

Modulos y acciones

Llegados a este punto tenemos gran parte de la lógica interna de nuestra aplicación desarrollada. Gracias a los comandos que acabamos de ejecutar, dentro del directorio frontend/modules tendremos creados los módulos articulo y comentario. Cada uno de ellos contiene los directorios actions y templates. De momento nos ocuparemos del primero, donde encontraremos el fichero actions.class.php En este fichero se nos ha creado una clase que contiene todas las acciones del módulo y que por supuesto podremos modificar según nuestras necesidades.

Sin entrar mucho en detalle, en nuestro modulo articulos tendremos, en el fichero actions.class.php, la clase articuloActions que contendrá, entre otras, las siguientes funciones:
  • executeList: muestra el listado de artículos utilizando la plantilla listSuccess.php
  • executeShow: muestra un determinado artículo utilizando la plantilla showSuccess.php
  • etc.
Por poner un ejemplo nosotros hemos modificado executeList para que muestre los artículos por orden descendente de fecha:
public function executeList()
{

$this
->nombreModul=$this->getModuleNam();
$c=new Criteri();
$c->addDescendingOrderByColum(ArticuloPeer::FECHA_CREACION);
$thi->articulos = ArticuloPeer::doSelect($c
);
}

Adaptando nuestro diseño inicial

En la introducción a esta serie escogimos el diseño Pluralism. Es el momento de adaptarlo a nuestra aplicación, para ello tomaremos el archivo css (style.css) y lo copiaremos en la ruta /web/css. Para hacer que nuestra web lo lea añadiremos la siguiente linea al archivo layout.php que se encuentra en /apps/frontend/templates/

php echo stylesheet_tag('style') ;

Por supuesto insertaremos esta linea antes del fin de la etiqueta html head.

Después de esto remaquetamos nuestro layout.php copiando el código html proporiconado por Pluralism. Es decir que añadimos las capas wrapper y todo lo que necesitemos para obtener el resultado esperado. Mostraremos parte del código:
<body>
<div id="wrapper">
<div id="wrapper2">
<div id="header">
<div id="logo">
<h1&gt
<?php echo link_to('Janfri Bloggart', '@homepage')?></h1>
</div>
<div id="menu">
<ul>
<li&gt
<?php echo link_to('Crear entrada','articulo/create')?></li>
<li&gt
<?php echo link_to('Lists de articulos','articulo/list')?></li>
</ul>
</div>
</div>
<!-- end #header -->
<div id="page">
<div id="content">
<?php echo $sf_data->getRaw('sf_content')?>
</div>


Observese que introducimos un link a la home como título y que en la zona de menús dejamos dos links más.

Con la instrucción $sf_data->getRaw('sf_content') mostramos la información correspondiente a la acción invocada del módulo actual.

Para mostrar el listado de títulos de posts recientes nos hemos ayudado creando una plantilla auxiliar llamada _articulos_listado.php que hemos hubicado en modules/articulo/templates/ Este tipo de plantillas se incluyen mediante la instrucción inclde_partial:

include_partial('articulo/articulos_listado',array('articulos'=>$articulos
));

Por lo demás, el trabajo en la capa de presentación se basa en modificar las plantillas existentes, por ejemplo, a la hora de dar de alta un artículo hemos cambiado el "select" cargado con los artículos existentes por un input hidden con el valor del articulo a comentar. De otro modo: Simfony es listo pero no perfecto. Nos ha proporcionado un formulario de creación de comentarios en el que podríamos elegir el artículo a comentar mediante un "select" pero no era lo que queríamos. También hemos ampliado los textarea que nos ha creado para el cuerpo de los artículos y los comentarios, por citar otro ejemplo.











Conclusiones


Tras todo lo comentado anteriormente llegamos a la conclusión de que en eso más o menos consiste el trabajo básico. Debemos modificar las acciones y las plantillas hasta conseguir los resultados deseados. Todo ello después de haber hecho un buen diseño de tablas y haber ejecutado los comandos que nos preparan todos los archivos. Fácil y rapido una vez te acostumbras al árbol de archivos, configuraciones, etc. No se le puede pedir más.

Además es de agradecer que Symfony diferencia entre el entorno de desarrollo y el de producción, ofreciendo en el primero bastante información útil a través de un menú flotante en nuestra propia página web. Podermos inspeccionar el valor de variables, mensajes de log, consultas SQL realizadas (a través de Propel), etc.

El precio para disfrutar de todo esto es el aprendizaje, tal vez mayor que con otros competidores ya que además del API, tendremos que tener conocimientos sobre YAML y Propel.

En definitiva dan ganas de seguir poniendo a prueba a Symfony ya que es una forma diferente de trabajar con PHP pero es el momento de comenzar con Zend.

martes, 12 de febrero de 2008

Symfony vs Zend Framework. 1- Definición del problema

Desde hace un par de años están tomando mucho auge diversos frameworks en PHP: Prado, Tigermouse, Symfony, CodeIgniter... Realmente hay una gran variedad de ellos haciendo difícil la tarea de elegir uno. Por si éramos pocos, durante el año pasado surgió Zend Framework (ZF en adelante) con todo el apoyo de la compañía que lleva las riendas del desarrollo del intérprete PHP.
Parecía que ZF iba a desplazar a todos los demás, pero entonces llegó Yahoo y anunció la adopción de Symfony para desarrollar Del.icio.us. Podríamos decir, con permiso de los demás, que la partida huele a tablas entre ambos al menos mediáticamente.

Todo esto invita a hacer una comparativa y la haremos desde el punto de vista de alguien que nunca ha utilizado ninguno de ellos. Para ello haremos una aplicación bastante simple: un blog (puede que no sea muy original) y partiendo de un diseño común la escribiremos utilizando ambos frameworks.

En principio dedicaremos capítulos diferentes a cada uno de los frameworks y, aunque no hay intención de que tengan estructura de tutorial, detallaremos bastantes de los pasos seguidos para la implementación. En la última parte comentaremos las conclusiones a las que lleguemos.

La aplicación

Simplificaremos bastante la aplicación, contemplando las siguientes historias a desarrollar.

1- El blogger escribe, edita o borra artículos.
2- El lector lee artículos
3- El lector añade comentarios a un artículo.



No incluiremos procesos de autenticación de usuarios.

Por supuesto el diseño de la BD será el mismo para ambos casos y responderá a este esquema:


Aclararemos aquí que seremos estrictos con el nombre de los campos. Como se verá mas adelante nos resultaría más fácil llamar id a los campos clave de cada tabla, de lo contrario nos veremos obligados, por ejemplo en el caso de Symfony, a extender las definiciones de nuestros campos en los ficheros yaml. Lo mismo ocurriría si llamásemos created_at a los campos fecha_creacion.


En cuanto a la capa de presentación elegiremos un diseño de la web freecsstemplates Para ello buscaremos uno que se adecue a la siguiente disposición:



Hay bastantes donde elegir. Nosotros nos quedaremos con Pluralism ya que cumple con nuestras características deseadas.



Así pues, a partir de nuestros casos de uso y con el diseño elegido, tenemos las siguientes páginas a desarrollar:

  • Listado de posts. En él se podrán leer directamente el cuerpo de los posts recientes y aprovechando la maquetación de pluralism tendremos un listado de posts (de sus títulos) inmediatamente antes del pie. Ya que no hay validación de usuarios colocaremos cerca de este bloque el enlace que nos permitirá crear una entrada nueva.
  • Edición de posts. Aquí se crearán, modificarán y borrarán los artículos. Será un entorno muy básico sin edición WYSIWYG, etc.
  • Añadir comentarios. Al igual que antes será un entorno muy simple.


Otras consideraciones a tener en cuenta


Por lo general no abarcaremos detalles de carácter avanzado como la instalación o la posibilidad de utilizar plugins porque simplemente nos pondremos en el caso más práctico: hacer una aplicación que funcione.

Por supuesto se intentará que ambas versiones sean lo más similares posible en aspecto y funcionamiento.

Versiones utilizadas

Usaremos el recién horneado Zend Framework 1.5 (que sigue siendo una beta en el momento de escribir esto) y el paquete Sandbox de Symfony 1.0 que en teoría tiene todo lo necesario para comenzar una aplicación como esta.
Como base de datos haremos uso de MySQL en ambas aplicaciones.

Powered by ScribeFire.

domingo, 3 de febrero de 2008

La battalla de Atenas y el fiasco de Argos

Cuenta Roald Dahl en su libro "Volando sólo" como doce pilotos de Hurricane se enfrentaron a cientos de cazas de la Luftwaffe en la Batalla de Atenas. El era uno de ellos y parece que la única estrategia aquel 20 de Abril era mantenerse vivo, lejos de la balas de los Me-109 y Me-110.

Sorprendentemente ese día los británicos perdieron sólo cinco aviones frente a veintidós de los alemanes. Parece difícil de creer pero todo se debía a que el fuego que conseguían evitar los ingleses terminaba impactando en alguno de sus muchos perseguidores.

Después de este encuentro los siete restantes se dedicaron unos cuantos días simplemente a esconderse, o sea, a sobrevivir camuflados entre olivos y, a veces, viendo pasar a la Luftwaffe muy de cerca y sin poder hacer nada.

Finalmente estando ocultos en un aeródromo en Argos fueron descubiertos por un Me-110 y fue entonces cuando llegó una orden absurda de sus superiores: a pesar de que los siete pilotos calcularon que tenían poco menos de tres horas antes de ser atacados, se les ordenó despegar tres horas más tarde en una misión de escolta a un convoy. Los cálculos resultaron correctos y aquello fue el fin de la RAF en Grecia ya que se perdieron dos Hurricane abatidos en la maniobra de despegue y el resto fueron evacuados a Egipto.



¿Por qué cuento todo esto? Pues porque en el mundo de la "Ingeniería" del Software las analogías son muy socorridas y por su puesto nos entusiasman para desahogarnos.

Creo que muchos de nosotros somos algo parecido a los pilotos de la RAF ya que a veces uno o unos pocos desarrolladores se enfrentan a su propia Luftwaffe en forma de enorme proyecto mal planificado al que se combate a la heroica. Pero aún así, aunque el caos de Atenas se correspondería con la falta de rumbo y planificación e incluso con la falta de tener las ideas claras sobre el producto deseado por la parte del cliente, hay veces en que, asombrosamente, las cosas salen mejor de lo esperado.

En cuanto a lo de Argos, bueno, podrían haber cientos de ejemplos de decisiones incomprensibles pero una de las últimas que he vivido se podría relatar así en el contexto de la historia anterior.

Aquel día regresaba agotado al aeródromo donde nos ocultábamos, después de una misión de reconocimiento, dando gracias por volver a tocar tierra. No había caminado ni diez pasos desde mi Hurricane cuando vi que el jefe de escuadrilla se dirigía hacia mí. ¿Me pediría un informe verbal de mi salida? Hubiese sido un poco estúpido contarle algo que ya sabía:

"Mira, he volado todo lo bajo que podía para que no me viesen y cuando he llegado al punto asignado resulta que la conclusión es la de siempre: son muchísimos y por mi puedes decirle a Churchill que nuestros Hurricanes no tienen balas para todos, si al menos nos hubieran dado Spitfires ..."


Pero no pude ni terminar de pensar en lo que le iba a decir ya que de inmediato dijo:

- Tienes una misión. Lo siento, ya sé que esperabas comer algo y dormir un poco bajo el ala de tu avión pero hay que atacar al enemigo.

- ¿Has dicho atacar? pregunté incrédulo. Eso es imposible, absurdo. Son cientos y ni siquiera tenemos bombarderos aquí. ¿Quién lo ha decidido?

- No lo sé, no lo recuerdo. Se comentó en un briefing al que no te llamaron y se nos olvidó comentártelo.

- ¡Mierda! ¿Cómo me hacéis esto? ¿Cuál es el plan?

- El plan... ¡claro! Verás... se comentó por encima, no había nada claro. El caso es que tenías que haber atacado ayer y claro hoy me han preguntado por los resultados. Total, que tampoco se dijo nada concreto aquel día, así que tú despega, ametralla lo que puedas y si a caso, cuando vuelvas, comentamos los resultados. Yo les transmitiré todo y si no les parece bien, que nos digan como lo quieren y volvemos a hacerlo.

- ¿Qué volvemos a hacerlo? ¿Y eso te parece correcto? ¡No hay plan de ataque!

- Ya, pero lo que no puede ser es que nos pregunten por el ataque y no tengamos nada que decirles, así que ves despegando y ya hablamos.


Y así, ese día, volví a hacerme al aire y no sé como, horas mas tarde, estaba de vuelta. El resultado del ataque no merece comentario pero dos días mas tarde se volvió a acercar a mí y con total tranquilidad me dijo que finalmente aquella misión había sido totalmente innecesaria.


Powered by ScribeFire.