viernes, marzo 13, 2009

Workast

Tanto tiempo sin escribir ha hecho de mi conciencia algo molesto, por lo que mi primer post será ni mas ni menos que una justificación!
Estos últimos meses he estado dedicado a un proyecto personal, Open Source (como no podía ser de otra manera), de microblogging.
El proyecto en cuestión es Workast y para explicarlo, nada mejor que una comparación: Twitter.
El "problema" con Twitter, aunque parezca una contradicción, es su naturaleza pública. Si bien eso lo ha llevado a donde hoy está, en las empresas no siempre es bien visto debido a que la información que allí se vuelca es visible para todos.
Así han surgido alternativas como laconi.ca con la que cualquier empresa puede instalar dentro de sus fronteras un servidor de microbloging para sus empleados. También hay servicios como Yammer, gratuitos hasta que se quieren administrar, momento en el cual cobran a la empresa por esa posibilidad.
Esto me ha llevado a plantearme la posibilidad de hacer un software yo mismo y devolver un poco de todo lo que tomamos cada día de la comunidad Open Source.
Por supuesto me ha servido también para probar diferentes alternativas a las problemáticas que van surgiendo, y aprender en el camino.

¿Que hay hecho hasta ahora?
5700+ líneas de Java mas algunas mas de javascript (en ohloh.net la cantidad de líneas javascript es desproporcionada, ya que el 99% es de bibliotecas de terceros).

¿Y que hacen esas 5700 líneas?

Mas pantallas aquí.

¿Como?
- Escribiendo lo que te pase por la cabeza en formato wiki
- Dejando eventos para formar un calendario
- Comentando lo que otros escriben
- Organizando lo que te parece útil mediante etiquetas
- Siguiendo a otra gente para que aparezca en tu vista de novedades
- Creando y escribiendo dentro de grupos, para organizar mejor las novedades
- Filtrando las novedades por etiqueta, texto o tipo de actividad

¿Y con qué tecnología está desarrollado?
- Spring framework
- Hibernate
- Hibernate Validator (JSR-303)
- RESTEasy (JAX-RS)
- jQuery
- MySQL/HSQL
- Joda Time
- info.bliki

Próximos pasos
- Investigar Spring 3.0, con su soporte para REST y Bean Validation
- Completar el roadmap
- Actualizar este blog con las novedades que vayan ocurriendo en el desarrollo

Luego de este resumen, queda por decir que ya hay una versión descargable aquí (alpha), y que todos los comentarios y sugerencias que me hagáis llegar son más que bienvenidos.

viernes, junio 27, 2008

Visualización de la historia de commits de Eclipse IDE



code_swarm - Eclipse (short ver.) from Michael Ogawa on Vimeo.

viernes, febrero 29, 2008

Spring Integration


El nuevo miembro de la famila, Spring Integration, nos permite utilizar los famosos patrones de integración dentro de nuestra aplicación, sin alejarnos del modelo de programación de Spring.

Con una configuración tan sencilla como esta se logra leer ficheros de un directorio y procesarlos:


<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/integration"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd">

<message-bus/>
<channel id="fileInputChannel" />
<annotation-driven/>

<context:component-scan base-package="com.habuma.si.example" />

<file-source directory="/Users/wallsc/sucker"
poll-period="1000" channel="fileInputChannel"/>
</beans:beans>
----
package com.habuma.si.example;
import org.apache.log4j.Logger;
import org.springframework.integration.annotation.Handler;
import org.springframework.integration.annotation.MessageEndpoint;

@MessageEndpoint(input = "fileInputChannel")
public class FileSucker {
private static final Logger LOGGER = Logger.getLogger(FileSucker.class);

@Handler
public void suckAFile(String fileContents) {
LOGGER.debug(fileContents);
}
}


Pero todo no acaba allí. Los mensajes de entrada (los ficheros en el ejemplo anterior) se pueden enrutar hacia otras salidas: otros ficheros, colas JMS, servicios web o cualquier sistema del que dispongamos (o desarrollemos) adaptadores.
Del mismo modo, los mensajes de entrada pueden provenir de diversas fuentes.

El ejemplo anterior está amablemente copiado de Spring Integration: Meet the channel adapters. En el mismo blog de Craig Walls encontraremos mas información y ejemplos de utilización.

miércoles, agosto 01, 2007

Atlassian compra Cenqua


Quién sabe que puede surgir de esta unión: Atlassian compra Cenqua
Con aplicaciones como FishEye, Crucible y Clover, la gama de productos de Atlassian es impresionante.

jueves, julio 12, 2007

Usando Confluence wiki para documentar en forma agil


Gestionar los requisitos de un proyecto no es tarea fácil. ¿Pero no es fácil por la complejidad de obtenerlos o la de documentarlos? Son dos caras de una misma moneda y en definitiva la buena gestión de ambas tareas hará que el proyecto salga adelante con éxito o no.
Para obtenerlos hay muchas metodologías, tantas como gustos. Quizás RUP sea la mas conocida en proyectos grandes y las variantes de Agile para proyectos mas pequeños. Pero cualquiera sea la metodología elegida del proyecto, y por lo tanto de como gestionar los requisitos, las herramientas para documentar son un poco mas que penosas.
El rey de las herramientas de requisitos, RequisitePro es una arcaica mezcla de MS Word y aplicación propietaria, junto con una herramienta de reportes (SODA) en MS Word. Nada ágil por cierto. Quizás con el nuevo desarrollo Jazz todo mejore para Rational, pero para eso faltan no menos de 2 años. ¿Que nos queda entonces para documentar los requisitos? Quizás Enterprise Arquitect sea bueno para esto, pero sigue siendo un cliente pesado.
¡Bienvenidos a la web entonces! Quizás el actual sistema de documentación distribuído mas popular de estos días sea la wikipedia, por que no documentar entonces un proyecto en un wiki? El primer pensamiento en contra es por lo "desestructurada" que suele ser la información guardada en un wiki, pero alguas herramientas nos permiten agregar control sobre los formularios de entrada y edición de datos. XWiki es un ejemplo de ello, pero el ejemplo que nos ocupa hoy está desarrollado con Confluence y una serie de plugins disponibles para esta plataforma.

Paso 1. Crear plantilla de doucmento Cliente.
primero crearemos una plantilla para contener los datos de los clientes, de los cuales, por simplicidad, solo guardaremos el nombre. Para ello deberemos ir a "Browse Space/Advanced/Templates/Add New Space Template" y agregar el siguiente código bajo el nombre "Client":



| Nombre: | {page-info:title} |

{report-table}
{content-reporter:spaces=@self|type=page|scope=@self > children}
{text-sort:content:title|order=ascending}
{text-filter:data:FormName|include=Project}
{content-reporter}
{report-column:title=Nombre}{report-info:content:title|link=true}{report-column}
{report-column:title=Project Leader}{report-info:data:ProjectLeader|link=true}{report-column}
{report-column:title=Start Date}{report-info:data:StartDate|link=true}{report-column}
{report-column:title=End Date}{report-info:data:EndDate|link=true}{report-column}
{report-column:title=Status}{report-info:data:Status|link=true}{report-column}
{report-table}
(+) {add-page:template=Project|live=true}Agregar proyecto{add-page}

{set-data:FormName|hidden=true}Client{set-data}


En esta plantilla vemos una tabla con el título del documento, un reporte de proyectos y un link para agregar un nuevo proyecto. Por último el tag {set-data}, del plugin Scaffolding, nos permite identificar este documento con la propiedad "FormName=Client", lo que nos facilitará los reportes de clientes que querramos hacer.

Paso 2. Crear documento raíz.
Luego necesitamos una página en algún lugar de nuestro wiki, que contenga el listado de clientes. Para el listado utilizaremos el plugin Reporting:



{report-table}
{content-reporter:spaces=@self|type=page|scope=Clients > children}
{text-sort:content:title|order=ascending}
{content-reporter}
{report-column:title=Nombre}{report-info:content:title|link=true}{report-column}
{report-table}

(+) {add-page:template=Client|live=true}Agregar cliente{add-page}


Al final de la página se puede ver el tag {add-page} para crear documentos de tipo cliente mediante una plantilla previamente creada. Luego de salvar la página con el título "Clients", podemos agregar un cliente:

Paso 3. Agregar un cliente.


Lo que nos presentará un documento a crear en base a la plantilla "Client":



Que luego de salvarlo tendrá la siguiente apariencia:



Paso 4. Crear plantilla de proyecto
Análogamente, para crear un proyecto deberemos crear primero una plantilla, con título "Project":

| Nombre: | {page-info:title} |
| Cliente: | {report-link:content:parent > content:url}{report-info:key=content:parent}{report-link} |
| Codigo JIRA | {text-data:JiraCode|content=text|width=100px}{text-data} |
| Project Leader: | {list-data:ProjectLeader|required=true}
{user-options:groups=confluence-users}
{list-data} |
| Team Members: | {list-data:TeamMembers|type=check|multiple=true}
{user-options:confluence-users}
{list-data} |
| Start Date: | {date-data:StartDate|format=dd-MMM-yyyy}today{date-data} |
| End Date: | {date-data:EndDate|format=dd-MMM-yyyy}{date-data} |
| Status: | {list-data:Status}
{list-option}Unstarted{list-option}
{list-option}In progress{list-option}
{list-option}Awaiting approval{list-option}
{list-option}Completed{list-option}
{list-data} |

[Requerimientos|Requirements]
[Casos de Uso|UseCases]
[Iteraciones|Iterations]
[Actas de Reunión|MeetingMinutes]
[Informes de estado de proyecto|StatusReports]

{set-data:FormName|hidden=true}Project{set-data}


Esta plantilla tiene los datos propios del proyecto, incluyendo su project leader, participantes, fecha de inicio y fin y estado. Al final también hay links a los documentos que harán de padres de los requisitos, las iteraciones y todos los demás documentos que nuestra metodología requiera.

Paso 5. Crear un proyecto.
Luego de creada la plantilla de proyecto podremos crear proyectos, mediante el link en el formulario correspondiente al cliente:



Lo cual nos preguntará el título del proyecto, y luego los datos que especifica la plantilla correspondiente:



Que una vez salvada tendrá la siguiente apariencia:



Paso 6. El listado de requierimientos.
Queda como ejercicio resolver que cada proyecto contenga su propia lista de requerimientos, ya que como ven en la plantilla de proyecto el link a los requerimientos es a una página genérica, llamada "Requirements": [Requerimientos|Requirements]. La mejor posibilidad es utilizar un "space" para cada proyecto.
Pero vamos con el diseño de la plantilla de la citada página padre "Requirements":

h3.Requerimientos Funcionales

{report-table}
{content-reporter:type=page|scope=@self > children}
{text-sort:data:Date|order=ascending}
{text-filter:data:FormName|include=Requirement}
{text-filter:data:Type|include=Funcional}
{content-reporter}
{report-column:title=Título}{report-info:content:title|link=true}{report-column}
{report-column:title=Estado}{report-info:data:State}{report-column}
{report-column:title=Prioridad}{report-info:data:Priority}{report-column}
{report-column:title=Dueño}{report-info:data:Owner}{report-column}
{report-column:title=Creado}{report-info:content:creation date}{report-column}
{report-column:title=Creado por}{report-info:content:creator}{report-column}
{report-table}

h3.Requerimientos No Funcionales
{report-table}
{content-reporter:type=page|scope=@self > children}
{text-sort:data:Date|order=ascending}
{text-filter:data:FormName|include=Requirement}
{text-filter:data:Type|include=No Funcional}
{content-reporter}
{report-column:title=Título}{report-info:content:title|link=true}{report-column}
{report-column:title=Estado}{report-info:data:State}{report-column}
{report-column:title=Prioridad}{report-info:data:Priority}{report-column}
{report-column:title=Dueño}{report-info:data:Owner}{report-column}
{report-column:title=Creado}{report-info:content:creation date}{report-column}
{report-column:title=Creado por}{report-info:content:creator}{report-column}
{report-table}

(+) {add-page:template=Requirement|live=true}Agregar requerimiento{add-page}


Se ha dividido la página en requerimientos funcionales y no funcionales, pero eso es a gusto del consumidor. Lo que hay que saber es que esta página lista los documentos de tipo "Requirement", creados a su vez con la plantilla "Requirement":

Paso 7. El formulario de requirimientos:

{section}
{column:width=300px}

*Detalles*
{table:width=300px}

{table-row}
{table-cell}
Tipo:
{table-cell}
{table-cell}
{list-data:Type|required=true}
{list-option}Funcional{list-option}
{list-option}No Funcional{list-option}
{list-data}
{table-cell}
{table-row}
{table-row}
{table-cell:width=100px}
Prioridad:
{table-cell}
{table-cell:width=200px}
{list-data:Priority}
{list-option}Sin asignar{list-option}
{list-option}Alta{list-option}
{list-option}Media{list-option}
{list-option}Baja{list-option}
{list-data}
{table-cell}
{table-row}
{table-row}
{table-cell:width=100px}
Estado:
{table-cell}
{table-cell:width=200px}
{list-data:State}
{list-option}Propuesto{list-option}
{list-option}Rechazado{list-option}
{list-option}Aprobado{list-option}
{list-option}Diferido{list-option}
{list-data}
{table-cell}
{table-row}
{table-row}
{table-cell}
Dueño:
{table-cell}
{table-cell}
{list-data:Owner|required=true}{user-options:groups=confluence-users}{list-data}
{table-cell}
{table-row}

{table}

{column}
{column:width=90%}
*Descripción*
{text-data:Description|type=area|content=wiki|width=100%|height=500px}
{column}

{section}

{set-data:FormName|hidden=true}Requirement{set-data}


El resultado es un formulario:



Y un listado de todos requerimientos:



Finalmente, queda por decir que el plugin para Graphviz nos permite hacer diagramas sin salir del wiki (ver UML class diagrams in Confluence using Graphviz and DOT), lo que aumenta varios grados la agilidad de la documentación y permite gráficos como este:

martes, julio 03, 2007

Gestión de excepciones en Java


Acerca de Exception-Handling Antipatterns
Tim McCune nos propone en un "antiguo" artículo (del 2006) varias formas no hacer bien las cosas cuando de excepciones se trata. Sin copiar todo el artículo, aquí van algunos de mis antipatrones preferidos:

Log and Throw
(Duplicación de entradas de error en los logs.)
catch (NoSuchMethodException e) {
e.printStackTrace();
throw new MyServiceException("Blah", e);
}


Throwing Exception
(Poco explícito)
public void foo() throws Exception


Catch and Ignore
(Se destruye la excepción y no se devuelve un error)
catch (NoSuchMethodException e) {
return null;
}


Destructive Wrapping
(Se destruye la excepción original)
catch (NoSuchMethodException e) {
throw new MyServiceException("Blah: " +
e.getMessage());
}

martes, mayo 08, 2007

Semmle, al fin una idea original


Semmle es una herramienta para hacer consultas de nuestro código como si de una base de datos se tratara. La siguiente consulta
from Class c 
where c.declaresMethod("equals")
and not(c.declaresMethod("hashCode"))
select c.getPackage(),c
devuelve el resultado:
Photo Sharing and Video Hosting at Photobucket
para el working space "framework" de mi workspace de eclipse (Todas las clases que definen un método equals, pero no hashCode).
Basado en ".QL", un lenguaje de queries orientado a objetos, permite hacer nuestras propias clases para ampliar las funcionalidades de búsqueda.
Con una biblioteca de métricas de código tales como Lack of Cohesion of Methods y Afferent Coupling/Efferent Coupling, solo le falta una tarea ant para agregar esta herramienta al servidor de integración continua.
Al fin una idea original!