Archivos de la categoría Programación

Nuevo proyecto: PlayEpub, lector de ebooks para Blackberry Playbook

Ah!, que no os lo había contado, os tengo algo abandonados últimamente, pero es que he estado bastante liado, nuevo proyecto en la oficina y nuevo proyecto en casa :P. Research in Motion (más conocido como Blackberry) me ha regalado su nuevo tablet, el Playbook. ¿Adivináis por qué? ¡Sí! Por publicar Valenbisi para Playbook :).

No lo voy a negar, nunca me habría comprado un tablet si no me lo hubiesen regalado :P, y después de dos meses con él en casa, me confirmo, no le veo 500 euros de utilidad :P. El aparato en cuestión me parece muy buen cacharro, micro de doble núcleo a 1ghz, 1G de ram, salida HDMI y lo más sorprendente, sistema operativo QNX, un nuevo player en el mercado. RIM compró QNX, un sistema operativo en tiempo real, hace unos años y ahora ha aprovechado para incluirlo en su tablet. El rendimiento es espectacular, reproduciendo una película en HD, navegando y jugando simultáneamente sin notar ni un ápice de deterioro. Pero claro, todo tiene sus pegas :P. Desde mi punto de vista la mayor es la falta de aplicaciones. Aunque RIM anunció a bombo y platillo hace unos meses que se podrían ejecutar aplicaciones Android, lo cierto es que por el momento no, nos limitamos a las aplicaciones nativas. ¿Y cómo se desarrollan estas aplicaciones nativas? Pues más sorprendente aún, en Adobe AIR, por mi encantado :P, pero reconozco que tiene muchas limitaciones a la hora de poder hacer ciertas cosas, por ejemplo un cliente ssh. Aún así es más que suficiente para la mayoría de aplicaciones de usuario.

Cuando cayó en mis manos, lo primero que eché en falta fue un lector de ebooks que me permitiese abrir los epub que ya tenía y que suelo leer en el móvil o convertir a mobi para pasarlos al Kindle. Ni corto ni perezoso me dije, ¿por qué no hacerlo yo mismo? De eso hace dos meses y hoy os confirmo que ya está a la venta :).

La verdad es que inicialmente pensé que sería mucho más sencillo, de hecho, tras estudiar el formato epub y tener el sistema de descompresión y lectura preparado, creía que lo tenía prácticamente hecho, ¡cuanto me equivocaba!. La parte de paginación tipo libro, es decir, click para página siguiente, click para página anterior, se me complicó muchísimo. Rehice el sistema cuatro veces desde cero ya que no encontraba la forma correcta de que todo funcionase como debía. Finalmente di con algo que funcionaba, me limitaba para hacer otras cosas, pero al menos la navegación y lectura eran fluidas y usables :).

La última semana de desarrollo  fue la más satisfactoria a nivel personal ya que, una vez superados los problemas de la paginación (mes y medio solo para eso), me dediqué a añadirle funcionalidades más vistosas y llamativas de cara al usuario, aumentar el tamaño de fuente, modo noche que hace el fondo negro y la fuente blanca, reducir y aumentar el brillo de pantalla, añadir marcadores para volver rápidamente a ciertas páginas, porcentaje de lectura…

Creo que me quedó muy aparente :). En la imagen de abajo podéis ver la interactividad de la pantalla de lectura con 4 zonas sensibles para hacer click, cada una con una función distinta. Pero eso no es todo, si se hace un click largo, es decir, se pulsa con el dejo y de deja pulsado sin levantarlo más de un segundo, sale la opción para añadir marcadores (o eliminarlo si esa página ya lo tenía).

He de decir que la finalidad de la aplicación no es hacer negocio, la hice para leer mis libros, pero si entra algo… :P. Los primeros tres días a la venta generó casi 200 descargas a 2$. Tampoco me puedo quejar.

Y como siempre llego tarde a todas partes he de decir que me pasé estos dos meses de desarrollo controlando en la tienda de aplicaciones que no saliese otro lector de epubs. Pues bien, el mismo sábado que subí la mía apareció otra publicada. Encima tardaron una semana en validármela, con lo que la otra tuvo tiempo de copar el mercado, una lástima, pero como siempre, tarde a todas partes :P.

Más información en PlayEpub.

Mi primer webservice en PHP (chispas)

Tras mucho tiempo consumiendo webservices de otros me ha tocado crear mi primer servidor SOAP en PHP y, la verdad, me ha parecido realmente sencillo e intuitivo. Creas una clase con los métodos que vas a exponer en el ws y se crea automáticamente el servicio sobre ellos, tan sencillo como eso.

<?php
$wsdl="miclase.wsdl";
$soap = new SoapServer($wsdl);
$soap->setClass('MiClase');
$soap->handle();

//clase que gestiona el ws
class MiClase {
    public function MiClase(){
      //tu código
    }

    /**
     *
     * @param string $email
     * @return string
     */
    public function is_email_available($email){
        //tu codigo...
        return "OK";
    }
    /**
    *
    * @param string $phone
    * @param string $email
    * @return string
    */
    public function register_user($phone, $email){
       //tu codigo...
       return "OK";
    }
    /**
    *
    * @param string $phone
    * @return string
    */
    public function downgrade_user($phone){
       //tu codigo...
       return "OK";
    }
}
?>

Con esto se crea automáticamente nuestro webservice con los tres métodos públicos. Pero espera, falta algo, arriba de todo defines un “miclase.wsdl“. ¿Qué es eso? ¿De dónde sale?

En efecto, ese es el principal problema al crear un webservice SOAP con PHP, no se genera el WSDL automáticamente sino que hay que escribirlo ¡a mano!. Para solucionarlo tenemos la librería PHP WSDL Generator a la que únicamente debemos pasarle la clase de la que queremos extraer el WSDL y lo hace por nosotros :). Para que todo funciona bien es necesario que los métodos de nuestra clase estén bien documentados tal y como aparecen en el ejemplo anterior, de esta manera WSDL Generator sabrá configurar los tipos de datos de los parámetros de entrada y salida de los métodos.

Veamos un ejemplo:

<?php
require_once("wsdl2php/WSDLCreator.php");
$test = new WSDLCreator("miclase", "http://ws.tudominio.com/wsdl");
$test->addFile("miclase.php");
$test->setClassesGeneralURL("http://tudominio.com");
$test->addURLToClass("MiClase", "http://ws.tudominio.com/miclase.php");
$test->ignoreMethod(array("MiClase"=>"MiClase"));
$test->createWSDL();
$test->saveWSDL(dirname(__FILE__)."/miclase.wsdl", false);
?>

Este pequeño código nos generará el archivo WSDL de nuestro webservice. Como veis simplemente le indicamos el archivo con nuestra clase (el que escribimos anteriormente), la clase que queremos mapear con la URL del webservice (el endpoint) y, además, le indicamos que ignore el constructor de la clase ya que no será un método de nuestro webservice. Eso es todo.

Si ahora probamos el servicio web, por ejemplo desde el Web Service Explorer de Eclipse:

Tras darle la ruta del wsdl, http://ws.tudominio.com/miclase.php?wsdl, veremos los tres métodos que hemos expuesto y podremos probarlos y utilizarlos.

Nunca había tenido la necesidad de crear un servidor SOAP pero ha sido realmente sencillo. Ahora estoy buscando la manera de devolver tipos de datos complejos, pero eso será en el próximo capítulo :P.

Cómo actualizar Eclipse Galileo a Helios sin perder la configuración y los plugins

Puede parecer sencillo, pero si intentas actualizar siguiendo el procedimiento oficial verás que no funciona. La documentación indica que sólo es necesario añadir el nuevo sitio de Helios, pero no, no es suficiente, surgen errores de dependencias no resueltas.

Solucionarlo es sencillo si sabes cómo. Desde Window->Preferences seleccionamos Install/Update->Available Software Sites y a la derecha veremos la lista de repositorios de software de nuestra instalación. Además de añadir el nuevo de Helios (http://download.eclipse.org/releases/helios) debemos añadir también el sitio de actualización de la nueva versión modificando “3.5” por “3.6” en el repositorio de “update” de Galileo. La siguiente imagen aclarará un poco más el cambio.

Con esos dos cambios pude actualizar correctamente dos instalaciones distintas de Eclipse, solo tuve un problema. En una de ellas tuve que desinstalar primero los plugins de BlackBerry ya que decía que no eran compatibles con Helios y tampoco me los actualizaba a la nueva versión. Una vez actualizado Eclipse los instalé de nuevo sin problemas.

Espero que os sirva de ayuda…

Miniproyecto – Valenbisi.mobi, geolocalización del servicio de bicicletas de Valencia para móviles y sms

Como supongo que la mayoría no sabréis de qué hablo, empezaré por el principio.

Valenbisi es el servicio urbano de alquiler de bicicletas de Valencia a semejanza del que existe en muchas otras ciudades españolas y europeas. La idea es fomentar su utilización para desplazamientos cortos ya que el abono anual (20 euros) permite alquilar gratuitamente la bicicleta la primera media hora de cada día. Hay varias estaciones a lo largo de la ciudad y simplemente coges la bici en una y la dejas en la que mejor te venga. Valencia creo que es una de las ciudades que más se prestan a un servicio de este tipo por dos razones básicas, la climatología y la falta de cuestas. Al parecer el éxito ha sido espectacular tras el verano hasta tal punto que el servicio de abonos está saturado de solicitudes, el nuestro tardó alrededor de un mes en llegarnos.

El sábado pasado mi pareja y yo decidimos acercarnos a la playa y darnos un paseo en bici, hacía un día fenomenal y el calorcito invitaba a pasear. El plan era coger la bicicleta al principio de la playa y dejarla al final para regresar a pie. Pues bien, el problema fue que a la hora de regresar no había ningún puesto libre donde dejar las bicis en las 3 estaciones por las que pasamos, tuvimos que volver al punto de inicio donde tuvimos la suerte de encontrar los dos que necesitábamos. Dos chicas que llegaron justos detrás nuestra no tuvieron la misma suerte :P. Esto nos planteó el problema que puede ser una situación de este tipo al tener que buscar otra estación que tenga enganches libres, puedes ir a la siguiente pero tampoco sabes si habrá puestos, con lo que te tocará ir a la siguiente y así indefinidamente. Si además del tiempo perdido tenemos en cuenta el dinero que pagas por el tiempo que pasa, no cabe duda que puede ser un serio inconveniente para el servicio. ¿Qué pasará cuando llegue el verano y todos los usuarios quieran bajar con sus bicis a la playa? Pues que no habrá donde dejarlas desde primera hora de la mañana. Estos días, siguiendo el problema, he visto que ocurre algo similar con las estaciones del centro de la ciudad en horario laboral, a las 10 de la mañana están casi todas completas. ¿Cómo sabes entonces dónde dejar tu bici?

Pues aquí llego yo a medio solucionar el problema :P. Una aplicación para el móvil que te dice las estaciones más cercanas con puestos libres o bicis disponibles, ya que el problema puede ser el contrario, que vayas a por una bicicleta y estén todas ocupadas. La diferencia con otras aplicaciones por el estilo es que no me he atado a Iphone o Android como casi siempre sucede en estos casos, he hecho algo que funcionará en la mayoría de terminales de los usuarios “normales”, otra cosa es que quieran utilizarlo. Para acompañarlo, he hecho una interfaz por SMS :P, que es más sencillo para la gente, pero sin la mayoría de opciones.

Como funciona el servicio

Muy sencillo. Entras en http://valenbisi.mobi, le dices donde estás, que puede ser tu dirección o el número de estación de Valenbisi, y automáticamente te indicará el estado de las estaciones que tienes a tu alrededor, es decir, bicis y huecos libres que tienen. Además, si las que tienes cerca no tuviesen bicis o puntos libres, te permite buscar las más cercanas con disponibilidad. Todo ello acompañado de imágenes con mapas con las estaciones indicadas posicionadas y rutas para llegar.

Detalles técnicos

La implementación del sistema no me habrá llevado más de 10 horas incluidas las pruebas. Gracias a todos los que me habéis ayudado con ellas y a vuestras sugerencias :).

Para desarrollarlo he utilizado:

  • API de Valenbisi, si se puede llamar así. Aporta la información de la localización de las estaciones y el estado de las mismas.
  • Google Geocoding API para obtener las coordenadas de una dirección y viceversa.
  • Google Directions API para obtener la ruta entre dos puntos.
  • Google Static Maps API para obtener imágenes de mapas.
  • Geolocation API Specification para aquellos navegadores que lo soporten, así el usuario no tiene que indicar su dirección, el GPS del dispositivo lo hace todo. Actualmente lo soportan, que yo sepa, Iphone, Android y las últimas Blackberry.
  • Wurfl, para obtener las características de su teléfono.

No voy a explicar cómo se utilizan las API’s ya que están bien documentadas y son muy sencillas, todas basadas en peticiones HTTP que devuelven XML o json.

Cuando el usuario accede a http://valenbisi.mobi, si su navegador soporta localización, le saltará el aviso de que la página quiere usar esa información y automáticamente posicionará al usuario. Si no lo soporta, la mayoría de los casos, el usuario debe introducir su dirección o el número de la estación Valenbisi que le interesa. Con esos datos averiguamos donde está. Si es una dirección a través de Google Geodecoding API y si es un número simplemente con el API de Valenbisi. De un modo o de otro ya sabemos donde está el usuario.

Ahora simplemente debemos buscar las estaciones que tiene alrededor. Yo lo he hecho de dos formas. La primera es mostrar las estaciones que tiene a su alrededor a partir del mapa. Esta es una de las primeras cosas curiosas que he hecho. Para obtener el mapa de la posición del usuario, le pido a Google Static Maps API una imagen del mismo tamaño que la pantalla del teléfono del usuario, así verá todo lo máximo que le permita su dispositivo. Esto significa que cada usuario verá un mapa de distinto tamaño. Ahora tengo que averiguar las estaciones que aparecen dentro del mapa. Podríamos pensar en pasarle todas al API y que éste pinte las que aparecen en nuestra imagen y pase de las otras, pero la idea no funciona ya que Static Maps tiene un tamaño máximo de url, que por cierto no es muy grande, rebasado el cual la imagen da error. Así que lo que hice fue calcular cuanto espacio geográfico cabe en la imagen. Le pedí una imagen posicionando marcas cada 0,001 puntos de longitud y latitud. A partir de esa imagen calcule a cuantos píxeles correspondía cada salto. Con esta información, y manteniendo el zoom fijo, sabremos en cada momento qué coordenadas se van a ver en la imagen que le pida a Google ya que conozco el ancho y el alto que le voy a pedir, conozco las coordenadas del centro (la posición del usuario) y sé cuánto me puedo desplazar a lo largo de la imagen. No es 100% fiable pero nos sirve para lo que necesitamos. Ahora simplemente recorro todas las estaciones y si sus coordenadas están entre los límites de la imagen que voy a mostrar, añado la marca. A medida que el usuario se mueve por el mapa con las flechas, voy actualizando las estaciones que se ven en el mismo con este procedimiento.

La segunda manera de buscar estaciones que he utilizado es mostrar las estaciones más cercanas que cumplan uno de los posibles requisitos, que tengan bicis o que tengan huecos libres. Aquí el usuario no puede navegar por el mapa, simplemente le muestro a las que puede acudir. Para localizar las estaciones más cercanas, la opción más clara es consultar Google Directions Api entre la posición del usuario y todas y cada una de las estaciones y obtener las que están más cerca (uno de los parámetros que devuelve es la distancia), pero esto implicaría más de 100 llamadas al API por consulta, con lo cual no es viable. Aplicando conceptos básicos de trigonometría y coordenadas cartesianas, sabemos que, en un plano, la distancia (en línea recta) entre dos puntos es:

Simplemente con los datos de la localización de estaciones y la posición del usuario y aplicando algunas operaciones matemáticas puedo averiguar aquellas estaciones que, siempre en línea recta y cumpliendo los requisitos de disponibilidad, están más cerca del cliente. Ordeno las distancias resultantes de menor a mayor y con las cinco primeras, ahora sí, consulto Google Directions API para que me de una distancia real entre el usuario y esas estaciones. Las vuelvo a ordenar por distancia y ya tengo aquellas más cercanas al usuario. Solo queda pedirle a Google Static Maps la imagen del mapa donde aparecen estas estaciones, ahora sin zoom para que lo ajuste automáticamente. Mucho más eficiente que consultar la distancia de las más de 100 estaciones.

Solo nos queda averiguar la ruta para ir desde la localización del usuario hasta la estación seleccionada. Static Maps no hace rutas, solo líneas rectas, pero podemos indicarle todos los puntos intermedios necesarios y que nos pinte las líneas entre ellos, con lo que si supiéramos los pasos que tiene que dar el usuario, podríamos pintar la ruta. Y para esto tenemos de nuevo Google Directions API, nos dirá los puntos entre el usuario y la estación. Solo tenemos que pasar estos puntos a Static Maps y tendremos la imagen de nuestra ruta.

Eso es todo, uniendo todas las piezas entre sí adecuadamente tendremos el sistema que os presento :). El último toque fue añadir las opciones de idioma, para que los turistas puedan utilizar el servicio :P.

Finalmente vinieron las pruebas con algunos conocidos y los ajustes para los terminales más antiguos (en los nuevos se ve todo fenomenal :P) .

Aquí van algunas capturas en distintos terminales:

Nokia X6

Nokia N95

Nokia N73

Nokia N70

Iphone

BlackBerry 9000

Android

Interfaz SMS

Cuando ya lo tenía terminado se me ocurrió, ¿y por qué no hacer también una interfaz SMS para los usuarios que no tienen Internet en el móvil? Ya tenía todas las piezas y dado que profesionalmente me dedico a eso… 10 minutos 🙂

Envía BICI númeroDeEstación al 215000 25325 y te devuelvo el estado de esa estación y las más próximas con sus direcciones. Por ejemplo:

BICI 146

Est. 165:12 bicis,8 libres.OTRAS:164,8 bicis,9 libres (C. PAVIA (OPUESTO Nº 15-17) )-167,17 bic 0,35Eur Alvento Soluciones S.A.n.atn.clte:902887786 alvento.es

Todo lo que quepa en los 160 caracteres permitidos, que no es mucho. Coste del SMS 0,35 euros, igual que un SMS normal 🙂. Si usas habitualmente la misma estación puedes saber con antelación si tendrás bici o hueco. Información legal del servicio: 0,35Eur.Alvento Soluciones S.A.n.atn.clte. 902887786 alvento.es

Más no se puede pedir en tan poco tiempo. Os invito a probarlo. Se aceptan críticas, mejoras de usabilidad, nuevas funciones, etc…

Actualización:

Sintiéndolo mucho he tenido que cambiar el número corto del servicio ya que el que había dicho inicialmente sólo funciona en Vodafone. El número actual, el 25325 es el más barato de los posibles, lo siento, ya sé que así se limita mucho su utilidad… quedará como ejemplo de lo que se podría hacer 😛 a no ser que alguien quiera hacerse cargo del servicio.

Team Foundation Server – Reutilizar un workspace creado en otra máquina

Es sin duda uno de los mayores inconvenientes de TFS, una vez creas un workspace no puedes utilizarlo más que en la máquina donde lo creaste, aunque sea el mismo usuario, ya que queda asociado también al nombre del equipo, no solo al usuario.

Esto es un problema si cambias de ordenador o si simplemente, como fue mi caso, se cambia el nombre del equipo (tuvimos que cambiar de dominio y en el nuevo los nombres eran diferentes). Pese a que hagas copia de seguridad y tengas todos los archivos, no puedes reutilizar el workspace porque está asociado a otra máquina y es en el workspace donde se almacena la información de los archivos que tienes descargados, las versiones, archivos que tienes bloqueados, etc. Está bien que se guarde esta información en el servidor pero si no puedo utilizarla desde otra máquina no le veo mucha utilidad.

Me costó bastante encontrar como solucionarlo, y es que TFS trae un cliente en línea de comandos desde el que se pueden hacer hacer virguerías. En mi caso, que lo utilizamos desde Eclipse con el plugin de Microsoft (originariamente de Teamprise), no tengo instalado el cliente de Visual Studio, así que le pedí algunos archivos a uno de mis compañeros. Con estos será suficiente:

  • TF.exe
  • Microsoft.TeamFoundation.Client.dll
  • Microsoft.TeamFoundation.Common.dll
  • Microsoft.TeamFoundation.VersionControl.Client.dll
  • Microsoft.TeamFoundation.VersionControl.Common.dll

Se copian todos en una carpeta y, desde la línea de comandos en esa carpeta, ya podemos jugar. Aquí tenéis una buena lista de opciones del cliente en línea de comandos.

Primero le preguntamos por los workspaces asociados a nuestra nueva máquina:

C:tfs>tf workspaces -server:http://tfs.tudominio.com:8080/
No workspace matching *;osus on computer NOMBREEQUIPO found in Team Foundation Server http://tfs.tudominio.com:8080/.

Como veis nos dice que no hay ninguno. Ahora le pedimos que cambie nuestro workspace de la máquina vieja a la nueva. Lógicamente tendremos que conocer el nombre del workspace y el de la máquina antigua. Es importante tener en cuenta que hay que hacerlo obligatoriamente desde la máquina nueva que vamos a utilizar, no sirve hacerlo desde la de otro compañero ya que asocia automáticamente el workspace a la máquina donde se lanza el comando.

C:tfs>tf workspaces -login:posus@DOMINIO -server:http://tfs.tudominio.com:8080/ -updateComputerName:NOMBREMAQUINAVIEJA NOMBREWORKSPACE
Collection: http://tfs.tudominio.com:8080/
Workspace	Owner		Computer     	Comment
--------- 	----------	------------ 	---------------------------------------------
NOMBREWORKSPACE	osus		NOMBREEQUIPO

Para hacer el cambio te pedirá que te autentifiques con tus credenciales y, si todo ha ido bien, nos dirá que lo ha cambiado correctamente.

Si hacemos de nuevo la primera consulta:

C:tfs>tf workspaces -server:http://tfs.tudominio.com:8080/
Collection: http://tfs.tudominio.com:8080/
Workspace	Owner      Computer     Comment
---------	---------- ------------ ---------------------------------------------
NOMBREWORKSPACE osus       NOMBREEQUIPO

Ahora ya podemos utilizar nuestro workspace en el nuevo equipo. Recuerda, eso sí, que si cambias de máquina (no es sólo un cambio de nombre) deberás copiar los archivos que ya tenías en la misma ruta original, se mantendrá todo como en la otra máquina, incluidos los archivos que estabas modificando.

Mi pequeña biblioteca técnica

Hoy voy a mostraros la pequeña colección de libros técnicos que he ido acumulando durante los últimos diez años. A tiempo pasado me he dado cuenta de que una gran mayoría de ellos no pintan nada ya en la estantería ya que son tecnologías desfasadas o superadas por nuevas versiones, tal es el caso, por ejemplo, de Visual Basic 6.0, Windows NT, Oracle 8i… Otros pueden servir aún como introducción general (Java2, SQL Server, MySQL, etc.), pero nunca serán un referente en sí mismos ya que están también “anticuados“. Bien es verdad, y considero importante puntualizarlo, que el grueso de mi biblioteca data del periodo 2000-2005, los últimos años apenas he comprado nada, Internet es, sin lugar a dudas, la biblioteca particular de todos nosotros. Mis últimas adquisiciones tratan temas más relacionados con la gestión (de proyectos, personas y negocios) que con la tecnología en sí misma, y es que estos últimos no pierden su capacidad de enseñanza, con los años siguen ahí para quien quiera consultarlos.

Estos son mis libros, agrupados, más o menos, por temática. Indico entre paréntesis el/los autor/es y la editorial, a continuación el año en que lo compré y una pequeña reseña del mismo.

  • Sistemas Operativos:
    • Guía completa de Microsoft Windows NT Server 4.0 (Russel y Crawlord, Mc Graw Hill), 2000. Con este y los dos siguientes aprendí todo lo relacionado con redes Windows, controladores de dominio, usuarios, etc. En su momento me fueron de muchísima utilidad e incluso gracias a ellos llegué a impartir formación sobre Windows NT, ha pasado mucho tiempo ya.
    • Windows NT 4.0 Server, instalación y gestión (J.M. Martínez y M. Martínez, Prentice Hall), 2000.
    • Windows NT Server 4.0 (Anaya Multimedia), 2000.
    • Linux Máxima Seguridad (Anónimo, Sams), 2002. En su momento me pareció una joya y me sirvió para profundizar y mejorar considerablemente mis conocimientos en temas de seguridad, auditoría e IDS en sistemas Linux. Aún sigo haciendo alguna consulta de vez en cuando.
    • El Libro Oficial de Red Hat Linux – Firewalls (Bill McCarty, Anaya Multimedia), 2003. Fundamental junto al anterior en mi formación sobre sistemas de red avanzados bajo Linux. También sigo echándole un ojo de vez en cuando aunque en Internet esté toda la información más que explicada.
  • Programación y lenguajes:
    • Teach yourself Java2 in 21 Days Second Edition (Lemay & Cadenhead), 2001. Un clásico. Con la primera edición aprendí Java allá por 1996. Con este libro recuperé mi formación en Java, importante en aquel momento.
    • Core Servlets and Java Server Pages (Marty Hall), 2002. Tras mejorar mis conocimientos de java con el anterior y junto al siguiente, aprendí todo lo relacionado con aplicaciones web en Java. En su momento me parecieron un par de libros fundamentales.
    • More Servlets and Java Server Pages (Marty Hall), 2002.
    • Creación de sitios web con XML y Java (Maruyama, Tamura y Uramoto, Prentice Hall), 2002. Lo compré a raíz de los anteriores, supongo que lo habría visto recomendado en algún lado, pero no recuerdo que me pareciese un libro impactante.
    • Learning Perl 3rd Edition (Schwartz & Phoenix, O’Reilly), 2002. Necesitaba algo de formación en Perl pero nunca llegué a leérmelo entero, más que nada porque nunca llegué a necesitar un nivel avanzado en Perl.
    • ActionScript con FlashMX Edición Especial (Prentice Hall), 2003. Sin duda otro libro básico en mi formación. Gracias a él aprendí todo lo relacionado con ActionScript, algo que me ayudó enormemente a dar el paso a Flex algún tiempo después.
    • Desarrollo de juegos con J2ME (Manuel J. Prieto, Ra-Ma), 2005. Un proyecto fracasado :P, en aquel momento tenía algunas ideas en la cabeza pero nunca llegué a leerme este libro.
    • Visual C#.NET (Fco. Charte Ojeda, Anaya Multimedia), 2004. No lo compré, llegó a mis manos por casualidad y tampoco hice nada con él.
    • Enciclopedia de Microsoft Visual Basic 6.0 (Fco. Javier Ceballos, Ra-Ma), 2000. Sin lugar a dudas fue básico en mi formación inicial allá por el año 2000. Hoy está completamente desfasado gracias a la tecnología .NET, pero en aquel momento era imprescindible. Creo que fue el primero de todos.
    • Programación de Active Server Pages (Hillier & Mezick, Mc Graw Hill), 2000. Gracias a este libro conseguí mi primer trabajo de programador web. Corría el año 2000 y comenzaba mi carrera profesional. Junto al anterior, fueron mis primeros libros.
    • XML (Óscar González, Anaya Multimedia), 2001. Cuando estaba aprendiendo Java, no recuerdo por qué, necesitaba conocimientos avanzados en XML y este pequeño libro de bolsillo me dio lo que buscaba.
    • WebServices (Joan Ribas Lequerica, Anaya Multimedia), 2003. Lo mismo que el anterior pero para WebServices, va al meollo del asunto sin complicaciones.
    • La Biblia ASP.Net (Mridula Parihar, Anaya Multimedia), 2009. Mi última adquisición. Por cuestiones profesionales he de ponerme las pilas con .NET, ahí lo tengo esperando :P.
    • The Pragmatic Programmer – From Journeyman to Master (Andrew Hunt & David Thomas, Addison Wesley), 2006. Fundamental para cualquier programador, todo lo que cuenta es completamente lógico y de cajón, tanto que muchas veces lo olvidamos todo.
    • The Unified Modelling LAnguage User Guide Second Edition (Booch, Rumbaugh & Jacobson, Addison Wesley), 2007. La biblia del UML.
    • UML y Patrones Segunda Edición (Craig Larman, Pearson – Prentice Hall), 2005. Empieza bien, pero me lo dejé a mitad, es bastante espeso. Espero retomarlo pronto.
    • The Zen of CSS Design (Dave Shea & Molly E. Holzschlag, New Riders), 2005. Éste y el siguiente me ayudaron considerablemente a entrar en el mundo del CSS, hay miles de recursos en Internet, pero no está de más tener algo de ayuda “a mano“.
    • Stylin’ with CSS – A Designer’s guide (Charles Wyke-Smith, New Riders), 2005.
    • Usabilidad – Diseño de sitios web (Jakob Nielsen, Prentice Hall), 2002. Completamente imprescindible. Recuerdo cómo me impactó su lectura y cómo me abrió los ojos hacia el desconocido campo de la usabilidad en un momento donde no estaba tan de moda como ahora. Todos los que trabajamos en diseño de software deberíamos leerlo, no es que aporte nada concreto, lo importante es la visión global que te hace tener sobre cómo deben pensarse las cosas que fabricas teniendo en cuenta en quién las utilizará.
  • Bases de datos:
    • Oracle 8i Guía de aprendizaje (Abbey, Corey y Abramson, Oracle Press), 2001. Este libro me permitió salir airoso de una tarea que me habían encomendado por aquella época, gracias a él conseguí aprender los conceptos básicos de Oracle.
    • Oracle 9i – Servidor de aplicaciones, red y programación (Cesa Pérez, Ra-Ma), 2003. La idea era prolongar los conocimientos que había alcanzado con el anterior, pero al final todo se quedó en nada ya que profesionalmente me aparté de Oracle.
    • MySQL  Edición Especial (Paul DuBois, Prentice Hall), 2001. La lectura de este libro fue fundamental para mi en aquel momento, con él aprendí a tunear y optimizar un sistema con una elevada carga. En 2001 no había tanta literatura al respecto en Internet como hay hoy en día.
    • Microsoft SQL Server a Fondo (Soukup, Mc Graw Hill), 2001. Mi primera toma de contacto con la base de datos de Microsoft.
  • Management y gestión de proyectos:
  • Negocios y emprendedurismo:
    • El Manifiesto Cultrain (Levine, Locke, Searls & Weinberger, Deusto), 2008. Un clásico sobre la gestión de negocios en Internet orientado hacia el trato con el cliente, la apertura de información en ambos sentidos, etc.
    • El Arte de Empezar (Guy Kawasaki, Ilustrae), 2007.  Otro clásico. Kawasaki expone su experiencia en la creación y desarrollo de startups.
    • El libro negro del emprendedor (Fernando Trías de Bes, Empresa Activa), 2008. Sería el equivalente en  español al de Guy Kawasaki. Muy recomendables los tres en todo caso.
  • Multimedia:
    • Premiere 6.5 (Antonio Paniagua Navarro, Anaya Multimedia) 2002. Con este pequeño manual dí mis primeros pasos en la edición de vídeo digital.
    • Adobe AfterEfeects 5 (Anaya Multimedia), 2002. Y con este otro profundicé un poco en ellos :).
    • Photoshop 5.5 para Windows (Miguel Angel Casanova González & Azucena González Ajenjo, Anaya Multimedia), 2001. Nunca llegué a leerlo, ni ganas de hacerlo :P.

Como conclusión, lo que os comentaba anteriormente. La mayoría de libros decentes sobre lenguajes de programación son muy caros y su vida útil es, como mucho, un par de años, a no ser que sea algo más tradicional como C ó C++. Hoy en día en Internet hay literatura de sobra para aprender cualquier cosa, la única pega que teníamos era tener que pegarte al monitor para leer un pdf o imprimirlo. Por suerte, la bajada de precios de los ebooks hace que durante los próximos meses asistamos a una migración paulatina de lectura técnica hacia los libros electrónicos, y es que así ya puedes ojear tranquilamente ese pdf de Python que tienes pendiente ;).

Adobe AIR XIII – Copiar y pegar desde un DataGrid a Excel

Una de las típicas cosas que necesitamos siempre en una aplicación que presenta una lista de datos es la opción de exportar a Excel. En el caso del que hablamos hoy, necesitaba copiar los datos que se presentaban en un DataGrid de una aplicación AIR. La solución fácil habría sido lanzar una tarea de servidor que, con ayuda de alguna librería de conversión a formato Excel, devolviese el archivo xls. Pero no me gustaba la idea ya que implicaba una latencia absurda, si ya tengo los datos en mi aplicación, ¿por qué pedirlos de nuevo al servidor?

La solución que se me ocurrió es muy sencilla, copiar los datos del DataGrid al portapapeles de manera que se puedan pegar en un archivo Excel automáticamente, y que, por supuesto, mantenga el formato.

Lo complicado de todo esto no es copiar los datos sino mantener las columnas. En realidad no es que sea difícil, más bien hay que saber como generar la cadena de texto para que Excel la entienda. La solución es simplemente generar una cadena de valores separados por tabuladores y copiarla al portapapeles, automáticamente al pegar en Excel éste entenderá el formato de columnas y filas a la perfección.

Sabiendo la teoría, pasemos a la práctica. Lo que haremos será, para el DataGrid en cuestión, recorrer una a una todas sus columnas y recuperar el valor del DataProvider en ella. Tan sencillo como esto:

private function DataGridToExcel(dataGrid:DataGrid):String{
	var cadena:String = "";
	var valor:String = "";
	var saltodeLinea:String = "n";
	var data:Array;

	if (Capabilities.os.indexOf( "Mac" ) >= 0)
       	    saltodeLinea="r";

	for (var i:int = 0;i< dataGrid.columns.length-1)
            cadena+= '"' + dataGrid.columns[i].dataField+ '"';
            if (i < dataGrid.columns.length-1)
                cadena+= "t" ;
	}
	cadena+= saltodeLinea; 

	data= ArrayCollection( dataGrid.dataProvider ).source;

	for each (var item:Object in data){
		for(var k:int=0; k < dataGrid.columns.length; k++) {
			if (dataGrid.columns[k].labelFunction != undefined){
				valor= dataGrid.columns[k].labelFunction(item, dataGrid.columns[k]);
			}else{
				valor= item[ dataField ];
			}

			var pattern:RegExp;
			if (valor){
				pattern = /["]/g;
				valor= value.replace( pattern, "" );
				valor= '"' + valor+ '"';
			}else{
				valor= '""';
			}
			cadena+= valor;
			if (k < dataGrid.columns.length - 1){
				cadena+= "t";
			}
		}
		cadena+= saltodeLinea;
	}
	return cadena;
}

A mi me gusta añadir la opción como menú contextual del DataGrid, de manera que al hacer click con el botón derecho sobre el mismo se abra un menú con la entrada “Copiar a Excel“. Para hacerlo de manera reutilizable podemos hacer una llamada de este estilo en los DataGrid donde queremos utilizarlo:

private function addCopyEventDtg(dtg:DataGrid):void{
	var _contextMenu:NativeMenu=new NativeMenu();
	var _copyMenuItem:NativeMenuItem = _contextMenu.addItem(new NativeMenuItem("Copiar a Excel"));
	_copyMenuItem.addEventListener(Event.SELECT, function(event:Event):void {
		System.setClipboard( DataGridToExcel(dtg) );
	});
	dtg.contextMenu=_contextMenu;
}

Y lo lanzamos de la manera más obvia:

addCopyEventDtg(nombreDeTuDataGrid);

Este sería el resultado:

No se a vosotros, a mi me sirve :P, y queda muy aparente la cosa :).

Adobe Air XII – No se puede instalar la aplicación, este instalador no se ha configurado correctamente

Recientemente he tenido que modificar una aplicación AIR y, ya de paso, me dio por convertirla a Air2. Todo iba bien hasta que la subí al servidor para que a todos los usuarios les apareciese automáticamente la actualización pero una vez comenzaba la instalación salía el siguiente mensaje:

No se puede instalar la aplicación, este instalador no se ha configurado correctamente

Tras googlear un poco lo único que encontré es que normalmente se debe a que la has publicado con un certificado distinto al que tenía la versión anterior, pero no era mi caso. Y así, de repente, me acordé que para utilizar la instalación automática se necesitaba el publisherID y pensé, ¿no será algo de eso?.

Así es que revisé el descriptor de la aplicación Aplicacion-app.xml y me encontré con un nuevo nodo comentado:

<publisherID></publisherID>

Lo descomenté y le añadí mi publisherID que se obtiene de la versión anterior instalada en:

RUTA_DE_INSTALACION_DE_TU_APPMETA-INFAIRapplication.xml

Publicas de nuevo la aplicación y todo solucionado, se actualiza perfectamente :).

Adobe Air XI – Despliega tus aplicaciones directamente desde la web

Vuelvo con un artículo sobre la serie que hice hace algún tipo acerca de Adobe Air.

Uno de los principales problemas con los que me he encontrado al desarrollar con Air es a la hora del despliegue, ya que los clientes deben instalarse primero el framework y después la aplicación, lo que da lugar a muchas dudas y potenciales problemas. Para solucionarlo existe una librería de Adobe que permite saber si un cliente tiene instalado el framework y tu aplicación directamente desde una página web y lanzar la instalación de ambos en caso de que no los tenga, de esta manera los usuarios no tienen que descargar nada, todo muy sencillo e intuitivo.

Para interactuar con esta librería existe además una pequeña aplicación Flash que se distribuye con el sdk de Flex con los conceptos básicos: comprobar si el cliente tiene el framework y lanzar la instalación si es necesario. La podéis encontrar en:

C:Archivos de programaAdobeAdobe Flash Builder 4sdks4.0.0samplesbadge

Sin embargo puede ser realmente tedioso configurarla y programarla adecuadamente, así que existe Badger, una aplicación AIR que enmascara todo este proceso con un sencillo asistente donde rellenas los parámetros, incluidas las cadenas de texto a utilizar, y te genera el código necesario. Puedes descargarla aquí.

Al ejecutarla veremos la pantalla principal.

Por defecto solo hay un template, así que el primer menú lo podemos obviar. Con el segundo seleccionas tu aplicación AIR para que Badger cargue automáticamente algunos de los parámetros y, cuando has terminado, con la última opción “Export badge” generas el código.

Dentro de la configuración hay dos campos importantes. “application url“, debes introducir la url completa (con http://) desde donde se descargará la aplicación, y “publisher ID“, donde tienes que seleccionar la ruta donde la tienes instalada localmente para que Badger lea automáticamente este dato, imprescindible para comprobar si el cliente ya la tiene instalada.

Al subir todos los archivos generados a tu web (el html puedes integrarlo adecuadamente) y cargar la url en un navegador verás algo parecido a esto suponiendo que no tienes la aplicación (o el framework) instalados.

Al hacer click en “Instalar”, si no tienes el framework instalado, te pedirá autorización y comenzará la descarga:

Para finalmente acabar instalando tu aplicación.

Si el cliente ya tuviese la aplicación instalada podremos lanzarla automáticamente también. Para conseguirlo es necesario, primero, que en el descriptor de la aplicación hayas configurado el siguiente parámetro a “true“:

<allowBrowserInvocation>true</allowBrowserInvocation>

Ahora, si el cliente ya tiene nuestra aplicación, veremos algo como esto:

Y al hacer click en “Lanzar ahora” nuestra aplicación se cargará ella sola :).

Como veis es muy sencillo para el cliente instalar así nuestras aplicaciones AIR, nada que ver con tener que descargar el framework por un lado y la aplicación por el otro.

Nuevo proyecto en 5 horas: UsayTira.me, direcciones de correo de usar y tirar explicado paso a paso

Parece que últimamente me aburro mucho :P. Hace unos días, leyendo un artículo, se me ocurrió de nuevo explicar cómo se hacen esos sistemas de correo instantáneos que se suelen utilizar para registrarse en webs y que después no te envíen spam :P. La idea me pareció muy adecuada para poner un ejemplo práctico de algo que vimos hace tiempo sobre otras utilidades para un servidor de correo y, tal y como me ocurrió hace unos meses, lo que era un artículo se convierte en proyecto.

La idea, por tanto, es crear un sistema que, sin necesidad de ningún registro, te permita crear una cuenta de correo y recibir y leer emails en ella por espacio de una hora, al cabo de este tiempo la cuenta se autodestruye y todos los emails serán devueltos. En nuestra aplicación tendremos dos opciones para crear la cuenta, aleatoria o personalizada, creo que no hacen falta más explicaciones. Una vez usas una cuenta puedes volver a ella más tarde cuando la necesites volviendo a crear una cuenta personalizada con el mismo usuario. Esto es útil, por ejemplo, para que te recuerden la contraseña que utilizaste para registrar en aquella web de descarga de películas y de la que ya no te acuerdas ;).

Qué necesitamos

  • Servidor Linux con Qmail como MTA.
  • Apache, PHP y MySQL.
  • Pear MimeDecode: para procesar los correos entrantes con PHP.
  • Una plantilla superchula de FreeCssTemplates
  • Jquery: para todo lo que es ajax y Javascript
  • ZeroClipboard:  para copiar y pegar automáticamente
  • Jquery ScrollTo: pluggin para desplazar el scroll automáticamente.
  • Una imagen de “Cargando” para las acciones ajax que personalizas aquí.
  • Diccionarios de palabras “aleatorias”. Aquí hay unos cuantos.
  • Adodb (opcional) para el acceso a base de datos.

Eso es todo, sólo hay que juntar las piezas adecuadamente.

Preparando Qmail

Nuestro primer paso, antes de ponernos con los temas puramente web, será configurar adecuadamente el servidor de correo para nuestro propósito. Para ello necesitamos crear un usuario del sistema que reciba todo el correo dirigido a un dominio. Esto lo podemos hacer del siguiente modo:

adduser -g users -s /dev/null usaytirame
passwd usaytirame UNACLAVESUPERCOMPLICADA

Añadimos nuestro nombre de host en:

/var/qmail/control/rcpthosts

usaytira.me

Y el usuario al que dirigiremos los correos en:

/var/qmail/control/virtualdomains

usaytira.me:usaytirame

Reiniciando Qmail conseguiremos que los correos enviados a cualquier cuenta del dominio vayan al buzón del usuario indicado, es decir cualquiercosa[arroba]usaytira.me.

Pero no queremos que los correos vayan al buzón del usuario sino simplemente procesarlos. Para eso editamos el archivo:

/home/usaytirame/.qmail-default

|preline /usr/bin/php /home/usaytirame/procesa.php

Sólo con esa línea. Con este comando conseguimos redirigir los correos entrantes a un script en el que podremos recuperarlos y reutilizarlos a nuestro antojo como veremos a continuación.

Procesando los emails entrantes

Vamos a comenzar por crear una base de datos donde guardaremos los emails recibidos. Como queremos poder acceder a los emails dirigidos a cada cuenta independientemente, haremos dos tablas, una (emails) la utilizaremos como tabla maestra para las cuentas de correo que se creen y en la otra (correos) iremos almacenando los emails recibidos para cada una de esas cuentas.  La estructura sería poco más o menos la siguiente:

CREATE TABLE IF NOT EXISTS `emails` (
  `idEmail` int(11) NOT NULL auto_increment,
  `fecha` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `email` varchar(255) NOT NULL,
  `ip` varchar(15) NOT NULL,
  PRIMARY KEY  (`idEmail`),
  KEY `email` (`email`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `correos` (
  `id` int(11) NOT NULL auto_increment,
  `idEmail` int(11) NOT NULL,
  `de` varchar(255) NOT NULL,
  `para` varchar(255) NOT NULL,
  `subject` varchar(255) NOT NULL,
  `fecha` varchar(255) NOT NULL,
  `body` text NOT NULL,
  `fullmail` text NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `idEmail` (`idEmail`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Creo que es suficientemente descriptiva. El campo fecha de emails nos servirá para controlar los 60 minutos de duración máxima.

Pues ya tenemos todo preparado. Veamos cómo procesamos los emails.

/home/usaytirame/procesa.php

include ("mimeDecode.php");

$email=file("php://stdin");
$email=implode("", $email);

$params['include_bodies'] = true;
$params['decode_bodies'] = true;
$params['decode_headers'] = true;
$params['input'] = $email;
$structure = Mail_mimeDecode::decode($params);

$subject = quoted_printable_decode(trim($structure->headers['subject']));
$ddate = quoted_printable_decode(trim($structure->headers['date']));
$from = quoted_printable_decode(trim($structure->headers['from']));
$to = quoted_printable_decode(trim($structure->headers['to']));

if(ereg("<(.*)>", $to, $p))
    $to=$p[1];
$to=strtolower($to);

Tenemos la primera parte del procesado preparada. De aquí debemos destacar:

$email=file("php://stdin");

Con esto leemos desde la entrada estandar el contenido del email. Recordad que no estamos en una aplicación web sino en un script ejecutado en la consola del sistema.

La otra línea importante es:

$structure = Mail_mimeDecode::decode($params);

Con ella conseguimos procesar el email y separar su estructura en un array asociativo con los distintos parámetros. Os ayudará mucho ver el contenido de ese array:

print_r($structure)

Llegados a este punto podemos hacer una prueba. Necesitamos el contenido completo de un email, podemos sacarlo de nuestro cliente de correo o del propio servidor.

cat prueba.eml | /home/usaytirame/procesa.php

Si todo ha ido bien veremos en pantalla un array con la estructura del correo.

No voy a detallar todo el proceso ya que alargaría mucho el artículo. Vamos con el siguiente paso:

$query="select idEmail from emails where email=".$conn->quote($to);
$rs=$conn->Execute($query);
if($rs->recordcount()==0){
        exit(100);
}else{
        $idEmail=$rs->fields['idEmail'];
        $content = get_content($structure);
        $query="insert into correos
            (idEmail, de, para, subject, fecha, body, fullmail)
            VALUES
           ($idEmail,
            ".$conn->Quote($from).",
            ".$conn->Quote($to).",
            ".$conn->Quote($subject).",
            ".$conn->Quote($ddate).",
            ".$conn->Quote($content).",
            ".$conn->Quote($email).")";
        $rs=$conn->Execute($query);
}

En la primera parte del script comprobamos si la cuenta a la que va destinado el email existe en nuestra base de datos, si no, muy importante, devolvemos un código 100 que indica a qmail que debe devolver el correo ya que no existe el usuario.

Si la cuenta existe recogemos el cuerpo del mensaje. Yo lo hago con la función get_content, que analiza la estructura del correo y devuelve el contenido. Esta parte os la dejo a vosotros. Básicamente consiste en comprobar las distintas partes que puede tener un correo y devolver lo que estimemos oportuno. Un detalle muy importante a tener en cuenta es la codificación tanto del email como de nuestra base de datos y la aplicación web. En mi caso las dos últimas están en UTF-8, con lo que debo convertir todos los textos del email a esta misma codificación. La estructura que teníamos inicialmente en un array tendrá parámetros que nos indican el charset en el que viene el email. Las funciones de conversión de PHP te pueden ser útiles: iconv, utf8_encode, etc.Finalmente introducimos todos los campos del email en la base de datos.

Puedes volver a probar a procesar el email de prueba tal y como hicimos antes. Recuerda que debes añadir el registro de la tabla emails para que  guarde el correo, si no la cuenta no existirá. Una vez te funcione desde la línea de comandos ya puedes probar a enviarte un correo real :).

La aplicación web

No creo que hacer la parte web propiamente dicha necesite muchas explicaciones. Tenemos ya todos los elementos preparados, sólo debemos añadir los formularios para crear la cuenta de correo (aleatoria o personalizada) y, con un poco de ajax, ir cargando los correos a medida que van llegando. No  hay más truco.

Añadiré, eso sí, algunas aclaraciones interesantes.

Para crear las cuentas aleatorias, en vez de utilizar una secuencia aleatoria de números y letras, que daría como resultado algo ininteligible, usamos los diccionarios que comentaba más arriba. Los importamos en una tabla de la base de datos y simplemente tenemos que buscar aleatoriamente una palabra que no esté utilizada todavía como cuenta de correo, sencillo y muy impactante visualmente ya que estás ofreciendo cuentas legibles y con sentido.

Como en cualquier otra aplicación accesible públicamente, hay que añadir algún tipo de mecanismo de seguridad. En mi caso lo he hecho implementando una blacklist de direcciones IP. Cada vez que se crea una cuenta actualizo en una base de datos el número de cuentas que se han creado desde esa IP, si pasa del límite que estimemos oportuno, esa IP se pasa a la tabla de lista negra y cuando intente crear una nueva cuenta no se le dejará.

Nos falta una cosa: Eliminar las cuentas que tienen más de una hora. Muy sencillo, una tarea en el CRON que ejecuta un script que lanza una consulta a la base de datos que elimina las cuentas (y sus correos asociados) que se crearon hace más de 60 minutos.

Finalmente he añadido la opción de reiniciar esos 60 minutos de tiempo, simplemente actualizando el timestamp de la base de datos y algunos efectos visuales para plegar y desplegar los mensajes usando Jquery.

No hay mucho más, en unas cinco horas tenemos la aplicación hecha y funcionando.

Conclusiones

Como conclusión, la misma que hice hace unos meses con el primer proyecto. La copio tal cual porque es igual de válida.

Bueno, y todo este rollo ¿para qué?. Pues muy sencillo, para que veais que hoy en día la tecnología está al alcance de todos, es sencillo y rápido crear un proyecto en Internet, hay de todo por todas las esquinas, la tecnología no es lo importante, lo que verdaderamente cuenta es cómo mueves ese producto tecnológico para rentabilizarlo y obtener un beneficio de él.

Ya tengo mi proyecto superchulo funcionando, sólo me ha costado unas 5 horas de trabajo. Le he puesto un poco de Adsense por aquí y por allí. ¿Y ahora qué? ¿A esperar a que la gente entre y me haga millonario? 😛 Es mucho más complicado que eso como todos sabéis, primero tienes que tener una masa de usuarios elevada que le dé movimiento al proyecto y después tienes que conseguir que la mayoría de ellos sean gente normal, no gente técnica, usuarios avanzados que no pagamos por nada ni pinchamos en publicidad 😛 .

Hoy en día, en Internet, como en cualquier negocio, las técnicas de marketing y venta son mucho más importantes que la tecnología en sí misma, es duro reconocerlo, pero es así. De nada sirve que tengas el mejor producto del mundo mundial si no consigues que la gente lo utilice y se deje dinero, así de claro. Si tienes los conocimientos adecuados para mover el negocio, no te preocupes, la tecnología te la aporta cualquier partner por un módico precio, pero poner en manos de otro toda la estrategia de ventas de tu negocio no está tan claro ¿no?.

Espero que os sirva de algo el artículo. He querido mostrar, fundamentalmente, cómo utilizando algunas librerías que puedes obtener sin coste puedes hacer algo realmente útil y funcional con muy poco esfuerzo. Seguro que sacáis alguna idea.

Perdón por el rollo 😛 , al final me ha costado mucho más escribir el artículo que implementarlo.

Podíamos haber añadido una opción que he visto por ahí que consiste en crear una cuenta automáticamente cada vez que entra un email para una cuenta que no existe, pero estaríamos creando cuentas para todo el spam que recibamos, así que prefiero no hacerlo. Si quisierais hacerlo creo que ya sabéis cómo.