lunes, 1 de agosto de 2011

Modelando la Capa de Acceso a Datos

La finalidad de este pequeño tutorial es mostrar con un pequeño ejemplo, el uso de distintas tecnologías para modelar e implementar una Capa de Acceso a Datos en la plataforma Java. Los frameworks usados serán los siguientes:

- Spring (IoC): Usaremos la Inversión de Control de éste framework general para configurar por inyección de dependencias las clases a utilizar ganando así flexibidad. También usaremos de él, algunas clases de apoyo útiles para los test de JUnit.

- JPA (Java Persistence Api): Estándar para la persistencia de objetos en Java.

- EclipseLink: Motor ORM que usaremos como proveedor JPA. Gracias a Spring podemos reemplazar EclipseLink por otro ORM como Hibernate o OpenJPA fácilmente.

- JUnit: Framework para crear test unitarios.

- DBUnit: Librería de utilidades para escribir test con Base de Datos.

- HSQL-DB: Motor de Base de Datos en memoria, muy útil para los test.

El código fuente se encuentra en un proyecto de Netbeans pero es muy sencillo copiar todas nuestras clases y agregar todas las librerías dependientes del directorio lib en tu IDE favorito.

El Domino
Como modelaremos sólo la capa de acceso a datos no es necesario conocer demasiado del negocio, sólo necesitamos saber que clases del domino serán las persistentes como muestra el siguiente diagrama de clases. Un empleado trabaja para un departamento y puede tener asignadas algunas tareas.



De esta forma tendremos un modelo de datos con cuatro tablas. La tabla EMPLEADO, DEPARTAMENTO, TAREA y EMPLEADO_TAREA para la relación muchos a muchos entre Empleado y Tarea.



La clase Departamento:

@Entity
public class Departamento implements Serializable {

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;

private String nombre;

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

@Override
public String toString() {
return "Departamento{" + "nombre=" + nombre + '}';
}

}


En éste caso el mapeo del nombre de la clase a la tabla se produce de forma implícita porque tienen el mismo nombre (no es case sensitive). Si la clase se llamaria con un nombre distinto al de la tabla, sería necesario hacer el mapeo del nombre explicito con la anotación @Table(name=”nombreTabla”).

Tambien podemos observar que la anotación @Id seguida de @GeneratedValue, especifica que el campo sera la clave primaria y el valor sera autogenerado por la base de datos con la estrategia IDENTITY.

La clase Tarea:

@Entity
public class Tarea implements Serializable {

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;

private String descripcion;

public String getDescripcion() {
return descripcion;
}

public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

}



La clase Empleado:


@Entity
public class Empleado implements Serializable {

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;

private String nombre;

private String apellido;

@Temporal(javax.persistence.TemporalType.DATE)
private Date fechaNac;

private float sueldo;

@ManyToMany
@JoinTable(name="EMPLEADO_TAREA",
joinColumns=@JoinColumn(name="EMPLEADO_ID"),
inverseJoinColumns=@JoinColumn(name="TAREA_ID"))
private Collection tareas;

@ManyToOne
@JoinColumn(name="DEPARTAMENTO_ID")
private Departamento departamento;

public String getApellido() {
return apellido;
}

public void setApellido(String apellido) {
this.apellido = apellido;
}

public Departamento getDepartamento() {
return departamento;
}

public void setDepartamento(Departamento departamento) {
this.departamento = departamento;
}

public Date getFechaNac() {
return fechaNac;
}

public void setFechaNac(Date fechaNac) {
this.fechaNac = fechaNac;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

public float getSueldo() {
return sueldo;
}

public void setSueldo(float sueldo) {
this.sueldo = sueldo;
}

public Collection getTareas() {
return tareas;
}

public void setTareas(Collection tareas) {
this.tareas = tareas;
}

@Override
public String toString() {
return "Empleado{" + "id=" + id + ", nombre=" + nombre + ", apellido="
+ apellido + ", departamento=" + departamento + '}';
}
}


Nótese el mapeo de las colecciones, en especial la colección tareas que representa la relación muchos a muchos con la tabla TAREA mapeada con la tabla intermedia EMPLEADO_TAREA gracias a la anotación @ManyToMany y la anotación @JoinTable

Clases DAO
Este patrón de diseño es usado como Objeto de Acceso a Datos. En nuestro ejemplo definimos su interface para acceder a los datos de la entidad Empleado:


public interface EmpleadoDao {

public Empleado buscarPorId(long id);

public void guardar(Empleado empleado);

public void borrar(Empleado empleado);

public Empleado buscarPorNombre(String nombre);

public Collection listarTodos();

public Collection listarPorDepartamento(Departamento departamento);
}


Y su implementación para JPA:


@Repository
@Transactional
public class EmpleadoDaoJPA implements EmpleadoDao {

@PersistenceContext
private EntityManager em;

@Override
public Empleado buscarPorId(long id) {
return em.find(Empleado.class, id);
}

@Override
public void guardar(Empleado empleado) {
em.persist(empleado);
em.flush();
}

@Override
public void borrar(Empleado empleado) {
em.remove(empleado);
}

@Override
public Empleado buscarPorNombre(String nombre) {
Query query = em.createQuery(
"SELECT e FROM Empleado e WHERE e.nombre=:nom")
.setParameter("nom", nombre);

return (Empleado) query.getSingleResult();
}

@Override
public Collection listarTodos() {
Query query = em.createQuery("SELECT e FROM Empleado e");

return query.getResultList();
}

@Override
public Collection listarPorDepartamento(Departamento departamento) {
Query query = em.createQuery(
"SELECT e FROM Empleado e WHERE e.departamento=:dpto")
.setParameter("dpto", departamento);

return query.getResultList();
}
}


La anotación @Repository es una anotación Spring que indica que es una clase que deberá ser instanciada automáticamente como un Singleton.

La anotación @Transactional le indica a Spring que las operaciónes de datos realizadas por JPA en esa clase serán transaccionales.

La anotación @PersistenceContext inyecta un EntityManager a la variable de clase em para poder acceder a las operaciones que nos expone JPA en su api.

Obsérvese además, las querys creadas en el lenguaje de consultas de JPA JPQL que nos permite consultar manteniendo las características de la orientación a objeto, tales como la herencia.

El archivo persistence.xml




org.eclipse.persistence.jpa.PersistenceProvider
alevouilloz.entity.Empleado
alevouilloz.entity.Departamento
alevouilloz.entity.Tarea




Si buscamos dentro del paquete META-INF nos encontraremos con el archivo persistence.xml. Este archivo es la unidad de persistencia que configura JPA. Como podemos apreciar se indica el proveedor de persistencia que se usará, en nuestro caso EclipseLink. Además se enumeran las clases que deben ser mapeadas por el motor ORM. También es posible configurar aquí la fuente de conexión JDBC que se usará, pero en nuestro ejemplo lo haremos en el contexto de aplicación de Spring.

Importante: Al iniciarse la aplicación, la JVM por defecto buscará éste archivo dentro del paquete META-INF.

El archivo applicationContext.xml:



xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">























class="org.springframework.beans.factory.config.PropertiesFactoryBean">


false























En el paquete resource del directorio test, se encuentra el archivo applicationContext.xml. Este archivo es el contexto de aplicación del framework Spring. En él indicaremos entre otras cosas, la fuente de conexión JDBC con la base de datos y las clases DAO que usaremos.

En nuestro ejemplo, el bean definido con id empleadoDao no es necesario, ya que como vimos anteriormente, nuestra implementación EmpleadoDaoJPA está anotada como @Repository y gracias al component-scan de Spring, ésta es cargada automáticamente y luego es inyectada cuando una clase necesita una instancia de su interface usando la anotación @Autowired. En el caso que la Interface EmpleadoDao tenga varias implementaciones, es útil definir el bean con un id en el contexto para que luego pueda indicarse que implementación DAO será la inyectada.

Preparando la Base de Datos para el Test

Por medio del script ddl.sql del paquete resource que ejecutamos, definimos la creacion de las tablas necesarias.


DROP TABLE EMPLEADO if exists;
DROP TABLE DEPARTAMENTO if exists;
DROP TABLE TAREA if exists;
DROP TABLE EMPLEADO_TAREA if exists;

CREATE TABLE EMPLEADO (
id integer NOT NULL IDENTITY,
nombre varchar(255) NOT NULL,
apellido varchar(255),
sueldo float,
fechaNac Date,
departamento_id integer
);

CREATE TABLE DEPARTAMENTO (
id integer NOT NULL IDENTITY,
nombre varchar(255) NOT NULL
);

CREATE TABLE TAREA (
id integer NOT NULL IDENTITY,
descripcion varchar(255) NOT NULL
);

CREATE TABLE EMPLEADO_TAREA (
id_empleado integer NOT NULL,
id_tarea integer NOT NULL,
);


En el archivo initDataSet.xml definimos el DataSet para que el framework DBUnit cargue algunos datos de prueba en las tablas de la base de datos.

Escribiendo el Test para el DAO: EmpleadoDaoJPA


@ContextConfiguration(locations = {"classpath:resources/applicationContext.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(transactionManager = "transactionManager")
@Transactional
public class EmpleadoDaoJPATest {

@Autowired
private EmpleadoDao empleadoDao;

@Autowired
@Qualifier(value = "HSQLDataSource")
private DataSource datasource;

@Before
public void setUp() throws Exception {
//Creamos las tablas necesarias para el test antes de cargar los datos
SimpleJdbcTemplate temp = new SimpleJdbcTemplate(datasource);
SimpleJdbcTestUtils.executeSqlScript(
temp, new ClassPathResource("resources/ddl.sql"), false);

//Cargamos la BD con los datos iniciales
Connection conn = datasource.getConnection();
IDatabaseConnection dbUnitCon = new DatabaseConnection(conn);
FlatXmlDataSetBuilder dsBuilder = new FlatXmlDataSetBuilder();
IDataSet dataSet = dsBuilder.build(new File("./test/resources/initDataSet.xml"));
try {
DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dataSet);
} finally {
DataSourceUtils.releaseConnection(conn, datasource);
}
}

@Test
public void testBuscarPorId() {
Empleado result = empleadoDao.buscarPorId(1L);
assertNotNull(result);

System.out.println("Empleado encontrado: " + result);
}

...


Es posible cargar el archivo de contexto de Spring por medio de la API, pero en el ejemplo lo hacemos por medio de la anotación @ContextConfiguration donde le indicamos además su ubicación. Si no se indica la ubicación Spring asume que el archivo contexto de aplicación se encuentra en el mismo paquete de la clase de inicio y su nombre es el de la clase concatenando “-config.xml”.

La anotación @RunWith(SpringJUnit4ClassRunner.class) nos da soporte de Spring para JUnit 4.

Podemos ver que la variable de clase empleadoDao al estar anotada como @Autowired será inyectada con la implementación de EmpleadoDao que sea encontrada en el contexto.

De forma similar también será inyectado el DataSource declarado en la variable datasource, pero esta vez indicamos explícitamente con la anotación @Qualifier que sea con el bean llamado “HSQLDataSource”. En el caso de que existan varios beans del mismo tipo y si no usamos @Qualifier, Spring no sabrá que implementación inyectar y nos arrojará una excepción informando éste inconveniente. En nuestro ejemplo no es necesario especificar el DataSource a inyectar ya que en el contexto existe un solo bean declarado, pero queda a modo ilustrativo.

El método setUp() anotado con @Before de JUnit4 se ejecuta al comienzo de cada test y prepara la Base de Datos con la ayuda de algunas clases de utilidades de DBUnit, cargando el dataset con los datos iniciales para las pruebas.

Esto es todo. Espero que les haya sido útil, y ya saben: cualquier duda, comenten.

martes, 10 de mayo de 2011

Las 10 webs de lectura imprescindibles para el Arquitecto de Software

Hacia tiempo que tenía ganas de redactar una entrada con las webs que me vienen ayudando en el día a día laboral. De esta forma, confeccioné un ranking con lo que para mi son los 10 sitios webs imprescindibles para un Arquitecto de Software.


InfoQ es el más completo sitio con artículos y conferencias del mundo del software, dividido en comunidades: Java, .NET, SOA, Arquitecturas, Agile.


Subscripción para recibir tarjetas-artículos sobre nuevas tecnologías de software.


Comunidad con artículos de la plataforma JEE.



Extensa recopilación de articulos sobre la plataforma Java continuamente actualizada.


Web con artículos sobre metodologías ágiles y liderazgo de proyectos.


El clásico de clásicos de Java en el lenguaje de Cervantes con noticias y una gran comunidad comprometida a brindar ayuda en los foros.


Comunidad de Linux en español con novedades sobre tecnologías de desarrollo para éste sistema operativo.


Excelente web con todo los patrones de diseño, anti-patrones y técnicas de refactoring explicados gráficamente y con ejemplos en los lenguajes más usados.


Se autodefine como: "El corazón de la comunidad de desarrolladores Java".


Sitio principal sobre el desarrollo de las apis de Java, implementaciones de JSRs y librerias en incubación.

viernes, 13 de agosto de 2010

Scala - Parte 1: Introducción


Luego de mucho tiempo de no escribir una entrada nueva al blog, me comprometo a redactar una serie de entradas para introducirlos en este lenguaje que me tiene fascinado: Scala

Existen dos motivos que me llevó a tomar ésta desición: 1-No existen muchos artículos en castellano sobre el tema. 2-Lo escribo más para mi que para los lectores a modo de repaso de lo estudiado.

Bien, comencemos.

¿Por donde empezar?
Lo primero que debemos hacer es visitar el sitio oficial de Scala y bajarnos su última versión.

Mientras descargamos les cuento que Scala es un lenguaje multiparadigma que convina la Orientación a Objetos con la Programación Funcional. Si bien se lo puede catalogar como de tipado fuerte, permite la inferencia de tipos. Como lenguaje Orientado a Objetos es tan puro como lo es Smalltalk. Es decir, todo en Scala es un objeto, no existen los tipos nativos. Si escibimos un valor literal como podría ser un entero veremos que éste tiene métodos.
Scala compila a bytecode para la JVM. Aunque existe una versión para .NET. Los astutos ya se habrán imaginado que entonces es requisito tener instalado un JRE para ejecutar una aplicación Scala.
Además de ésto tenemos el potencial de poder reutilizar todas las Apis y librerias de Java importandolas en nuestro código Scala de manera muy sencilla. Importante es aclarar que el paquete java.lang esta implícitamente importado en el lenguaje.

Existen plugins tanto para los ide's Netbeans como para Eclipse con caracteristicas poderosas que van más allá del simple coloreado de sintaxis. Como si fuera poco la distribución de Scala nos trae una propia herramienta REPL que no es otra cosa que un iterprete Scala. Para invocarla y tirar nuestro primer "hola mundo" sólo hace falta ejecutar la orden scala desde el shell de nuestra terminal del S.O. Previamente y una vez descargada la distribución deberemos descomprimirla en algun directorio y establecer el directorio /bin de Scala para que sea accedido desde cualquier path. Para ésto desde Windows editamos la variable de entorno path agregando el directorio /bin de nuestra instalación Scala. Los linuxeros ya sabrán como hacerlo, ni me gasto :P

Hola Mundo Scala!
Para nuestro primer hola mundo accedemos al interprete de scala ejecutando scala.bat desde el directorio /bin de la instalación o simplemente ejecutando scala si tenemos configurado el path en la variable de entorno.
scala> println("Hola Mundo Scala!")
Hola Mundo Scala!
Declarando variables
Si declaramos las variables con la palabra reservada val, la variable puede ser asignada con un valor una sola vez, similar a cuando declaramos con el modificador final de Java.
scala> val msg = "Hola Mundo Scala!"
msg: java.lang.String = Hola Mundo Scala!
scala> println(msg)
Cuando queramos asignarle un nuevo valor el error producido es el siguiente:
scala> msg = "Hola de nuevo"
:5 error: assignment to non-variable
val unnamed4 = {msg = "Hola de nuevo";msg}
Por el contrario si declaramos la variable con la palabra reservada var, ésta podrá reasignarsele valores todas las veces que queramos.
scala> val msg2 = "Hola cambiante"
msg2: java.lang.String = Hola cambiante
scala> msg2 = "Hola de nuevo"
msg2: java.lang.String = Hola de nuevo
scala> println(msg2)
Hola de nuevo
Definiendo métodos
Ahora veamos algunas definiciones de métodos en Scala:
scala> def max(x: Int, y: Int): Int = if (x < y) y else x max: (Int,Int)Int 
Éste método calcula el máximo de los dos valores enteros argumentados. En la definición está indicado explícitamente el tipo de retorno del método. Algunas veces el compilador requiere que especifiquemos el tipo. Si el método es recursivo, por ejemplo, es necesario explicitar el tipo del resultado del método. Pero en el ejemplo anterior es posible obviar el tipo del retorno en la definición porque el compilador es capaz de darse cuenta por inferencia:
scala> def max2(x: Int, y: Int)= if (x < y) y else x max2: (Int,Int)Int
Podemos observar como Scala sabe por inferencia que el retorno es un objeto Int.

En los ejemplos anteriores el cuerpo del método está definido en una sola sentencia. Pero si el método fuera más complejo el cuerpo debería estar enmarcado dentro de un bloque. Al igual que Java y C, Scala usa las llaves { } para limitar los bloques de código:
scala> def max3(x: Int, y: Int) = { if (x < y) y else x } max3: (Int,Int)Int 
Podemos comprobar el resultado del método con:
scala> println(max(5,2))
5
Cuando el método no necesita argumentos es posible definirlo de la siguiente manera:
scala> def saludo = println("Hola, soy un metodo sin argumentos")
saludo: Unit
Además podemos notar que ahora el retorno del compilador indica que el método saludo no tiene parametros y que retorna un Unit. Un Unit viene a representar lo que es un void en Java. Para usarlo podemos escribir:
scala> saludo
Hola, soy un metodo sin argumentos
Bueno, por ahora dejo sólo esto pero espero volver con más en un par de días. Mientras vale seguir experimentando, sobre todo para los que vienen de Java. No sean flojos! :)

viernes, 5 de junio de 2009

LiveCD de Ágil


Un alto porcentaje de la gente que crítica a Ágil no conoce de que va el tema y se resisten a comprender sus ventajas por una multitud de motivos sin sentido y presentando excusas tontas como: “ahh, pero en mis proyectos no se podría aplicar, mis proyectos son especiales”. Pfff…Ahora somos todos especiales!! Otros reconocen ciertas ventajas pero no se animan al cambio debido a que algunas prácticas propuestas exigen cierta destreza.

Sin embargo, podemos realizar pequeños pasos para introducirnos en ágil y asomarnos levemente a ver más o menos de que se trata.

Una forma de asomarse al agilismo puede llegar a ser éste desafío que lo tomé prestado de ésta web chilena y permite que los conservadores y cautelosos puedan experimentar sin “dañar nada de su sistema”, similar a un liveCD :) como se calcula la velocidad de un equipo de desarrollo usando Kanban o mejor dicho algo de Kanban.

1. Listar en post-its las tareas de cada uno para las próximas dos semanas

2. Escribir en cada post-it el tiempo que demoraría en hacerse en condiciones óptimas (sin interrupciones)

3. Frente al escritorio de trabajo, crear un panel (que llamaremos Panel Kanban) con 3 columnas: Ítemes que no han partido, ítemes comenzados e Ítemes finalizados

4. En las dos semanas, mover los post-its de una columna a otra a medida que se progresa

5. Al final de las 2 semanas, sumar los numeros de aquellas tareas que estén en la columna “finalizados


Al dividir la suma de horas “ideales” logradas sobre el total de horas de trabajo de las 2 semanas, habrán medido su velocidad. Ahora tienen una medida de cuanto son capaces de realizar cada 2 semanas, y por ende tienen una guía cerca de cuanto pueden comprometerse para la próxima.


¿Que les parece esta experiencia?

jueves, 30 de abril de 2009

Resultado de la encuesta sobre RIA's


Otra vez una encuesta con tan pocos votantes no es indicador de mucho.
Pero creyendo en una tendencia de 29 votos se destacan las herramientas Flash/Flex, Ajax con librerias Javascript y GWT sobre JavaFX, Silverlight y OpenLaszlo.
No hay mucho para decir. Es lo que esperaba.

viernes, 27 de marzo de 2009

Lean en la producción de Software


Considerado por los expertos como el sistema de fabricación del siglo XXI, Lean Manufacturing es un sistema de gestion de proceso de producción impulsado por Toyota. Su objetivo primordial es implantar la eficacia en todos los procesos del negocio, eliminando las actividades que no aportan valor añadido (denominadas waste), con el fin de generar beneficios tangibles para el cliente final.

Veamos los cinco principios del Lean:
  1. "Understanding Consumer Value" o comprensión de lo que es valor para el cliente; el foco se externaliza desplazándose hasta el consumidor final, que es quien decide lo que es importante y le aporta valor.
  2. "Value Stream Analysis" o estudio de todas las fases del proceso de producción, para determinar las que añaden valor y las que se deben cambiar o eliminar.
  3. "Flow" o unificación de las fases de trabajo en un espacio único.
  4. "Pull" o fase final, en la que el producto no se termina hasta que los clientes no hacen el pedido.
  5. "Perfection" u objetivo final. En la medida en que se eliminan los pasos innecesarios y los flujos de trabajo se adaptan a los pedidos de los clientes, se comprueban las reducciones de costes, esfuerzo y tiempos de trabajo en todas las áreas de la empresa. continuas.

Mejoras Continuas.

El soporte a los principios del Lean Manufacturing, se realiza en tres áreas funcionales básicas: gestión, planificación y ejecución, y reducción de actividades sin valor añadido.

En el área de gestión, esta metodología analiza todos los procesos y prácticas respecto a una serie de indicadores clave, y establece unos criterios fundamentales que sirven de punto de partida para medir las mejoras y progresos durante el proceso de implementación del Lean Manufacturing.

En el área de planificación y ejecución, la fabricación comienza cuando el cliente hace el pedido. Mediante el sistema Kanban de planificación y ejecución, se establece un flujo ordenado y automático de materiales, tanto en lo que se refiere a peticiones y aprovisionamientos como a cantidades, proveedores y lugares de destino, basándose en la demanda actual.

Los proveedores también pueden formar parte del sistema gracias al desarrollo de portales web en los que pueden verificar los niveles de existencias y reponer ellos mismos el material en función de los niveles acordados.

La posibilidad de replicar actividades repetitivas sin necesidad de emitir órdenes de trabajo para cada una de ellas o de establecer líneas de producción independientes para cada trabajo, son otras de las ventajas de este sistema que reduce los tiempos muertos entre cada etapa.

Por último, el sistema Lean incide con especial interés en la reducción de actividades que no aportan valor añadido ”waste”. Básicamente, esta metodología identifica siete tipos de waste:

  • Exceso de producción o producción temprana: producir más de lo que el cliente demanda o hacerlo antes de tiempo. Ocupa trabajo y recursos valiosos que se podrían utilizar en responder a la demanda del cliente.
  • Retrasos: por falta de planificación, de comunicación o de tardanza en el suministro de materiales, herramientas, información…
  • Transportes desde o hacia el lugar del proceso: los materiales se deberían entregar y almacenar en el punto de fabricación, para evitar traslados innecesarios.
  • Inventarios: se deben reducir al mínimo ya que suponen un coste financiero y de almacenamiento.
  • Procesos: dedicar más esfuerzos de los necesarios en revisiones y actualizaciones; la calidad se debe insertar en todas las fases del proceso de forma que cada una de ellas sea correcta desde el principio.
  • Defectos: multiplican los costes y el tiempo de trabajo y consumen una parte importante de los recursos para su solución.
  • Desplazamientos: los empleados deben tener a su disposición todas las herramientas y recursos que vayan a necesitar para evitar desplazamientos innecesarios.
Mejoras Operativas

90% reducción de tiempos en el ciclo de trabajo

50% incremento de la productividad

80% reducción del inventario

80% mejora de la calidad final

75% reducción del espacio utilizado

Para eliminar o reducir el waste, existen una serie de técnicas que abarcan todas las áreas funcionales como: análisis de producción de la empresa, análisis de las actividades de valor, sistema de gestión de calidad total, mantenimiento totalmente productivo, análisis Kaizen de costes y fijación de precios, ingeniería y gestión del cambio y gestión de la documentación.

Como se ha visto, la implantación de la metodología Lean implica el compromiso de toda las áreas funcionales de la empresa y supone un cambio de mentalidad basado en la calidad total. Además ayuda a generar una dinámica propia de mejora, por lo que la adaptación a las caracteristicas de cada caso es indispensable. Por todo ello las ideas centrales del pensamiento Lean no incluyen explicitamente una implementación.

Fuente: Principios Lean para una fabricación eficaz. de IFS España

Ahora bien, En el caso puntual de la industria del software la respuesta rápida al cambio es un requisito indispensable. Cuantas veces hemos oido la frase: "¿Pero como, ahora es tan dificil agregar un botón en el formulario?" Haciendo una analogía apresurada con la ingeniería de puentes, ¿cuántos habitantes de una región(clientes) han pedido modificar el puente ya construido para que en vez de que sea de tipo colgante sea en arco. El cliente ve un proyecto de software como algo blando, fácilmente modificable, y sabemos que no siempre es asi. Pero entonces, ¿qué hacemos? Tratamos de persuadir al cliente que la Ingeniería del Software es tan rígida como la Ingenería Civil o buscamos adaptarnos a la flexibidad requerida.

Teniendo en cuenta lo anterior, la industria del software es el contexto ideal para implementar Lean. Toyota y muchas empresas ajenas a la industria del software tuvieron éxito y mejoraron su productivad con su implementación. Si el software se identifica tanto con los principios del Lean, ¿porqué no implementarlo?

El mismo RUP propone cierta flexibidad al cambio. Eso si, exige abundante documentación para poder llevarla a cabo. En un ciclo productivo Lean se analizaria que documentación es útil en la producción y que documentación es pérdida de tiempo y recursos. Aquí es donde entran las metologías ágiles. Si, es verdad, al igual que las religiones, todas se parecen. Pero cada una busca su implementación de la filosofía Lean para maximizar la producción. Noten que ahora hice referencia a Lean como una filosofía y no como una metología. Si se quiere se puede ver a Lean como una especificación de principios y a cada metodología agil como una implementación de Lean que intenta conducir un proyecto por el camino del éxito.

Sin dejar la objetividad de un ideal de fábrica de software productiva y metodológica, quiero abrir el debate y leer sus opiniones.

jueves, 19 de marzo de 2009

FileDrop: Drag & Drop de archivos fácil en Java

Así es como se presenta éste api, sencillo, de dominio público y muy, pero muy útil.

FileDrop no tiene licencia, es de dominio público y tal como se aclara en su web, podemos hacer lo que se nos antoje con el. El zip de descarga contiene además del jar, el archivo FileDrop.java con toda la funcionalidad embebida para que podamos incluírlo en la ruta de paquetes de alguna aplicación propia sin tener dependencias de jar externos.

Para ver cuan fácil es usar el Drag & Drop de archivos en Java con FileDrop, vamos a ir más alla del ejemplo de su web y vamos a hacer un componente que muestre imágenes y acepte archivos de imagenes "dragueados" desde el sistema. Algo similiar se podría hacer con visores PDF, reproductores multimedia, o cualquier funcionalidad relacionada al drag & drop de archivos integrada a una aplicación Java standalone. En éste link puse el código fuente del ejemplo.

Primero implementmos el visor de imágenes como un componente. También es posible implementar el visor de imagenes extendiendo de JPanel, Canvas o un JLabel en lugar de un JComponent.
Luego es necesario definir una clase que maneje la transferencia del objeto a draguear. Para nuestro propositito sólo se soportará transferencia de objetos java.awt.Image.

Y Finalmente, hacemos uso de FileDrop en el método que instancia nuestro visor de imágenes.

Como se aprecia en el ejemplo, en el método FileDroped del listener se espera un array de objetos File, ésto permite manejar múltiples "dropeos" de archivos. Una aplicación útil podría ser la típica lista de reproducción que al dropear múltiples archivos .mp3 en el contenedor Swing reproduzca el elemento [0] y encole el resto en la lista.

Espero que les sirva y cualquier duda, comenten.