12/27/2004

MDA; visión escéptica de Dave Thomas.



El autor Dave Thomas, en la revista IEEE Software, realiza comentarios sobre la controvertida MDA (Model Driven Architecture) de la OMG (Object Management Group).

Un Modelo NO ES un producto, y es necesario darse cuenta de que es, para bien y para mal, la abstracción de lo que se desea conseguir.

Proviniendo de OMG, MDA se basa en UML (Unified Modeling Language). La ingeniería de Modelos, o desarrollo guiado por el modelo, trata el desarrollo de software como un conjunto de transformaciones entre modelos sucesivos, de requisitos a análisis, hasta llegar al despliegue (traducción del original).

MDA se especializa mediante la utilización de MOF (MetaObject Facility) y modelos UML. MOF permite, en principio, la unificación de UML, perfiles UML y, por tanto modelos específicos de MDA.

El autor es excéptico con respecto al uso indiscriminado de estos modelos.

Creo que puede ser interesante ver en más detalle el mundo de las arquitecturas de modelos y los DSLs (Domain-Specific Language).

12/18/2004

12/14/2004

Continuous Integration

Continuous Integration

Este artículo de Martin Fowler y Mathew Foemmel discute sobre la necesidad de que los proyectos de desarrollo de software dispongan de una arquitectura de integración continua. Para ello, introducen la herramienta de opensource, CruiseControl que permite automatizar este proceso. En este post resumo sus características básicas, aunque recomiendo leer el artículo original, que no es tan largo ;)

La idea básica es la de disponer constantemente de una "build" estable, es decir, que la creación esté automatizada, y que exista un core de pruebas que se ejecuten en cualquier momento deseado y aseguren un mínimo. En muchos proyectos se realizan "builds" diarias, pero otras filosofías, como la de eXtremeProgramming plantean que las builds se realicen constantemente, cuando sean necesarias.

Las necesidades básicas para que todo funcione son las siguientes:
  • El código reside en un único lugar (versión actual, y previas): para ello ha de utilizarse una herramienta de configuración con control de fuentes y control de versiones. CVS es quizá la herramienta más utilizada de este tipo.
  • Y no sólo el código: también todo fichero susceptible de cambio en el proceso de construcción de software: scripts, properties, esquemas, documentación, ... todo aquello que NO SE GENERE AUTOMÁTICAMENTE.
  • El proceso de build debe ser tan sencillo como utilizar un único comando.
  • También con un único comando debería poder lanzarse una suite de pruebas de sistema.
  • Consecuentemente, todo el mundo debería de ser capaz, en todo momento, de disponer de un buen ejecutable.

Por otra parte, una build "exitosa" ha de cumplir ciertas reglas para ser considerada como tal:

  • Todo el código fuente "checked out" se extrae.
  • Todo fichero se compila de cero.
  • Los objetos resultantes se enlazan y despliegan si es necesario (.jar). Estos dos últimos puntos requieren utilizar una "make tool" adecuada, más allá de scripts a mano. En Java, una herramienta open source muy usada es "Ant", anuque existe alguna otra, como Maven, que se basa en Ant y permite aún un mayor control.
  • El sistema se arranca automáticamente, y se lanza una suite de pruebas (como mínimo unas "smoke tests"). Las pruebas se basan en el enfoque de XP: test first. No se programa nada sin tener previamente implementada una prueba que sólo funcione si se desarrolla esa característica concreta -es discutible que esto sea posible en la práctica, en todos los casos, pero en sí es una "best practice" recomendable-. Para la realización de pruebas unitarias, el artículo recomienda JUnit (de la familia de xUnit).
  • Todo OK sin intervención "humana": eso es una build exitosa.

El "Master Build" que proponen corre en una sóla máquina, y es un proceso Java que se ejecuta continuamente ( a-la demonio):

  1. Si no hay build ejecutándose, el proceso chequea el repositorio de build cada pocos minutos.
  2. Si no hay nadie que hay realizado un check-in (hace cinco minutos o más, para evitar conflictos con gente que esté realizando un check-in en este preciso momento), sigue esperando.
  3. Si hay alguien, comienza el proceso de build.
  4. Si el proceso termina satisfactoriamente, se marcan las fuentes que fueron chequeadas con un "build number".
  5. El proceso de build envía un correo a los desarrolladores que hicieron check-in con un status del proceso (como dice el artículo, se considera de mala educación el irse del trabajo tras un "check-in" sin esperar a recibir este correo). Además, este status se almacena en un servidor web de la máquina de build para que pueda ser consultado.

Se recomienda realizar siempre builds completas, pero es cierto que en algunos entornos esto es imposible (cierto proyecto en el que estuve tardaba horas y horas), por lo que un esquema mixto (incremental durante el día y una full build por las noches) puede ser adecuado en esos casos.

Hasta ahora sólo nos hemos centrado en la build general. Hay que tener en cuenta que esta build debe poder ser recreada en local, para que cada desarrollador pueda probar que el check-in que va a realizar va a funcionar adecuadamente; para ello, cada vez que se vaya a empezar un nuevo desarrollo -tarea, caso de uso, ...-, hay que sincronizarse con la herramienta de control de código (un checkout completo). Por otra parte, los desarrolladores deberían intentar realizar un check-in diario, para que las builds tengan sentido.

CruiseControl se ocupa de realizar la build continua. En su web hay bastante información sobre cómo utilizar Ant por debajo para realizar esa build, pero también es posible utilizar otras herramientas, como la arriba mencionada Maven.

9/14/2004

Obtención de conocimiento para proyectos SW

Comentario al artículo "Toward a Practical Solution for Capturing Knowledge for Software Projects", de S. Komi-Sirviö y A. Mäntyniemi. IEEE Software, Mayo/Junio 2002

Los autores se centran en:

  • mantener información sobre proyectos pasados, que denominan "Lessons to learn" database. Pero crear una bd no significa que se utilice.

  • "Data Transfer Days": reuniones de análisis de problemas y éxitos pasados. El inconveniente era juntar a la gente, pero el éxito es mayor que con la bbdd.



El problema es que estas acciones no están incorporadas a la metodología organizacional. Por otra parte, ningún cambio que ignore los hechos comportamentales y culturales de la organización, podrá tener éxito.

9/13/2004

XP en una compañía con Proceso definido

Comentario al artículo "Launching Extreme Programming at a Process-Intensive Company, de J. Grennnig, en el IEEE Software de Noviembre/Diciembre de 2001

En un ejemplo "real", una empresa tiene mucho "overhead" al desarrollo de software:

  • Comienzo de Diseño

  • Modelado en Rose

  • Planificación de una reunión de revisión

  • Distribución de materiales a revisar
  • Introducción de temas a discutir en la web

  • Reunión de revisión

  • Acta de la reunión con tareas a realizar

  • Reparación de defectos

  • Cierre de defectos en la web

  • Modificación de documentos

  • Vuelta a empezar



¿Cuánta documentación es necesaria?

  • La suficiente para la definición de requisitos de producto, permitir revisiones técnicas y dar soporte al mantenimiento

  • Código fuente comprensible

  • Documentación de interfaz



Utilizan CppUnit como framework de pruebas unitarias.

Al comienzo del proyecto, se trabaja sobre casos de uso -sin descripción detallada, sólo el nombre-, y se priorizan. No se realiza un diagrama de casos de uso, se da por hecho que no hay especialización.

El resto del proyecto se realiza siguiendo casi al 100% el XP, pero teniendo en cuenta la forma de trabajar habitual del cliente -p.e. siguiendo sus convenciones de codificación y nombrado-.



Desarrollo de SW en proyectos Internet

Comentario sobre artículo "Software Development on Internet Time", del Computer de Octubre del 99

Las pequeñas y medianas empresas, así como departamentos de grandes compañías que estén involucradas en proyectos "internet", han de desarrollar técnicas y metodologías mucho más flexibles.

Para comentar esta idea, se basa en entrevistas con Microsoft y Netscape para estudiar su modo de trabajo diario -lo que el autor denomina "Synchronize and stabilize"-.

Microsoft:

  1. Builds de producto diarias

  2. Dos o más hitos de proyecto -milestones-: estos son los momentos de "estabilización"

  3. Releases alpha y/o beta



Los equipos de Microsoft no intentan tener una especificación completa al comienzo del proyecto: crean un "vision statement". Este "outline", sin embargo, ha de ser lo suficientemente detallado como para poder realizar una estimación de tiempos y equipo necesario.


Las alpha y beta salen en cada hito de proyecto -las alpha son internas y las beta externas, por lo que éstas últimas no siempre-.

Se crea un "buffer time" de entre un 20-50% en cada hito para hacer frente a dificultades inesperadas, retrasos, etc. En el caso de productos con fecha límite estricta, se pueden llegar a eliminar funcionalidades para cumplir la fecha de salida.

Idea interesante de Netscape: Advance Planning Meetings, una especie de brainstorming una vez cada, aproximadamente, tres meses, que reúne a ejecutivos, ingenieros y comerciales para pensar en nuevas características y planes de salida de cada nuevo producto.

9/10/2004

Cuándo realizar menos pruebas

Comentario de un artículo de IEEE Software del número de Septiembre/Octubre de 2000.
When to test less, de Tim Menzies y Bojan Cukic


El artículo defiende que en pequeños proyectos, un gran conjunto de pruebas no verifican mejor el sistema que un pequeño número.

Si una entrada al azar en una prueba de caja negra tiene una probabilidad x de provocar un fallo, entonces 1-x es la probabilidad de que esa entrada no falle.
Si se realizan N pruebas de caja negra => (1-x)^N es la probabilidad y de encontrar un fallo en N pruebas aleatorias.
(si x=0.0001, se requiere 46000 pruebas para estar seguro al 99% de encontrar ese fallo).


Sin embargo, las empresas medianas-pequeñas no realizan más de centenares de pruebas -a veces decenas nada más-.

Los autores describen la "forma" -shape- de un programa como los diferentes caminos dentro de él. Entonces, la pregunta es cuál debe ser la "forma" de una aplicación para que se pueda probar adecuadamente utilizando recursos limitados.

De hecho, lo que afirman es que una forma correcta es aquella que nos permite tomar una de las siguientes dos decisiones:

  • la forma del programa es tan compleja que no merece la pena realizar muchas pruebas, pues no podrán encontrar fallos residentes en regiones remotas del código.

  • la forma del programa es tan simple que un conjunto limitado de pruebas será suficiente.




En definitiva, proponen lo siguiente: ejecución rutinaria de pruebas nocturnas con miles de test cases generados de una manera totalmente aleatoria (sin ningún tipo de desviación, según su modelo NAYO).

8/23/2004

Dejo la Nebrija

Sólo un pequeño mensaje para avisar a aquellos de vosotros que leáis este blog que he dejado la Universidad Antonio de Nebrija, y que desde la semana pasada estoy de nuevo en Denodo Technologies como investigador.

Espero, a partir de ahora, seguir con la idea del blog y que no se quede tan estancado como ahora.

4/06/2004

Sun announces peace with Microsoft: Legal and technical

Sun announces peace with Microsoft: Legal and technical

El título lo dice todo y, aunque llevo mucho sin escribir en el blog -debido sencillamente a: nueva asignatura de Calidad del SW + múltiples cambios en la de Ingeniería del Software + sigo con Sistemas en Internet + ... -, esta noticia merecía un inciso.

Espero volver en breve con muchos temas en cartera...

1/29/2004

Qué hay de nuevo en UML 2.0 -a partir del libro de Fowler- (II)

Books by Martin Fowler

En esta segunda parte me centro en comentar las novedades con respecto a los diagramas de secuencias:

Recordamos que el d. de secuencia es el d. de interacción más comúnmente utilizado.

En UML1 los elementos que participan en un d. de secuencia eran objetos. Sin embargo, en UML2 el concepto es más ambiguo, y se denominan "participantes" -no sé por qué, tengo que mirarlo-.

Cuando un mensaje proviene de un emisor desconocido, se denomina "found message" -desconocido significa, sencillamente, que el emisor no aparece en el diagrama-.

El borrado de un participante se marca con un aspa, que puede provenir de la invocación de un método, o ser un "suicidio".



Los d. de secuencia no son buenos a la hora de mostrar flujos, pero se puede, mediante la utilización de "marcos de interacción": cuadradados que rodean la parte del d. de secuencia que es un flujo. Obviamente, al igual que los bucles pueden anidarse, aquí podemos tener marcos dentro de otros marcos.

... personalmente, creo que lía bastante la cosa.

Asíncronía


Un cambio en UML2 es que los mensajes síncronos pasan a modelarse como flechas rellenitas, mientras que los asíncronos son las flechas aspadas -en lugar de la media flecha-.

1/28/2004

Gestión de Sistemas en Internet. Pequeños cambios

IT4128: Introducción a la asignatura

Podríamos considerar que este curso es de transición con respecto a GSI. Los cambios más importantes son los siguientes:


  1. Utilización de BEA Weblogic Server 8.1 para la realización de los ejemplos y prácticas en la parte de J2EE con servlets y JSPs.

  2. Más énfasis al XMLSchema, ya que algún ejemplo se pondrá con JAXB, que requiere de su uso.

  3. Seguramente se amplíe la convalidación de clases por asistencia a seminarios (Microsoft, BEA, primordialmente)



El temario, por tanto, queda como sigue:


  1. Presentación de la asignatura. Introducción a las aplicaciones web.

  2. XML. Introducción (I)

  3. XML. DTD (II)

  4. XML. XMLSchema (III)

  5. XML. XMLSchema (IV)

  6. XML. DOM (V)

  7. XML. SAX (VI)

  8. XML. JAXB (VII)

  9. Protocolo HTTP 1.1 (I)

  10. Protocolo HTTP 1.1 (II)

  11. Protocolo HTTP 1.1 (III)

  12. Patrones Arquitectónicos de Acceso a Repositorio (Fowler)

  13. Introducción a J2EE

  14. Servlets. Teoría (I)

  15. Servlets. Ejemplos básicos y utilización de BEA Weblogic Server (II)

  16. Servlets. Manejo de sesión (III)

  17. JSPs. Ejemplos básicos (I)

  18. JSPs. Manejo de sesión (II)

  19. JSPs. Otras características de JSPs (III)

  20. Patrones Arquitectónicos de Presentación (Fowler)

  21. Patrones arquitectónicos de Lógica de Negocio

  22. Introducción a EJBs. Componentes y tipos de EJBs (I)

  23. Introducción a EJBs. Ejemplos (II)



Toda la asignatura se realiza en el laboratorio.

Las prácticas vuelven a ser tres.


  1. Comenzando las clases teóricas por XML nos permite que la primera práctica sea la realización del XmlSchema/DTD del proyecto a realizar -ver más adelante-, ya programado (fecha de entrega aproximada: 20/III) .

  2. La segunda práctica sería la primera iteración de la implementación, realizada con Servlets (fecha de entrega aproximada: 14/IV).

  3. La tercera práctica les exigiría la implementación siguiendo el modelo MVC, con servlets y JSPs (fecha de entrega: día del examen).



Proyecto a realizar: seguramente, un BLOG con capacidad de estructuración por tópicos. No es demasiado complicado, y permite, como siempre, utilizar todas las capacidades vistas en clase: XML, manejo de sesión, utilización de patrones, etc.

Temas a tener en cuenta:
- Probar todos los ejemplos tanto en WL como en la implementación de referencia de Sun, para evitar sustos.
- Revisar la siguiente documentación:
- HTTP1.1 -mejorar-
- XMLSchema -mejorar-
- Mapping transparencias propias - transparencias BEA en J2EE.
- Patrones arquitectónicos: ejemplos -quizá los suyos directamente en Java y C#-.





1/24/2004

Repaso de JDBC

JDBC drivers in the wild

Este artículo de la revista electrónica JavaWorld, escrito por Nitin Nanda, resume las características principales de cada tipo de driver JDBC. A pesar de ser un artículo del 2000, nos sirve para tener una visión general de los drivers.



  1. Tipo 1: Bridge JDBC-ODBC

  2. Tipo 2: API nativo /driver Java parcial

  3. Tipo 3: Protocolo de red/driver todo Java

  4. Tipo 4: Protocolo nativo/driver todo Java





Tipo 1: Bridge JDBC-ODBC

Este driver traduce todas las llamadas JDBC a ODBC y las envía al driver ODBC (ver figura).

Esto nos lleva a que el driver ODBC tenga que estar en la máquina cliente.

A favor: los drivers ODBC están en todas partes.
En contra: prestaciones, instalación ODBC en el cliente.


Tipo 2: API nativo /driver Java parcial

Convierte las llamadas JDBC a llamadas propietarias del Gestor relacional. Ver figura.

A favor: mejores prestaciones que el tipo 1.
En contra: la biblioteca del vendedor ha de estar en la máquina cliente -no utilizable en aplicaciones internet-. Peores prestaciones que tipo 3 y tipo 4.


Tipo 3: Protocolo de red/driver todo Java

Sigue una arquitectura en tres capas. Si la capa intermedia es Java, ésta puede utilizar un tipo 1 ó 2 para hablar con la base de datos.

A favor: no hace falta instalación en máquina cliente del driver nativo. Puede proveer cache, balanceo de cargas, etc.
En contra: la capa intermedia requiere código para la base de datos.


Tipo 4: Protocolo nativo/driver todo Java

Convierte las llamadas JDBC a nativas de manera que el cliente se pueda comunicar directamente con el servidor gestor (ver figura).

A favor: prestaciones, sin instalaciones nativas en el cliente. Se permite la carga dinámica de drivers.
En contra: driver diferente para cada base de datos.



Conclusiones del benchmarking

Este artículo concluye que:

1. El tipo 1 no debería de utilizarse.
2. El tipo 2 es OK para intranets, pero 3 y 4 siguen siendo mejores.
3. Tipo 3 OK cuando hay multitud de bases de datos.
4. Para el resto, tipo 4.




1/23/2004

La insoportable levedad de las pruebas software

Test Infected: Programmers love writing tests

JUnit es un framework de pruebas unitarias de regresión que se ha convertido en un referente cuando deseamos realizar sw fiable.

La forma de trabajar es la siguiente, que se nos muestra en el artículo:

1. Escribe el test que, obviamente, ahora no funciona.
2. Escribe el código que hará que el test funcione.

Esta fórmula es la utilizada en las metodologías ágiles: "code a little, test a little, code a little, test a little" ;)

JUnit contiene la clase TestCase, que heredaremos en nuestra clase de prueba (p.e. MoneyTest). Esta clase irá, por convenio, en el mismo paquete que la clase a ser probada, para que tenga acceso a los métodos de paquete.

public class MoneyTest extends TestCase {
//…
public void testSimpleAdd() {
Money m12CHF= new Money(12, "CHF"); // (1)
Money m14CHF= new Money(14, "CHF");
Money expected= new Money(26, "CHF");
Money result= m12CHF.add(m14CHF); // (2)
Assert.assertTrue(expected.equals(result)); // (3)
}
}

La última línea es la más interesante, por dos temas:

1. Hay que sobrecargar el método Object.equals para comparación de objetos.
2. Se utiliza Assert.assertTrue

JUnit provee en la clase Assert diferentes tipos de métodos:

  • assertEquals para booleans, chars, double, float, int, Objects, ...

  • assertFalse

  • assertNotNull

  • assertNotSame

  • assertNull

  • assertSame




Una vez que hemos definido las diferentes pruebas a realizar en nuestra clase de pruebas, hay que definir cómo se ejecuta un caso de prueba, y cómo se ejecuta una "suite" de pruebas.

Modos de prueba en JUnit

1. Estático
2. Dinámico

1. Se sobrecarga el método TestCase.runTest y se invoca mediante una clase anónima interna:
TestCase test= new MoneyTest("simple add") {
public void runTest() {
testSimpleAdd();
}
};

JUnit implementa un patrón Template Method para ejecutar adecuadamente ese método.

2. Utilización de introspección (Java Reflection) para implementar el método runTest. Asume que el nombre del test es el nombre del método del caso de prueba:
TestCase test= new MoneyTest("testSimpleAdd");


Suites de pruebas

TestSuite es un composite de Tests:

public static Test suite() {
TestSuite suite= new TestSuite();
suite.addTest(new MoneyTest("testEquals"));
suite.addTest(new MoneyTest("testSimpleAdd"));
return suite;
}

También hay otras maneras -desde JUnit 2.0-:

public static Test suite() {
return new TestSuite(MoneyTest.class);
}

JUnit extrae todos los métodos de pruebas automáticamente.

public static Test suite() {
TestSuite suite= new TestSuite();
suite.addTest(
new MoneyTest("money equals") {
protected void runTest() { testEquals(); }
}
);

suite.addTest(
new MoneyTest("simple add") {
protected void runTest() { testSimpleAdd(); }
}
);
return suite;
}

Lo mismo, pero de manera estática.




Ingeniería del Software II: fundamentos del temario (I)

LS4118: Introducción a la asignatura

La asignatura de Ingeniería del Software II se centra sobre todo en la utilización de mejores prácticas en el diseño de sistemas orientados a objetos. Sin ser éste el único objetivo de una asignatura de este tipo, sí es verdad que ahora mismo es la única asignatura obligatoria donde los alumnos salen con conocimientos de las diferentes arquitecturas existentes, de lenguajes de modelado, patrones, etc. Otras asignaturas, como Sistemas Distribuidos, Sistemas en Internet o, de alguna manera, Gestión de Red, abarcan parte de esta problemática, pero de manera insuficiente.

Vicente Orjales y yo estamos trabajando en la definición de un temario que aporte a los alumnos una máxima ganancia, aunque, sin duda alguna, con un esfuerzo por su parte bastante mayor que el realizado en el primer cuatrimestre.

1. Presentación (1 sesión)
2. Repaso a técnicas de orientación a objetos y metodologias de procesos.
En este capítulo se repasa el Proceso Unificado, y sobre todo, los conceptos de OO más importantes en cuanto a patrones: dicotomía interfaz-implementación y la guerra herencia vs. delegación (1 sesión)
3. Introducción a patrones (1 sesión)
4. Patrones estructurales: Composite. Utilizándolo como ejemplo inicial, dedicar un par de clases a explicarlo con sumo detalle, y con ejemplos en Java -¿y C#?-. Nos llevaría al menos dos sesiones, posiblemente tres. (3 sesiones)
5. Patrones estructurales: Proxy. (2 sesiones)
6. Patrones estructurales: Adapter. (1 sesión)
7. Patrones creacionales: Abstract Factory & Factory Method.(1 sesión)
8. Patrones creacionales: Builder.(1 sesión)
9. Patrones de comportamiento: State & Strategy.(1 sesión)
10. Patrones de comportamiento: Observer.(1 sesión)
11. Patrones de comportamiento: Command.(1 sesión)

Algunos de los patrones restantes se mandarán como trabajo para casa, p.e.: Prototype (C), Flyweight (S), Facade (S), Iterator (B), Visitor (B), Template Method (B), Chain of Responsibility (B).

Tras estos patrones se realizará un ejemplo que conjugue gran cantidad de ellos. El ejemplo habrá sido publicado con anterioridad para no perder el tiempo ese día, y centrarse en realizar el trabajo.
(3 sesiones)

14. Patrones Arquitectónicos: sin meternos en tanto detalle como en Sistemas en Internet, el conocimiento de los patrones de alto nivel es fundamental para futuros ingenieros sw:
14.1.: Layers (2 sesiones)
15. PA: MVC (1 sesión)
16. PA: Pipes&Filters, o Broker. (1 sesión)


Según mis cálculos, ahora mismo llevaríamos 21 sesiones + parcial.

17. Pruebas: fundamental que aprendan a hacer pruebas. Habría que utilizar JUnit y mirar Nunit a ver qué tal. Repaso a lo que dice el PU sobre pruebas, y algún patrón de Pruebas (2 sesiones).
18. Gestíón de Calidad de Software: ISO 9000, CMM (2 sesiones)

Y con esto hemos llegado a las 26 sesiones. Aunque no da tiempo a ver la parte de Orientación a Componentes y Frameworks, lo puedo dar como "culturilla general" o enlazar artículos de interés.



1/22/2004

Qué hay de nuevo en UML 2.0 -a partir del libro de Fowler- (I)

Books by Martin Fowler: UML Distilled

Me centro en diferencias entre UML1 y UML2 -alguna cosa se me escapará, claro ;)-

Cuando ya leí la segunda edición, me gustó mucho cómo empezaba el libro: de qué diferentes maneras puede ser utilizado UML:
1. Sketch: comunicación entre profesionales. Nada serio, sencillamente una muy eficaz forma de comunicación.

2. Blueprint: este es el diseño detallado del proceso unificado. Diseño a lo bestia, prácticamente la implementación -aunque algunas clases y/o algoritmos pueden verse añadidos/modificados posteriormente-.

3. Lenguaje de programación: traducción automática de modelo a código, al cuál se le añade después la "chicha".


Dónde usar UML

Fowler comenta, en cada una de los "workflows" principales, qué diagramas son susceptibles de ser utilizados:


  1. Requisitos:

    • Diagrama de casos de uso

    • Diagrama de clases, desde la perspectiva conceptual

    • Diagrama de actividad

    • Diagrama de estado



  2. Diseño:

    • Diagrama de clase, desde perspectiva sw -blueprint o implementación-

    • Diagrama de secuencia

    • Diagrama de paquetes

    • Diagrama de estado

    • Diagrama de despliegue






Propiedades

Son características estructurales de una clase: atributos y asociaciones.

A los atributos se le pueden añadir un {property-string}, que indica propiedades adicionales al atributo, como por ejemplo {readOnly}.

Multiplicidad

UML1 admitía multiplicidad discontínua -p.e. un vehículo puede tener entre 2 y 8 ruedas-. UML2 no lo permite ya.


Dependencias

Existe una serie de palabras clave a utilizar para nombrar las dependencias entre clases:


  1. call

  2. create

  3. derive

  4. instantiate

  5. permit

  6. realize

  7. refine

  8. substitute

  9. trace

  10. use




Restricciones

UML permite, en el diagrama de clases, la indicación de diferentes restricciones. Se puede utilizar lenguaje natural, lenguaje de programación, u OCL (Object Constraint Language) -cálculo de predicados-.


1/19/2004

Generación de Claves Primarias por parte de un Entity Bean en J2EE

TheServerSide: Entity Bean Primary Key Generator



Este artículo plantea la utilización de un Entity Bean que actúe como contador que se vaya incrementando. Como es un EBean, es distribuído, transaccional y persistente.

El bean contiene un atributo, long nextID, que contiene el valor en cada momento. Cuando se crea la clave primaria, el bean inserta en la "tabla" el nombre de la clave y el valor actual.

Este artículo es interesante tanto por lo que cuenta, como por cómo se llega a una solución más adecuada a partir de los comentarios de la gente. Este planteamiento de trabajo es mucho más ágil y lleva a mejores resultados que los típicos artículos -como puede ser éste mismo- sin opción a réplica.

En el artículo de Marinescu, se referencia un artículo de 1999, escrito por Scott Ambler, sobre generación de object identifiers:

El autor comenta que la utilización de claves con significado de negocio es muy peligroso, debido a que los cambios en esas columnas pueden provocar graves problemas en la integridad de la bbdd -p.e. si se cambiara el número de DNI o el Social Security USA-. Por ello, los gestores relacionales ofrecen lo que se denomina "surrogate keys", mediante claves incrementales. Estas claves son valores que se almacenan en tablas ocultas, y que se incrementan cada vez que se añade una fila de una tabla. El cómo se implementan estas tablas -valores globales para todas las tablas, o diferentes para cada una- depende del fabricante.

Además de esta estrategia, existen otras, como UUID (de la Open Software Foundation) y GUID (de Microsoft):
1. UUID: valores de 128 bits a partir de un hash del ID de Ethernet y la fecha sw.
2. GUID: hashes de 128 bits de un ID SW y la fecha.


¿Cuántos valores diferentes se pueden generar por segundo? Pues como los ordenadores actuales suelen representar el tiempo hasta milésimas de segundo, sólo podemos generar como mucho 1000 claves/segundo.

Además, las aplicaciones empresariales suelen ser multibases de datos, cada vendedor tiene una estrategia diferente, se da por hecho que existen comunicaciones constantes con las bases de datos para la obtención de la clave...

Ambler plantea una estrategia nueva denominada HIGH-LOW:

- El identificador se divide en dos partes:
1. Valor HIGH que se obtiene de una fuente definida.
2. Valor LOW que la propia aplicación se asigna a sí misma

- Cada vez que se obtiene un valor HIGH, el LOW se pone a 0.

1/18/2004

ENCAPSULAMIENTO DE INFORMACIÓN SEGÚN FOWLER

IEEE Software: Data Access Routines


Este artículo discute las diferentes posibilidades de "esconder" información cuando implementamos un sistema de información.

Inicialmente recomienda la utilización de atributos públicos en el acceso a valores simples, aunque más por comodidad que por otra cosa. Yo, la verdad, no estoy del todo de acuerdo; aunque evidentemente es un "rollo" tener que estar codificando -aunque los IDEs ayudan- métodos "getter" y "setter", creo que es una buena práctica, y simple.

En el acceso a colecciones de valores, sí tiene mucha razón al explicar que, por ejemplo,

class Album {
private List tracks =new ArrayList();
public List getTracks() {
return tracks;
}
}

, no es una buena manera de encapsular datos, pues el usuario podría añadir y eliminar elementos de la lista sin conocimiento de la estructura.

Fowler establece tres maneras de leer valores, manteniendo la encapsulación:

1. Copiado
Devolver no la referencia, sino una copia.

2. Proxy de protección
Devolver un proxy que impide modificaciones sobre la estructura:
class Album {
private List tracks = new ArrayList();
public List getTracks() {
return Collections.unmodifiableList(tracks);
}
}
(en C++, se consigue con la palabra clave const).

3. Iterador
Un iterador que permite avanzar por la colección, sin tener realmente acceso a ella -aunque sí a los elementos-.


Construcción de Objetos

¿Constructores repletos de argumentos para disponer de objetos bien formados desde el principio, o constructor vacío o casi vacío, más métodos "setter"? Fowler no es definitivo en este apartado, aunque en general prefiere la primera opción. Yo me quedo con la utilización de constructores pequeños con aquellos argumentos que representan atributos inmutables, y la utilización de métodos setter para el resto. Cada cuál...


1/16/2004

MEJORAS QUE TRAJO CONSIGO EL J2SE1.4: WEBSTART (III)

Core Java Technology

Java Webstart

Es un sistema de despliegue de aplicaciones. Permite instalar software con un sólo click en un navegador web.

Está basado en el protocolo JNLP (Java Network & Launching Protocol).

Una aplicación JAWS se descarga, como si fuera un applet, de un servidor web remoto. La diferencia es que la aplicación se "cachea" en local, y se va actualizando mediante el "JAWS runtime system".

Las aplicaciones JAWS se ejecutan dentro de un sandbox, wrapper de seguridad que controla qué recursos del sistema se pueden utilizar y cuáles no. Si la aplicación es "de fiar" -trusted-, se puede traspasar el sandbox. Si la aplicación JAWS puede utilizar el paquete javax.jnlp, éste le ofrece opciones de acceso restringido a los recursos del sistema. P.e. una aplicación JAWS, mediante este paquete, podría grabar un fichero en local, pero SIEMPRE se utilizará una caja de diálogo para que el usuario lo autorice.

1/15/2004

MEJORAS QUE TRAJO CONSIGO EL J2SE1.4: NIO AVANZADO(II)

Java 2 Platform, Standard Edition (J2SE)

Brevemente, comento algunas características avanzadas de NIO:

1. MappedByteBuffers: permite asociar una porción del fichero en un buffer de memoria.
Es importante anotar que sólo carga en memoria bajo demanda -sólo lo que se está leyendo-.

2. E/S No Bloqueante:

ByteBuffer buffer = ByteBuffer.allocate( bufferSize );
Socket newSocket = ss.accept();
newSocket.configureBlocking( false );
SocketChannel sch = socket.getChannel();
buffer.clear();
sch.read( buffer );

La llamada a read devuelve un buffer vacío si no hay nada que leer, en lugar de quedarse esperando hasta que llegue el primer byte.


3. Multiplexación

Para realizar E/S multiplexada, en Java hasta ahora no quedaba más remedio que utilizar polling. Sin embargo, de los viejos tiempos de C nos llega el "selector": es un objeto que monitoriza un conjunto de canales, avisando cuando alguno tiene datos de entrada.
El método Selector.select() se queda bloqueado hasta que alguno de los canales está preparado:
while (true) {
selector.select();
// deal with new input ...
}


Interfaces de Red

La clase NetworkInterface provee acceso a objetos de nivel de sistema operativo que representan las interfaces.




MEJORAS QUE TRAJO CONSIGO EL J2SE1.4: NIO (I)

Java Technology

Ahora, con el J2SE1.5 a punto de caramelo, quizá es buen momento para ver cuáles fueron las mejoras de la versión anterior, que quizá no habéis llegado a utilizar.

Información tomada a partir del JDK1.4 Tutorial de Manning.

Este primer post trata sobre el NIO (New I/O):

El paquete java.nio aporta las siguientes características al preexistente java.io:
1. block-oriented: opera sobre bloques, buscando obtener las mismas prestaciones que otros lenguajes, como C ó C++.
2. Utilización de buffers directos, que no utilizan buffers Java.
3. E/S no bloqueante, simplificando la programación multithreading.

Los elementos fundamentales, que se añaden al concepto anterior de "stream", son los siguientes:
1. Canal -channel-: fuentes y destinos de datos secuenciales, solo que leen los datos en pedazos, no byte a byte. Además, un canal puede ser bidireccional.
2. Buffer: donde se almacenan los trozos de datos. Normalmente son muy grandes.

- Obtención de un canal:
FileInputStream fin = new FileInputStream( infile );
FileChannel inc = fin.getChannel();

- Creación de un buffer:
ByteBuffer buffer = ByteBuffer.allocate( 1024 );

Tb. existen los IntBuffer, ShortBuffer, FloatBuffer, ...

- Lectura:

Se pasa de:
public int read( byte[] b, int off, int len );
, a:
public int read( ByteBuffer dst );

- Escritura:

Se pasa de:
public void write( byte[] b, int off, int len );
, a:
public int write( ByteBuffer src );


Buffers

También se puede utilizar directamente un buffer mediante sus métodos get y put. Es importante entender que cuando se lee de un canal, se escribe en un buffer, y viceversa.


- Lectura y Escritura de otros tipos desde un ByteBuffer:

Aquí hay que recordar el tamaño en bytes de cada tipo: byte, short, float, ...

IMPORTANTE: la ordenación por defecto de un ByteBuffer es BigEndian (MSB antes), pero puede cambiarse mediante el método order(ByteOrder).

Realmente, esta nueva manera de implementar E/S me recuerda a la manera de C con la estructura FILE * y los métodos fopen, ... ¡qué tiempos!

Buffers Directos

En lugar de utilizar buffers intermedios en la JVM para interactuar con el exterior, se utiliza la memoria del entorno de ejecución directamente:

ByteBuffer buffer = ByteBuffer.allocateDirect( 1024 );

No es buena idea utilizarlo siempre, ya que cuesta más recursos. Sólo cuando sea necesario por velocidad.


File Locking

* Tipos de bloqueos:

1. Mandatory lock
Evita que un fichero o la porción de un fichero sea accedido.

2. Advisory lock
Evita que otros "locks" adquieran la misma región.

También hay otra diferenciación:

1. Exclusive
Como los bloqueos del synchronized.

2. Shared
No evitan que otros threads adquieran el lock, sino que evitan que bloqueos exclusivos lo hagan.




FileOutputStream fout = new FileOutputStream( "abc.txt" );
FileChannel fc = fout.getChannel();
FileLock fl = fc.lock( 20, 20, false );
, donde se están bloqueando los bytes 20 a 39 del fichero abc.txt, de manera exclusiva

Todo el fichero:
FileOutputStream fout = new FileOutputStream( "abc.txt" );
FileChannel fc = fout.getChannel();
FileLock fl = fc.lock();




1/14/2004

JAXB: ARQUITECTURA JAVA PARA XML BINDING

The Java(TM) Web Services Tutorial

Aunque es fundamental para comprender el esquema interno de XML, la utilización de JAXP (ya sea DOM o SAX) como parser se hace muy incómodo. Ya desde hace años JDOM viene a solucionar este problema, pero hacía falta una estandarización. JAXB puede resolver este problema.

Esto no quiere decir que DOM o SAX -en particular este último- dejen de utilizarse.

En JAXB tenemos dos pasos:

1. Enlazar (bind) el esquema para el documento XML.
2. Deserializar (unmarshal) el XML a objetos Java.

1. Binding

Primero, es necesario que el sistema comprenda cuál es la estructura del XML, lo cuál se realiza mediante la transformación del XmlSchema del documento a clases e interfaces Java.

JAXB exige que el XML tenga un esquema, y que cumpla el W3C XML Schema Language.

Para ello, se utiliza el Xml Java Compiler (xjc), que se encuentra en \jaxb\bin:

xjc -p <package> <XmlSchema>.xsd -d <directorio destino>

, que genera un conjunto de clases e interfaces, generalmente -por lo que estoy viendo-, para los elementos y los tipos compuestos, además de algún factory. Cada clase define sus métodos getter y setter para cada tipo de elemento y atributo.

2. Unmarshalling

Este paso crea, a partir de un fichero XML, un conjunto de instancias de las clases anteriormente generadas con xjc, en memoria.

Además de eso, el framework JAXB provee:
- javax.xml.bind: marshalling, unmarshalling, validación.
- javax.xml.bind.util: clases de utilidad.
- javax.xml.bind.helper: proveedores de implementación.

Sin meternos en detalles de implementación -para eso está el enlace de arriba-, la idea es que JAXB, al pasarle el nombre del XML, nos devuelve la instancia de la clase "root" del fichero XML -p.e. si el root se llama "Ciudad", la clase será Ciudad-.


Aunque no lo he probado, se supone que se puede realizar este proceso sobre multitud de fuentes: InputStreams, URLs, DOMs, o incluso eventos SAX!


Creación de un Documento

Los pasos son fáciles de imaginar:

1. Binding -como antes-.

2. Creación del Content Tree. Se crea el root del XML.

3. Marshalling.
Transformación a fichero XML.



Anotaciones

Hasta ahora hemos dado por hecho que los tipos de dato que selecciona el compilador xjc son los adecuados para nosotros, pero ¿y si no es así? ¿Y si deseamos que una de las clases generadas se llame de una manera determinada, o que un tipo XML se transforme a otro Java que no es el estándar?

Respuesta: Anotaciones XML. Forma parte del XmlSchema, normalmente arriba del todo, y define qué cambios con respecto a lo definido por defecto tiene que haber.





ALGUNOS PATRONES DE DISEÑO CLÁSICOS

Hillside.net - Design Patterns Book - DP Book

Lo mismo que el post anterior, pero sobre algunos patrones de diseño del GoF:

* Prototype: otra manera de creación de objetos, pero utilizando un prototipo como medio de creación de instancias. La propia clase tiene un método "clone" que implementa un deep copy. La utilidad de Prototype es sobre todo para evitar la proliferación de estructuras paralelas, como ocurre con el Factory Method, y es muy importante para el tema de instancias cargadas dinámicamente: el usuario no se entera de con qué subclase concreta está trabajando. De todas formas, me vendría bien un ejemplo más claro.

* Bridge: desacoplamiento "físico" entre la abstracción y la implementación en dos clases diferentes. Esta idea es la que utilizamos en la implementación de drivers, la que nos permite crear las diferentes capas de una aplicación.

* Decorator: adición dinámica de nuevas responsabilidades a un objeto. Para ello se utiliza una jerarquía de objetos que encapsulan los objetos a modificar, manteniendo su interfaz pero añadiendo -por "arriba" o por "abajo"- su funcionalidad. El planteamiento de este patrón es la modificación de partes visibles o externas del objeto. Para cambiar su comportamiento interno es más útil el patrón Strategy o State.

* Flyweight: objetos muy repetitivos que sólo se almacenan una vez -como los caracteres en un procesador de textos-. La información intrínseca -en este caso el ASCII code- se almacena en el objeto carácter, mientras que la información extrínseca -el contexto del carácter en cada una de sus ocurrencias, como tamaño, fuente, ...- tiene que ser conocida en algún otro sitio. Esto permite que un documento no crezca demasiado, pues el acceso a los caracteres se realiza mediante referencia. Si un documento no cambia mucho de fuente y tamaño, el tratamiento será sencillo.

* Chain of Responsibility: desacoplamiento entre el cliente y el servidor mediante una serie de objetos que se van encargando de partes de la petición, o se van pasando hasta que alguien puede responder adecuadamente (como el DNS). El concepto es el de "burocracia".

* Interpreter: es la creación de un autómata, no es nada más, donde cada clase tiene un método de interpretación con un argumento de contexto -para saber dónde está-, y que puede realizar operaciones de comprobación de la gramática. El árbol en sí suele ser un composite. Es válido para gramáticas sencillas -es lo que utilicé en el SGRT, sin saberlo ;) -.

* Mediator: un "manager" que se encarga de gestionar las interacciones de un conjunto de objetos, para así evitar un excesivo acoplamiento entre sí. Se puede implementar también como un observer, de manera que los objetos envían notificaciones al mediador cuando cambian de estado.

* Memento: patrón que permite capturar y externalizar el estado interno de un objeto, de manera que pueda ser restaurado a ese mismo estado más tarde. Aunque comprendo la idea, un ejemplo de cómo se utiliza exactamente el patrón no vendría mal.

* Strategy: definición de una familia de algoritmos para hacerlos intercambiables.


* Template Method: la superclase deja la implementación de partes del algoritmo como métodos redefinibles por las subclases, de manera que se puedan modificar fácilmente. Sigue el "principio de Hollywood: no nos llames, te llamaremos nosotros", refiriéndose a que sea el padre quien realice las operaciones.

* Visitor: cuando las clases de una jerarquía de clases invocan diferentes métodos dispares entre sí, quizá es mejor crear una jerarquía complementaria para cada tipo de método (métodos parecidos que se invocan desde diferentes subclases), de manera que se estructure todo mejor. El visitor permite que las operaciones relacionadas estén juntas en una misma clase, de manera que las clases de la primera estructura que lo necesiten, accederán como "visitantes" a esas operaciones.

ALGUNOS PATRONES J2EE

Sun Java Center - J2EE Patterns

A continuación pongo pequeños comentarios, basándome en los patrones clásicos de GoF, de los patrones J2EE más conocidos. Doy por hecho que primero os habréis leído la definición de cada patrón.

* Front Controller: ya conocido, es un MVC donde el controller utilizar una serie de dispatchers.

* Composite View Pattern: las JSP están constituidas por conjuntos de JSPs, a través de "includes".

* Session Facade: al igual que el patrón clásico Facade, en este caso es un Session Bean el que ejerce como tal.

* Service Locator: utilización de un singleton que permite encontrar el resto de EJBs. Esto permite no tener que utilizar JNDI constantemente desde el servidor.

* Value Object: en la comunicación c/s, cuando un EJB tiene multitud de propiedades, el acceso constante degrada las prestaciones. Para ello, un EJB devuelve un objeto ValueObject con todas sus propiedades, de manera que el cliente puede procesarlas localmente.

* Business Delegate: llega más allá del SessionFacade, encapsulando todo el tratamiento con los objetos de negocio (es quien interactúa con el cliente y con el service locator, por ejemplo). Se puede aprovechar como proxy para temas de caché, reintentos, etc.

* Data Access: las tareas sobre los datos suelen ser independientes del formato de esos datos. Es básicamente un Adapter.

* View Helper: encapsulamiento de la interacción de la lógica de negocio con la JSP mediante helpers (JavaBeans, por ejemplo), con métodos getters y setters si es posible.

* Dispatcher View: interactúa con el Front Controller para controlar el acceso a la vista JSP. También funciona de manera que la JSP tenga un View Helper. De esa manera se soluciona completamente el problema de acoplamiento entre las dos capas.

* Service To Worker: parecido al Dispatcher View, sólo que mientras que el Dispatcher View no instancia View Helpers, por lo que se entiende que el acceso a los datos externos sólo ocurre cuando ya se ha accedido a la vista, en el caso del Service To Worker el FrontController sí accede a diferentes View Helpers, de manera que el Dispatcher, cuando selecciona la vista, también interactúa con estos ViewHelpers. Básicamente, la diferencia fundamental es que el Dispatcher se preocupa de la elección del conteindo del modelo cuando se crea la vista, mientras que el ServiceToWorker ya crea un modelo intermedio antes.

* Value List Handler: También llamado Page-by-page Iterator. Stateful session bean que accede al DAO para que el cliente no tenga que realizar múltiples peticiones a través de la red. También ejerce de fachada.

* Fast Lane Reader: cuando los datos no cambian mucho y son de sólo lectura, la utilización de EJB Finders es tediosa y mala para las prestaciones del sistema. Este patrón accede directamente a la fuente de datos, e interactúa con el cliente, como si fuera un Entity Bean.

* Transfer Object: a mí me da la sensación de que es un Value Object con otro nombre, centrado en entities.

* Transfer Object Assembler: debido al problema de siempre con las comunicaciones, este patrón lo que hace es devolver al cliente un sólo objeto que sea "resumen" de diversos valores devueltos por session beans, entity beans, DAOs, etc.

* Composite Entity: igual que el Transfer Object, pero centrado en un Entity Bean particular.
En cuanto a la tesis, además de ver el resto de patrones J2EE para considerarlos en el diseño, estaría bien echar un vistazo al documento de diseño de VINI, donde parece que hay buenos diseños que estudiar. En principio yo tiraría por utilizar el patrón Data Access Object, tal y como recomienda J2EE y Fowler, pero habrá que ver.

* Composite Entity: un mapping directo entre el modelo relacional y el objetual (entity beans) no tiene en cuenta que los EBeans son mejores cuando la granularidad es gruesa. El Composite Entity modela un conjunto de objetos interrelacionados en lugar de representarlos independientemente. De esta manera sólo se tiene un Entity Bean, el que se comunica con este patrón, en lugar de considerar cada elemento compuesto como un entity bean.

MÉTODOS DE APRENDIZAJE AUTOMÁTICO PARA MODELADO DE ESTILO MUSICAL (II)

IEEE Computer Society

Uno de los métodos que se utiliza para generación de música por ordenador es el de predicción basado en diccionario. La idea es la de "parsear" una pieza musical ya existente, y proveer una regla de inferencia que permita seleccionar el "mejor" objeto musical que debería aparecer tras uno concreto -o tras un contexto-. Este método exige que el esquema de parsing:
1. intente maximizar el tamaño del diccionario, para obtener una mejor predicción.
2. recoja suficiente evidencia de que el objeto seleccionado es lo suficientemente fiable.

Otro método ya comentado, el de Markov, genera tablas enormes de "posibles futuros estados". El artículo comenta la utilización de "predicción selectiva" para conseguir que este modelo funcione con un tamaño variable de memoria.




El proyecto que se detalla en el artículo utiliza métodos basados en diccionarios para obtener un plan léxico con "motivos" a partir de una pieza musical, y sus probabilidades de predicción asociadas.

Para generar nuevas piezas, estos modelos predictivos navegan a través del árbol de predicción, buscando, a partir de un contexto determinado, si aparece un "motivo" en el árbol.





1/12/2004

TEMARIO DE INGENIERÍA DEL SOFTWARE II. PATRONES DE DISEÑO (II)

Hillside.net - Your Patterns Library

El "core" de la asignatura es la comprensión, conocimiento, y posterior maestría en la utilización adecuada de Patrones de Diseño en la creación de arquitecturas y diseños software acordes a lo requerido por los requisitos de la aplicación a realizar.

En este blog no pretendo explicar en detalle cada uno de los patrones, pues existen libros y URLs que lo hacen mucho mejor de lo que yo sería capaz. Sin embargo, quizá un párrafo resumen de cada patrón, que llegue algo más allá de los resúmenes que aparecen en las cubiertas de los libros, podría resultar útil.´
Además, a mí me vendrá bien para repasar ;)

Los patrones en la asignatura estarán divididos en dos partes:

1. Patrones Arquitectónicos
2. Patrones de Diseño



TEMARIO DE INGENIERÍA DEL SOFTWARE II (I)

Página Principal de Justo N. Hidalgo

Ya es época de plantear las asignaturas del segundo cuatrimestre, sobre todo aquellas que sufren cambios fundamentales con respecto al año pasado. Este es el caso de INgeniería del Software II, ya que la creación de la nueva asignatura optativa de quinto, "Gestión de Proyectos Tecnológicos", me permite "abandonar" un poco la parte más gerencial de la ISW, y centrarme en la parte técnica.

Obviamente, mientras no exista una carrera de Ingeniería del Software, o, al menos un itinerario intensivo, no puedo pretender enseñar TODO lo existente de la ingeniería del sw en dos asignaturas cuatrimestrales.

Ingeniería del Software I es una asignatura bien centrada -aunque todo es mejorable, obviamente-, que introduce qué es la ingeniería, qué es la ingeniería del sw, metodologías, ..., y que permite definir y utilizar el Proceso Unificado.

Mi planteamiento de Ingeniería del Software II es centrarme en un par de temas específicos de la ingeniería del software desde el punto de vista técnico, como es el diseño orientado a objetos mediante la utilización de patrones arquitectónicos y de diseño, y las nuevas tendencias de orientación a componentes, SOA, y creación de frameworks.

El año pasado, esta asignatura fue desde el principio un "cajón de sastre" donde meter muchos conceptos diferentes y no relacionados entre sí. Este año todo está mucho más cohesionado:

1. Introducción a la planificación de proyectos: aunque esto se ve con mucho más detalle en la asignatura optativa mencionada anteriormente, algo tiene que verse en la parte obligatoria de la carrera.
2. Análisis y diseño: arquitectura y patrones. Ya saben lo que es analizar y diseñar. Ahora enseñemos a los alumnos a hacerlo BIEN.
3. Tendencias de ingeniería: lo comentado anteriormente.

Sin embargo, me quedan temas sin tratar que son fundamentales -los temas que aparecen a continuación han sido tomados del IEEE/ACM CCSE (Computing Curriculum: Software Engineering), un intento bastante loable de estandarizar el conocimiento que un alumno de titulación de segundo ciclo debe conocer sobre la Ingeniería del Software. Obviamente, no pretendo que un alumno que no se especializa en este ámbito domine todas las áreas que aparecen en este documento, pero sí que domine las fundamentales, y haya oído hablar de algunas más.


Knowledge Areas:

1. CMP: Computing Essentials: OK.

2. FND: Mathematical & Engineering Fundamentals: OK.

3. PRF: Professional Practice:
Al no disponer de tiempo material en la carrera, se está realizando desde el año pasado un Ciclo de Inteligencia Emocional para Ingenieros en Informática que traten temas tales como la comunicación, asertividad, trabajo en equipo, etc.

4. MAA: Software Modeling & Analysis: OK (Ingeniería del Software I)

5. DES: Software Design: OK, excepto el DES.hci: Human Computer Interface Design.

6. VAV: Software Verification & Validation: OK (un capítulo en ISW I).

7. EVL: Software Evolution: OK, si se concibe desde el punto de vista iterativo del Proceso Unificado.

8. PRO: Software Process: OK.

9. Software Quality: casi nada. Daremos un poco de Métodos Formales al final de ISW II.

10. Software Management: un poco al principio de ISW II, el resto se deja para la asignatura optativa.


Por tanto, nos quedaría por ver:
- Gestión de Versiones: este tema lo podría tratar tangencialmente aprovechando las prácticas que tienen que realizar.
- Calidad de Software: estándares ISO-9000, CMM, ...
UN COMPAÑERO SE NOS UNE

AUDIO E IMAGEN DIGITAL

Juan Franco abre un nuevo blog que versará sobre temas de Audio e Imagen Digital. Por de pronto, acabo de aprender que MP3 NO ES MPEG-3!!!

1/10/2004

¡HA VUELTO GOMAESPUMA!

Gomaespuma.TV

Vale, esta noticia no tiene nada que ver ni con ISW ni con distribuidos... pero es que ¡ha vuelto gomaespuma!

Aquí los tenéis.
MÉTODOS DE APRENDIZAJE AUTOMÁTICO PARA MODELADO DE ESTILO MUSICAL (I)

IEEE Computer Society Digital Library

Llevo meses queriendo leer y pensar acerca de un artículo de la revista "Computer", de la IEEE Computer Society del mes de Octubre pasado:
"Using machine-learning methods for musical style learning", por Dubnov et al.

Se parte de una premisa -aparentemente bien documentada- de que el proceso de composición musical no es, para nada, una actividad aleatoria, sino que, aunque complicado, es formalizable.

Después comenta las dos capas principales de una composición: la "superficie musical", esto es, el pentagrama con sus notas, silencios, etc., y las características estilísticas, como el ritmo, la melodía, la armonía, etc. Gracias a aproximaciones estadísticas se pueden capturar las relaciones redundantes de estos estilos, y generar nuevas instancias de secuencias musicales que las adopten, con lo que serían del estilo de los ejemplos origen.


Con este tipo de herramientas, las aplicaciones que se podrían generar son, por ejemplo, las siguientes:

1. Herramientas de caracterización estilística para musicólogos.
2. Obtención inteligente de información en bases de datos musicales.
3. Generación musical automática para aplicaciones web, de juegos, etc.
4. Improvisación automática con o sin supervisión humana
5. Composición asistida por ordenador.


Ya era posible la generación automática de música a partir de la codificación de un conjunto de reglas musicales en algún tipo de lógica -reglas- o gramática formal, es decir, mediante la construcción de un sistema experto. El problema con esto es la necesidad de una explotación masiva del conocimiento musical -¿es esto un problema?-. El planteamiento de los autores es la utilización de técnicas estadísticas o inducción empírica.


Algunas opciones anteriores fueron:
- Utilización de Cadenas de Markov -que dependen del contexto inmediatamente anterior para generar un nuevo estado-: cuando se han utilizado cadenas de orden bajo, se ha visto que no eran útiles, mientras que a órdenes más altos, se llegaban a cadenas similares al corpus inicial.
- David Cope utiliza generación de gramática + "signatures" -microgestor melódicos de un autor concreto-. Con ambas cosas, consigue nuevas composiciones.

Este artículo busca la obtención automática de estos microgestos: pattern matching, me imagino.


1/09/2004

SPRING FRAMEWORK PARA J2EE (I)

Spring - j2ee Application Framework

Justo antes de navidades, Fabio García, ex-alumno de Nebrija, me recomendó que le echase un vistazo a este framework para J2EE. Que sirva este post para empezar a hacerle caso!

Sus "estatutos" son, principalmente, los siguientes:
- Es mejor programar sobre interfaces que sobre clases. En eso, estoy TOTALMENTE DE ACUERDO, aunque cuesta darse cuenta al principio.
- Se basan en JavaBeans.
- El diseño de la aplicación, mediante técnicas OO, es más importante que la tecnología utilizada, como J2EE. Chapeau!
- Un framework no debería obligarte a capturar tantas excepciones como te obliga Java con sus "checked exceptions".
- Las pruebas son fundamentales, y un framework debería "integrarlas" en el desarrollo habitual -volvemos al test-driven development de hace un par de posts-.


En este artículo del ServerSide se resume el Framework de Spring.

[KITKAT:
En este artículo se habla de POJOs, y no sabía lo que era: el WIKI de Martin Fowler lo explica... y, desgraciadamente, creo que tiene razón!
]

Lo primero de todo es decir qué NO ES Spring, y no tiene:
- No hay paquete de logging. Ya hay buenos en el mercado.
- No hay connection pool.
- No hay O/R mapper: JDO o Hibernate lo hacen genial.


Si ofrece -es decir, compite con otros- en:
- MVC framework -contra Struts, por ejemplo-.
- Contenedor ligero de componentes -ya hablé de ello en el post del Exo Container-.


Resumiendo lo que dice el artículo -¡aviso! artículo denso para los que no estén acostumbrados a vocablos del estilo JNDI, EJB, MVC, IoC, DAO, DBCP, etc.-:

Una característica que me atrae es la de no tener que instrumentalizar tu código con implementación de interfaces o extensión de clases, sino que la metadata y la utilización de una estructura JavaBean es suficiente.

Mejoran el API de JDBC para evitar tareas tediosas como el cierre de ResultSets y Statements, y para crear una estructura de excepciones, más allá del SQLException clásico.


DESARROLLO DE APLICACIONES CONDUCIDAS POR PRUEBAS -TEST-DRIVEN-


TheServerSide.com J2EE Community - Test-Driven Development Series Part I - Overview


Me parece increíble como, desgraciadamente, hay que inventarse nuevos conceptos para que los profesionales apliquen técnicas, flujos o metodologías que existen desde hace años, y que desde hace años también, se sabe que son fundamentales. Es el caso de las pruebas. No es una crítica contra los que inventan estas nuevas metodologías, sino contra todos los que no terminamos de aprender.

El artículo comienza describiendo los problemas de la realización manual de pruebas:

- Es repetitivo: si en un proyecto se realizan pruebas de regresión en cada defecto producido, ¿cuántas veces habremos de realizar una misma prueba? La primera vez es divertido, pero la decimocuarta...
- Da lugar a errores: porque somos humanos y nos cansamos, y no nos fijamos.
- No se prueba todo: las pruebas manuales tienden a ser pruebas de usuario, las cuáles son importantísimas -sobre todo en metodologías centradas en casos de uso-, pero a veces no suficientes, hay que ir más abajo.
- Otros han de creer en tu palabra... o tú has de demostrar que lo que dijiste que funcionaba, lo hacía de verdad.

La automatización de pruebas de manera integrada implica el que los casos de prueba, además de ser programados para poder repetirse una y otra vez -con lo cuál han de ser idempotentes-, han de evolucionar al mismo ritmo que el código probado, lo cuál nos obliga a un segundo esfuerzo que merecerá la pena al final.

Hay dos aproximaciones para este tipo de pruebas: la utilización de scripts que automatizan las pruebas de usuario, y APIs de Pruebas, como JUnit, para incluir en el propio código de la aplicación. Las APIs permiten lo siguiente:
- Seguir la regla TestFirst - DeployLater, seguida por varias metodologías, como ExtremeProgramming o, aunque no se diga explícitamente, el Proceso Unificado -aunque lo de que los casos de prueba deben realizarse antes de la implementación puede dar alguna pista-.
- Realizar pruebas unitarias.
- Realizar pruebas funcionales. Este es el único punto donde los scripts de pruebas de usuario hacen lo mismo, y quizá más rápidamente.

El artículo termina con una lista de las APIs más utilizadas en Java para tests.

¡A probarlo todos! ;)


LA LEY DE DEMETER PARA SISTEMAS ORIENTADOS A OBJETOS

Law of Demeter

De la web: Demetrio es el dios griego de la agricultura: construye el software en pequeños pasos

En este enlace se da una definición un poco más detallada: cada unidad sólo debe tener conocimiento limitado acerca de otras unidades: sólamente unidades "cercanas entre sí" deben conocerse: no hables con extraños.

Realmente, esto ya se ha discutido en clase tanto de Ingeniería del Software como en Distribuidos cuando se habla de obtener una cohesión máxima, pero un acoplamiento mínimo. La Ley de Demeter busca el desacoplamiento entre elementos para obtener una arquitectura en capas que permita su reutilización y su facilidad de cambio y ampliación.

Según los artículos enlazados en la página, esta idea de limitación de conocimiento por parte de elementos -o métodos- da pie a la Programación Orientada a Aspectos -AOP-.

En este otro enlace se define la ley de Demeter para Objetos, que, resumiendo, viene a decir que dentro de un método sólo se pueden enviar mensajes a objetos que sean parámetros del método, a métodos de él mismo, a objetos creados en el método, a un elemento de una colección que sea un atributo del objeto, y a un objeto devuelto por un método del objeto que invoca.

En ningún sitio se dice que esto sea fácil de conseguir, pero sin duda da lugar al desacoplamiento más adecuado para manejarse con sistemas que pueden cambiar constantemente.

Esto me lleva a apuntarme para próximos "posts" una explicación un poco más detallada de la Orientación a Aspectos. El curso pasado trajimos a un experto en AOP que ya explicó los fundamentos, pero vamos a ver si lo entendemos mejor.

1/08/2004

INTRODUCCIÓN A LA PLATAFORMA EXO

EXO

La plataforma EXO es un portal que cumple la JSR 168 -portlets-.


Los elementos fundamentales son:
1. Sistema de gestión de contenidos: a partir del Patrón Composite, y utiliza Programación Orientada a Aspectos (AspectJ). En la documentación comentan que en cuanto se publique la JSR 170 -Content Repository por Java-, la implementarán.

2. Contenedor de Portlets: basado en el PicoContainer, un contenedor de componentes basado en el Patrón de Inversión de Control (IoC, en su versión: Type 3 IOC).

3. Portal: implementa el JSR-127 -JavaServer Faces-, que implementa una arquitectura MVC -es la especificación de lo que antes lideraba Struts-.


Si hubiera tiempo... :( Pero bueno, seguiremos informando!
MÍRALE, ES UN TÉCNICO

TheServerSide.com J2EE Community - He's Just a Techie - Image and Impact of the Software Developer

Aunque sea, leed el chiste inicial... y con eso entenderéis cuán acertado es este artículo, al menos en su planteamiento.

Aunque trata diversos temas, me quiero centrar en dos:
- La necesidad de la certificación como "válvula de escape"
- La integración de los técnicos en la estructura corporativa de la empresa.

El primer punto se lleva discutiendo años en España, y lleva a peleas casi sangrientas entre los que exigen un Colegio nacional que ponga orden a esas "hordas de infieles que nos quitan la mujer, nos roban la comida y nos invaden la casa" -vamos, que nos quitan el trabajo ;)- a los que lo ven de una manera más fría y con algo de autocrítica por parte de los que nos consideramos "ingenieros" más que "informáticos". Ese es un tema en el que hoy no me apetece meterme.
Sin embargo, sí creo que el concepto anglosajón de la acreditación o certificación puede tener un futuro adecuado si conseguimos dividir entre las certificaciones profesionales de empresas del sector -ingenieros MSoft, CCNA de Cisco, BEA Architect- y las otorgadas por asociaciones multinacionales -estoy pensando en el CSDP de IEEE Computer Society para Ingenieros de Software que, por cierto, llevo tiempo planteándome... quizá para cuando acabe la tesis ;) ;) ;) -.


El otro punto es el que los técnicos, o los directores de departamentos de IT o sistemas tengan peso en la toma de decisiones de la empresa. El artículo de Pilgrim lo expresa muy bien. Se empieza con un "qué va a saber el Java-man este del negocio" y se termina dándose cuenta de que este "Java-man" está implementando todo el business process, lo que conlleva la integración de todas las aplicaciones interdepartamentales, y alguna que otra más. ¿De verdad que no sabe del negocio? ¿De verdad que no tiene nada que decir? Me extraña. Aunque lo que quizá ocurra es que no hable directamente de €$ sino de optimización.

Como nota final: en cada momento, en cada situación, hay que contar siempre con los que tienen ALGO QUE DECIR.



CÓMO CONVERTIR JAVA EN LA PLATAFORMA PERFECTA...

In pursuit of perfection

Humphrey Seil pretende identificar en este artículo qué debería ser una plataforma de desarrollo perfecta, y, tras estudiar las mayores debilidades de Java, ver si ésta podría serlo en un futuro cercano.

Su definición de "plataforma tecnológica perfecta" es aquella capaz de ser utilizada por "niños y viejos" para realizar cualquier tipo de aplicación en toda plataforma hw, y que corra en modo nativo o casi.

Primero, comienza dejando claro algo que siempre se ha sufrido: la curva de aprendizaje de Java en entornos empresariales -J2EE- es alta, y la dificultad de algunas de sus funcionalidades, también. No sólo J2EE como tal, sino las herramientas de desarrollo, todavía tienen mucho que currar para llegar la nivel de VStudio. Quizá el WebLogic Workshop esté ahí, tengo que verlo todavía.

Por tanto, las fortalezas que comenta son, por ejemplo:
- soporte de la plataforma
- separación entre especificación de Java y Runtime.
- Comunidad de desarrolladores.
- plataforma estable y madura.
- inserción en la universidad.

Desventajas:
- Comunidad de desarrolladores: demasiado activa.
- Complejidad creciente.


Puntos débiles, desafíos:
- La plataforma por defecto es demasiado pobre: falta Ant, XDoclet, ...
- Evolución darwiniana radical: que sólo el mejor sobreviva, por ejemplo:
- Persistencia: EJB vs. JDO vs. Hibernate.
- IDE: NetBeans vs. Eclipse.
...o que se llegue a un acuerdo!
- Keep It Simple!!!
- Creación de JCP "lite": la Java Community Process es el lugar donde las nuevas especificaciones de Java aparecen. Sin embargo, como con casi cualquier organismo de especificación, leer lo que escriben no es fácil. El autor propone un documento "simple" donde los "usuarios" puedan, al menos, empezar.


De todo lo que el autor propone, no tengo tan claro que la uniformidad lleve a la perfección. Gracias a proyectos "paralelos" a la industria, como Sprite, March, Chorus, ... los sistemas distribuidos siguieron avanzando. El que haya "guerras" acrecienta la iniciativa y la originalidad -siempre visto como competitividad bien entendida-.
La promesa de BEA Workshop de "realizar aplicaciones Java sin programar Java", o una vuelta a esa utopía llamada JavaStudio (sniff!) puede abrir puertas al futuro de Java, pero habrá que irlo viendo.





TRANSACCIONES, ESOS GRANDES DESCONOCIDOS... HASTA AHORA

XA Exposed, Part I


El pasado 5 de Enero (hace dos días) el Spille Blogs publicó la primera parte de su "magnum opus" sobre el Commit en 2 Fases. Me parece interesante comentarlo y resumirlo para "abrir boca" y así­ lo devoráis mejor.

El artí­culo comienza con un recordatorio de la integración de sistemas en los 80 y 90, y del problema principal de la agregación de esas "islas de datos" que poblaban (¿poblaban o pueblan?) el mundo empresarial.

Una primera solución al problema de realización de consultas y actualizaciones sobre datos distribuidos en diferentes bases de datos -consistencia, coherencia, etc.- fue el Commit en 2 Fases -2Phase Commit, 2PC o XA- que introduce el concepto de transacción global, y amplí­a el concepto de transacción obtenido ya hací­a tiempo por las bases de datos relacionales a través de sus caracterí­sticas ACID (Atomicity, Consistency, Isolation, Durability), a bases de datos distribuidas.


Como bien se apunta en el BLOG, las transacciones distribuidas estuvieron olvidadas por el "informático medio" durante algunos años. Pero ahora, con la necesidad de EAI (Enterprise Application Integration)y EII (Enterprise Information Integration) existente, con arquitecturas así­ncronas tipo JMS, se hace vital el contar con un soporte transaccional distribuido... ahora todo el mundo tiene que saber de XA.

El resumen de 2PC lo tomo directamente del blog:
"1. start(Xid) - enlist the resource as part of the transaction
2. end(Xid) - tell the resource that no more transactional work is coming its way
3. prepare(Xid) - prepare for commiting. The resource can respond "OK" or "oh no!". The latter indicates that the whole global transaction should be rolled back.
4. commit(Xid) - Really commit.
", donde Xid es el identificador de la transacción realizada (
XID Javadoc).


Esta frase me hace gracia: "The JTA specification, along with its philosophical parent, the X/Open XA specification[...]". Es como si poco a poco se fueran creando varios tipos de "ingenieros sw": los que leen y entienden y aprecian las especificaciones originales, y los que sólo las aceptan como base de algo más moderno y entendible, y, sobre todo, más práctico. Es como si tuviéramos la frase "La película Matrix, junto con su padre filosófico, La Caverna de Platón[...]" ;)

Un punto bastante conocido de la teoría transaccional local, pero que no deja de ser importante, es que el mayor coste en tiempo de ejecución proviene de lo que en el blog se denomina "disk forcing". Todas las operaciones realizadas han de ser almacenadas en disco para poder ser trazadas ("traceadas"), y de esa manera tengamos tolerancia a fallos (recuperación ante fallos).

Muy interesante, esperaremos a la segunda parte de su trabajo!

1/07/2004

TRANSACCIONES, ESOS GRANDES DESCONOCIDOS... HASTA AHORA

XA Exposed, Part I: "2PC"


El pasado 5 de Enero (hace dos días) el Spille Blogs publicó la primera parte de su "magnum opus" sobre el Commit en 2 Fases. Me parece interesante comentarlo y resumirlo para "abrir boca" y así lo devoréis mejor.

El artículo comienza con un recordatorio de la integración de sistemas en los 80 y 90, y del problema principal de la agregación de esas "islas de datos" que poblaban (¿poblaban o pueblan?) el mundo empresarial.

Una primera solución al problema de realización de consultas y actualizaciones sobre datos distribuidos en diferentes bases de datos -consistencia, coherencia, etc.- fue el Commit en 2 Fases -2Phase Commit, 2PC o XA- que introduce el concepto de transacción global, y amplía el concepto de transacción obtenido ya hacía tiempo por las bases de datos relacionales a través de sus características ACID (Atomicity, Consistency, Isolation, Durability), a bases de datos distribuidas.


Como bien se apunta en el BLOG, las transacciones distribuidas estuvieron olvidadas por el "informático medio" durante algunos años. Pero ahora, con la necesidad de EAI (Enterprise Application Integration)y EII (Enterprise Information Integration) existente, con arquitecturas asíncronas tipo JMS, se hace vital el contar con un soporte transaccional distribuido... ahora todo el mundo tiene que saber de XA.

El resumen de 2PC lo tomo directamente del blog:
"1. start(Xid) - enlist the resource as part of the transaction
2. end(Xid) - tell the resource that no more transactional work is coming its way
3. prepare(Xid) - prepare for commiting. The resource can respond "OK" or "oh no!". The latter indicates that the whole global transaction should be rolled back.
4. commit(Xid) - Really commit.
", donde Xid es el identificador de la transacción realizada (
XID Javadoc).


Esta frase me hace gracia: "The JTA specification, along with its philosophical parent, the X/Open XA specification[...]". Es como si poco a poco se fueran creando varios tipos de "ingenieros sw": los que leen y entienden y aprecian las especificaciones originales, y los que sólo las aceptan como base de algo más moderno y entendible, y, sobre todo, más práctico. Es como si tuviéramos la frase "La película Matrix, junto con su padre filosófico, La Caverna de Platón[...]" ;)

Un punto bastante conocido de la teoría transaccional local, pero que no deja de ser importante, es que el mayor coste en tiempo de ejecución proviene de lo que en el blog se denomina "disk forcing". Todas las operaciones realizadas han de ser almacenadas en disco para poder ser trazadas ("traceadas"), y de esa manera tengamos tolerancia a fallos (recuperación ante fallos).

Muy interesante, esperaremos a la segunda parte de su trabajo!

IDENTIDAD DE OBJETOS: DIFERENCIA ENTRE JDK1.1 Y J2SE

Object Identity and why JDK 1.0.2/1.1 was better than 1.2+

Poco que comentar aquí, pues el artículo es breve y conciso: la identidad de objetos es vital en los sistemas distribuidos, y hay que conocer con detalle cada versión de Java que estemos utilizando. Como comenta el blogger al final del artículo, C# utiliza la misma filosofía que la versión 1.1 de JDK.



PORQUE INNOVAR, POR SÍ SOLO, NO ES SUFICIENTE EN ESTE MUNDO

Fast Company | If He's So Smart...Steve Jobs, Apple, and the Limits of Innovation

"Innovar... eso es lo que hacemos". Y sin embargo, Apple no acaba de conseguir lo que ha deseado durante años: lo que Microsoft, Dell, IBM, ... tienen: ventas.

El artículo llega más lejos: Apple no es como Xerox PARC: Apple inventa cosas que son vendibles al 200%, incluso "molan" -cool-.

Me encanta el resumen del último sidebar:
1. Not All Innovation Is Equal
La innovación puede ser de la que te produce seguidores, y de la que te produce dinero. Uno es Apple, el otro es Dell.
2. Innovate for Cash, Not Cachet
Siempre hay que actuar pensando en la estrategia comercial de la compañía.
3. Don't Hoard Your Goodies
Esta es una idea típica: cada producto tiene su momento, no lo desperdiciemos.
4. Innovation Doesn't Generate Growth. Management Does
Pues eso.
5. Attention Deficit Has No Place Here
Y si se saca un producto innovador, mímalo todo lo que puedas. Cualquier puede copiarlo y dejarte sin porcentaje, a pesar de que hayas sido el inventor.


Por eso creo que es importante que los proyectos sean acometidos por, al menos dos perfiles bien diferenciados: es difícil ser a la vez el inventor "ilusionado e ilusionante" y el gerente práctico que intenta buscar en cada momento la opción más ventajosa de posicionamiento. Quizá no se lleven bien del todo, pero cada uno ha de respetar la otra parte. Creo que muchos tenemos ejemplos que poner, de nuestra propia experiencia profesional.

¿Se enseña esto en los MBAs en Innovación o Emprendedores? Esa es la idea en la que deben apoyarse estos cursos de postgrado: la idea llega, pero hace falta mucho más para ponerla en marcha, y, sobre todo, mantenerla ahí arriba.






ABRACEMOS LA PROGRAMACIÓN EXTREMA... ¿O NO? CONCLUSIONES (y V)

El capítulo 25 trata sobre aquellos proyectos donde, en principio, XP no tiene cabida.

- Cuando el cliente requiere un "libro de especificaciones", perfectamente cerrado antes de comenzar a desarrollar.
- Proveedores acostumbrados a 100h/semana.
- Número de desarrolladores / tamaño del proyecto.
- Tecnología con curva exponencial de coste.
- Construcción de frameworks: en XP se construyen aplicaciones.

Lo cierto es que en la actualidad la mayor parte de los proyectos tendrían posibilidad de utilizar XP según el libro.

ABRACEMOS LA PROGRAMACIÓN EXTREMA... ¿O NO? PR�CTICAS (IV)
- Las prácticas de XP:

1. Planning Game: diálogo entre negocio y técnico. Sin duda uno de los puntos calientes, que no creo que ninguna metodología pueda resolver, pues la gente de negocio no se atendrá a ello casi nunca -y esto no es echarles las culpas, sino que una metodología no puede dictarles cómo comportarse-.

2. Pequeñas releases: poco que decir. El PU, el modelo en espiral de Boehm, ... lo plantean desde siempre. La idea es hacer las releases cortas, consistentes y estables.

3. Metáforas: entiendo que es lo más cercano a una mezcla entre requisitos funcionales y no funcionales, pero estructurados como la arquitectura del sistema.

4. Diseño simple: está en contra del dicho de diseñar con el futuro en mente. No digo que no pueda ser factible en muchas aplicaciones, pero ¿no corremos el riesgo de posicionarnos en el otro extremo?

5. Pruebas: nada que decir: probar, probar, probar.

6. Refactoring: modificación del código, y reestructuración posterior para ver si es posible simplificarlo tras el cambio. No soy un experto en refactorización, apenas he tenido que hacerlo "en serio" un par de veces o tres. Queda pendiente la lectura del libro de Martin Fowler Refactoring: improving the design of existing code.

7. Pair programming: ya lo he comentado en un post anterior: pair programming, sí, pero con "minutos de soledad", como cuando vives en pareja ;)

8. Pertenencia colectiva: me parece perfecto, pero eso obliga a utilizar el estado del arte de las herramientas de gestión de versiones.

9. Integración continua: esto lo he podido comprobar de primera mano en un gran proyecto realizado hace unos años, y, de verdad, ¡funciona! Aunque, tal y como dice Beck, suele obligar a tener una máquina de integración dedicada, debido a la gran cantidad de checkins-checkouts-integraciones que se realizan al día.

10. Semanas de 40 horas: jajajajajajajajajajajajajajajajajajajajajajajajajaja!!!!!! Seamos realistas. Estamos de acuerdo en que una cosa es un "pico", y otra una "meseta"=conjunto de picos continuos. Pero esto no lo va a cambiar XP, me temo.

11. Cliente al lado: me parece una gran idea, que jamás he visto en serio. O el cliente no tiene tiempo para estar "ahí contigo", o tú no lo quieres "ahí contigo".

12. Estándares de codificación: mi duda -y lo es de verdad- es si hay o habrá estándares oficiales y mundialmente reconocidos de codificación para cada lenguaje de programación.


Mi impresión es que es un "mix" de ideas muy bien pensadas y valoradas, junto a una lista de deseos que, de vez en cuando, se cumplen.
ABRACEMOS LA PROGRAMACIÓN EXTREMA... ¿O NO? PRINCIPIOS BÁSICOS (III)

- Retroalimentación rápida: vamos, que reaccionemos cuanto antes.

- Asumir simplicidad: tal y como escribí en mi post anterior, es la parte que menos clara tengo. Quizá soy un ingeniero de sw "de los de antes", que da mucha importancia a la reutilización, y al dejar las cosas preparadas para posibles cambios futuros. Es cierto que esta filosofía conlleva más trabajo, y quizá la mayor parte de los desarrollos no lo requieran, pero también es tarea del ingeniero la de saber cuál es el nivel de complejidad que la herramienta va a requerir.

- Cambio incremental: con esto tengo que estar de acuerdo. Llevo años aplicado el Proceso Unificado, que se basa también en esto.

- Abrazar el cambio: ¿dónde está mi queso? ;)

- Trabajo de calidad: aquí sí creo que el "pair programming" ayuda. Aún dando por hecho que todos queremos hacer un trabajo de calidad -y habría que discutirlo en algunos casos-, desde luego, a nadie le gusta hacer el ridículo delante de un compañero. Esta situación nos obliga a sacar lo mejor de nosotros mismos.
Sin embargo, hay veces que el trabajo de dos en dos dificulta o coharta ese tiempo de reflexión que algunos necesitamos para llegar un poco más lejos.


Otros principios que se citan en el libro son, entre otros:
- Juega para ganar: en la universidad yo siempre decía lo mismo: me presento al examen para sacar un 10. Es la única manera de, salga lo que salga, salir orgulloso, y, desde luego, la única de poder ganar. Kent Beck habla de baloncesto, del equipo de UCLA de John Wooden. Si alguna vez habéis jugado a un deporte de equipo, sabéis lo que significa llegar a los segundos finales y "saber" que ese partido lo ganais, o tirar con tres tíos defendiéndote y "saber" que ese balón entra en el aro sin tener que comprobarlo.

- Aceptación de responsabilidad: bueno, esto no es nuevo, ya existe desde hace años en
el código ético del IEEE.

Sin duda la mayor parte de los profesionales del sw son sinceros, y aceptan sus errores. ¿Pero todo el mundo es así? ¿Cómo minimizar ese número?


ABRACEMOS LA PROGRAMACIÓN EXTREMA... ¿O NO? VALORES (II)

El capítulo 7 se centra en los cuatro Valores fundamentales de XP:
1. Comunicación: totalmente de acuerdo. Soy un defensor de las habilidades emocionales en la formación de un ingeniero o, en este caso, de un desarrollador. No dejan de ser elementos de un equipo, y los equipos funcionan con comunicación.

2. Simplicidad: este valor me da miedo. Aun creyendo en la simplicidad dentro de un diseño, veo dos problemas -sin meternos en tecnicismos-:
- ¿Cómo conseguir que el equipo completo entienda de la misma manera este concepto? Lo que para un es "simplificar", para otro es no comprender la complejidad del sistema.
- La filosofía "lazy" adoptada me puede resultar peligrosa cuando se trata de crear frameworks. Obviamente "simplicidad" no significa lo mismo en este ámbito que en el de una aplicación ad-hoc, pero ¿cómo simplificar en un desarrollo que busca ser lo más generalista posible?

3. Retroalimentación: sin duda. Se basa sobre todo en la realización constante de pruebas -de unidad, funcionales, etc.- y casos de prueba.

4. Coraje: igual que en el segundo valor, ¿qué significa coraje cuando cada componente del equipo lo entiende de diferente forma?

Y el quinto: el respeto. Ahí sí que me han dado. Ojalá existiera ese respeto en todos los proyectos, desde los grandes proyectos de decenas de personas, hasta los que involucran a tres o cuatro estudiantes de 4º de ingeniería informática...



ABRACEMOS LA PROGRAMACIÓN EXTREMA... ¿O NO? INTRODUCCIÓN (I)

Amazon.com: Books: Extreme Programming Explained: Embrace Change

El párrafo inicial sobre la Serie de libros sobre XP de Kent Beck resume la filosofía subyacente de XP: (traduciendo) "Si queremos eliminar confusión del desarrollo de software, debemos estar preparados para abrazar completamente las pocas 'prácticas' que adoptemos. Medidas tomadas a medias dejan problemas sin resolver que serán posteriormente tomadas por otras medidas a medias."

El libro está dividido en dos partes fundamentales: el problema y la solución.

El problema básico en un proyecto sw es, según Beck, el riesgo, y da varios ejemplos de riesgo:
- Fallos de planificación
- Cancelación de proyecto
- Ratio de defectos
- Cambios de procesos de negocio
- Cambios del equipo
- ...

Para cada ejemplo, Beck da la solución que XP tiene para evitar esos riesgos o, al menos, mitigarlos, p.e.:
- Fallos de planificación: metodología iterativa con ciclos cortos.
- Cancelación de proyecto: se pide que el cliente elija la release más pequeña que tenga más sentido.
- Ratio de defectos: tests constantemente.
- Cambios de procesos de negocio: los ciclos son muy cortos, es más difícil que el negocio cambie.
- Cambios del equipo: debido a la metodología, el desarrollador se frustra menos, se aumenta el contacto humano social, etc.
- ...

El capítulo 4 habla de las cuatro variables clásicas en la gestión de proyectos: Coste, Tiempo, Calidad y Alcance. -otro autor que ahora no recuerdo hablaba del dicho de la ingeniería del software: hay cuatro variables en la gestión de proyectos: elige dos ;) -.

ESCRIBIENDO CASOS DE USO EFECTIVOS

Amazon.com: Books: Writing Effective Use Cases


Estoy releyendo el libro de Cockburn, Writing Effective Use Cases.
Algunos puntos importantes del libro son los siguientes:
- El concepto de caso de uso de Cockburn no es exactamente el de UML, aunque en el mismo prólogo del libro se comenta que Jacobson le asegura que la mayor parte de las cosas que enumera Cockburn pueden ser realizadas con UML.
- El caso de uso es un contrato de comportamiento entre un actor y el sistema. Si comprendemos eso todos, mejor nos irá. Por supuesto, aquí no me refiero a los profesionales que llevan tiempo usándolos, sino a los estudiantes que se están pegando con ellos.
- La lista in/out de Rob Thomsett. Cuando hay dudas de si un elemento, tema, etc., pertenece o no al sistema -es decir, si es un requisito de este-, se construye una tabla con tres columnas: tema, in, out. Se discute si el tema está "in" el sistema o "out" del sistema. Muy simple, pero muy adecuado y útil.
- Diferenciación entre "stakeholders" y "actors".
- Niveles de Casos de Uso
- Metas de resumen, nivel nube o cometa: involucra un conjunto de casos de uso de usuario. Aunque con posibilidad de dar lugar a confusión, se puede hablar de casos de uso "estratégicos", o de proceso.
- Metas de usuario, nivel del mar: los más importantes.
- Subfunciones: submarinos

Me parece un gran acierto el cómo se responde a la pregunta: ¿cuál es el nivel adecuado para este caso de uso? Si este caso de uso responde a un "cómo", es de bajo nivel, mientras que si responde a un "por qué", pertenece a niveles más altos. Es como la diferenciación entre interfaz e implementación: uno responde al "qué", el otro al "cómo".

Otro punto muy interesante del libro es el apartado 11.2, "Fuerzas que afectan a los estilos de escritura de casos de uso", tales como, por ejemplo:
- Cultura: siempre lo hemos hecho de otra manera.
- Nivel de comprensión: acerca del dominio, del ciclo de vida, ...
- Necesidades del cliente: es técnico, le vale con una descripción de alto nivel, ...
- Experiencia vs. Formalidad.
- Cobertura
- Consistencia
- Complejidad: deseo de completitud, simplicidad de expresión, etc.
- Conflicto: la ambigüedad ayuda a esconderlo.
- ...