sw
Singleton Pattern — Patrones de diseño
Estamos abordando ahora un tercer patrón creacional, o de creación. El Singleton Pattern, a diferencia de los dos que ya hemos visto y los que veremos, no se encarga de la creación de objetos en sí, sino que se enfoca en la restricción en la creación de un objeto. Este patrón es ampliamente utilizado por muchos frameworks, y también es uno de los más fáciles de aprender y utilizar.
Siempre que se crea un objeto nuevo (en Java con la palabra reservada new) se invoca al constructor del objeto para que cree una instancia. Por lo general los constructores son públicos. El singleton lo que hace es convertir al constructor en privado, de manera que nadie lo pueda instanciar. Entonces, si el constructor es privado, ¿cómo se instancia el objeto? Pues a través de un método público y estático de la clase. En este método se revisa si el el objeto ha sido instanciado antes. Si no ha sido instanciado, llama al constructor y guarda el objeto creado en una variable estática del objeto. Si el objeto ya fue instanciado anteriormente, lo que hace este método es devolver la referencia al estado creado anteriormente.
En los patrones anteriores utilizamos un Traductor. Imaginemos que el traductor carga a memoria no sólo números, pero también diez mil palabras obtenidas a través de un archivo de texto o un web service. Cada vez que este objeto se cree utilizará mucho espacio en memoria. Además, si se usa un web services para cargarlo, cada carga consume muchos recursos de red y tarda mucho en terminarse de construir.
Traductor estará disponible para toda la aplicación, y en cualquier lado que se despliegue un texto será invocado. No tendría mucho sentido construir un Traductor cada vez que lo querramos utilizar. Lo más sano sería utilizar un sólo Traductor para toda la aplicación. ¿Cómo lograrlo? A través de un Singleton. Omitiendo la lógica del objeto, el código que se debería usar quedaría algo así:
public class Traductor{ private static boolean instanciated=false; private static Traductor traductorInstance; /** *Notar que el constructor es privado! */ private Traductor(){ //cargar un diccionario a memoria a través de un WebService. } public static Traductor getTraductor(){ if (! Traductor.instanciated){ Traductor.traductorInstance= new Traductor(); Traductor.instanciated=true; } return Traductor.traductorInstance; } public String translate(String toTranslate){ //mucho código bonito va aquí } }
En cualquier lugar de la aplicacion que se quiera utilizar hacer una traducción se hace esto:
Traductor.getTraductor().translate("unaPalabra");
¿Qué logramos con esto? Que alguien que utilice nuestro código no pueda hacer esto
Traductor t = new Traductor();
Es un gran beneficio porque podemos controlar mejor, cambiarla en el futuro, optimizarla, a Traductor. Evita malos usos de la clase y se nos asegura que a lo más hay una instancia del objeto en toda la aplicación.
Las cosas no son tan fáciles como parecen. Hay muchas maneras de crear los Singletons. En este ejemplo utilizamos un booleano estático, pero no siempre es necesario, pudimos haber inicializado traductorInstance como null, y en vez de verificar la variable booleana, verificar si la instancia es null o no.
public class Traductor{ private static Traductor traductorInstance=null; /** *Notar que el constructor es privado! */ private Traductor(){ //cargar un diccionario a memoria a través de un WebService. } public static Traductor getTraductor(){ if (! Traductor.INSTANCE==null){ Traductor.traductorInstance= new Traductor(); } return Traductor.traductorInstance; } public String translate(String toTranslate){ //mucho código bonito va aquí } }
O, para hacer las cosas más fáciles (que no siempre conviene, jeje) podríamos evitar la evaluación en getTraductor y crear el objeto cuando lo declaramos:
public class Traductor{ private static Traductor traductorInstance=new Traductor(); /** *Notar que el constructor es privado! */ private Traductor(){ //cargar un diccionario a memoria a través de un WebService. } public static Traductor getTraductor(){ return Traductor.traductorInstance; } public String translate(String toTranslate){ //mucho código bonito va aquí } }
Fácil ¿no? Mmm, pues se puede complicar. En Java por ejemplo, todavía se podría obtener una copia de traductor así:
Traductor t = (Traductor)Traductor.getTraductor().clone();
Para evitar esto tendríamos que añadir las siguietnes líneas a nuestra clase Traductor
public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); }
También alguien podría extender la clase y volver público el constructor. Para evitar esto sería buena idea declarar nuestra clase como final.
Hay que tener especial cuidado cuando el Singleton se utiliza en un ambiete multi hilos, porque puede crear problemas si no se implementa de la manera adecuada. En Java es posible que tengamos que meter algún synchronized por ahí para evitar problemas.
Concluyendo, la idea central del Singleton es esa: asegurar de que exista tan solo una instancia del objeto en toda la aplicación. Hay muchas maneras de implementar un Singleton (aquí solo vimos algunas). Es un patrón muy aplicado en Java, aunque, como todos los patrones, se puede implementar en cualquier lenguaje orientado a objetos. También se pueden hacer cosas interesantes uniendo el Singleton con otros patrones creacionales (recordemos que el singleton no busca crear, sino que limitar la creación).
Abstract Factory Pattern - Patrones
Hace una semana hablamos del Factory Pattern, que realmente se llama Factory Method Pattern, porque como vimos se trata de reducir la desición de la creación de una instancia a un método, pero que por gusto mío lo pusimos en una clase Factory con un método abstracto. Ahora vamos a hablar del Abstract Factory Pattern, que va un paso más alla: el Abstract Factory Method agrupa varios Factory Methods.
Básicamente lo que hace el este patrón es unir varios Factory Methods, delegando la responsabilidad total sobre qué instancias crear a partir de datos comunes. La semana pasada hicimos un pequeño traductor, que al recibir un número desplegaba su valor en español, inglés o alemán. Para mostrar el concepto del Abstract Factory vamos a extender el ejemplo.
Primero vamos hacer un sencillo reloj que nos muestra la hora actual. Como sabemos, la hora puede ser desplegada en formato de 24Hrs o puede ser desplegada en formato AM/PM. Recordando que es a manera de ejemplo, vamos a utilizar la clase Date de una manera que no se debe, y probablemente el reloj lo haríamos de una manera más sencilla, pero para nuestro ejemplo queda perfecta su uso. Como en el caso del diccionario, haremos una clase abstracta de Reloj y dos implementaciones para cada una de los formatos, y una clase que contenga el método del Factory Method. La cosa quedaría algo así:
La clase Reloj:
public abstract class Reloj { abstract String dameLaHora(); }
La clase que se da la hora en formato AM/PM:
public class RelojAmPm extends Reloj{ public RelojAmPm(){ } public String dameLaHora() { Date d = new Date(); int hora = d.getHours(); int minutos = d.getMinutes(); int segundos = d.getSeconds(); String tr; if (hora<=12){ tr="Son las "+hora+":"+minutos+":"+segundos+" AM"; } else { tr="Son las "+(hora-12)+":"+minutos+":"+segundos+" PM"; } return tr; } }
La que nos da la hora en formato de 24 horas:
public class Reloj24Hrs extends Reloj { public String dameLaHora() { Date d = new Date(); int hora = d.getHours(); int minutos = d.getMinutes(); int segundos = d.getSeconds(); String tr; tr = "Son las " + hora + ":" + minutos + ":" + segundos + " "; return tr; } }
Nuestra clase que contiene la el método que elije las instancias. A diferencia del post anterior, ahora el parámetro que recibe el método es un entero, que acepta los enteros especificados como constantes estáticas en la clase. Esto se usa mucho para no estar adivinando los paráemetros que acepta el método:
public class RelojFactory { public static final int RELOJ_AM_PM=0; public static final int RELOJ_24_HRS=1; public RelojFactory(){ } public static Reloj createReloj(int tipoDeReloj){ if (tipoDeReloj==RelojFactory.RELOJ_24_HRS){ return new Reloj24Hrs(); } if (tipoDeReloj==RelojFactory.RELOJ_AM_PM){ return new RelojAmPm(); } return null; } }
Y finalmente la clase cliente, que será la usuario final:
public class MainClient { public static void main(String[] args) { Reloj r = RelojFactory.createReloj(RelojFactory.RELOJ_24_HRS); System.out.println(r.dameLaHora()); } }
Hasta aquí tenemos dos fábricas: una de palabras, y la que acabamos de hacer que nos da la hora. En un proyecto cualquiera se nos pide hacer un sistema que despliegue la hora y los números de la manera en la que se expresan en cada país (una implementación súper elemental de Locale de Java). Vamos con dos ejemplos prácticos. En Estados Unidos se despliegan los números en inglés, y la hora en formato AM/PM; mientras que en Guatemala se dicen los números en español y la hora en formato de 24 Horas.
Ahora vamos a crear una Abstract Factory, que le pondremos Locale.
public abstract class AbstractLocaleFactory { public static final String US="ESTADOS_UNIDOS"; public static final String GT="GUATEMALA"; String pais; public abstract Traductor createTraductor(); public abstract Reloj createReloj(); public String getPais(){ return this.pais; } public void setPais(String pais){ this.pais = pais; } }
Como ven esta fabrica tiene un par de métodos que devuelven un Reloj y un Traductor. Noten que Reloj y Traductor son a su vez clases abstractas.
Ahora implementamos nuestra clase LocaleGuatemalaFactory, que va así:
public class LocaleGuatemalaFactory extends AbstractLocaleFactory{ public LocaleGuatemalaFactory(){ this.pais=this.GT; } public Traductor createTraductor() { return TraductorFactory.createTraductor("espanol"); } public Reloj createReloj() { return RelojFactory.createReloj(RelojFactory.RELOJ_24_HRS); } }
Y la respectiva para Estados Unidos:
public class LocaleEstadosUnidosFactory extends AbstractLocaleFactory{ public LocaleEstadosUnidosFactory(){ this.pais=AbstractLocaleFactory.US; } public Traductor createTraductor() { return TraductorFactory.createTraductor("ingles"); } public Reloj createReloj() { return RelojFactory.createReloj(RelojFactory.RELOJ_AM_PM); } }
Ahora en el cliente, si queremos las cosas como se verían en Guatemala, simplemente hacemos esto.
public class MainClient { public static void main(String[] args) { Reloj reloj = null; Traductor traductor = null; AbstractLocaleFactory localeFactory = new LocaleGuatemalaFactory(); reloj = localeFactory.createReloj(); traductor = localeFactory.createTraductor(); System.out.println("--------"); System.out.println("1="+traductor.traducirNumero(1)); System.out.println(reloj.dameLaHora()); } }
El resultado de correr el codigo anterior es:
1=uno
Son las 21:50:17
Ahora si cambiamos la linea
AbstractLocaleFactory localeFactory = new LocaleGuatemalaFactory();
Por esta
AbstractLocaleFactory localeFactory = new LocaleEstadosUnidosFactory();
Tendremos como resultado:
1=one
9:52:56 PM
Aquí es un ejemplo sencillo. Pero imaginen quedemos hacer un Locale para cada país, y en el locale tener más cosas como: la nomenclatura de moneda, el sistema de numeración, el manejo de fechas, kilómetros o millas, etc. Con el Abstract Factory Pattern es muy sencillo agregar cada nuevo pais, o cada nueva característica del Locale. Pero sobre todo el código es MUY legible y FACILMENTE extensible. Alguien que nunca ha visto estas piezas de código puede entender como hacer un nuevo país.
Entonces, el Abstract Factory Pattern puede ayudarnos mucho en casos donde hemos de manejar familias de objetos. Al inicio no siempre es obvia su implementación, pero siempre está el recurso de del refactoring, en el cual salen nuevas maneras sencillas de hacer las cosas. Este, como muchos patrones, requieren escribir un poco más de código al principio, pero nos reducen el esfuerzo a largo plazo porque hay menos código repetido.
Aquí el código de este patrón.
Factory Pattern - Patrones
Los patrones creacionales (creational patterns) son aquellos que tienen que ver con la creación (duh!) de objetos. La razón de ser de estos patrones es para facilitar, ordenar, o ayudar en la creación de objetos. Dependiendo del lenguage de programación que estemos utilizando, generalmente crearemos un objeto así: Objeto o = new Objeto(). Pues bueno, en los patrones creacionales las cosas cambian un poquito, y probablemente ahora crearemos un objeto así Objeto o = ObjectoFactory.getInstance(”x”);, o algo parecido.
Hoy hablaremos del más famoso de los patrones de creación: en Factory Pattern (Patrón de fábrica). Utilizaremos los nombres ingleses porque creo que son más claros que las traducciones que se podrían hacer. Además, en software de todos lados, es más estandar utilizar el inglés en ciertas nomenclaturas para facilitar que otros lean nuestro código. Buhh, alguien alega por ahí, pero reconzcámoslo: programamos en inglés.
Como todo se entiende mejor con un ejemplo -al menos eso creo yo-, comenzaremos con uno. Supongamos se nos encarga crear un traductor que devuelva los números del cero al diez en tres idiomas: inglés, español, y alemán. Existen muchísimas maneras de hacer esto. Al final, se desea un método que reciba un entero entre 0 y 10 y que devuelva una cadena con el nombre de dicho número en el idioma que se esté trabajando.
Una manera de entrarle al problema podría ser algo así:
public class MainClient { public MainClient(){ } public traducirNumero(String idioma, int numero){ if (idioma.equals("español")){ switch (numero){ case 0: return "uno"; case 1: return "dos"; .... } } if (idioma.equals("english")){ switch (numero){ case 0: return "one"; case 1: return "two"; .... } } if (idioma.equals("deutsch")){ switch (numero){ case 0: return "eins"; case 1: return "zwei"; .... } } }//traducirNumero public static void main(String args[]){ MainClient mc = new MainClient(); System.out.println(mc.traducirNumero("espanol",1)); } }//de la clase
El resultado del código anterior, como ya sabrán, es uno.
Esta solución parece funcionar, y de hecho lo hace. Pero imaginemos que ahora nos dicen que desean la traducción de todos los números? Sin duda el código comenzará a crecer. Y claro, ahora tendremos que agregar código de lógica para cada idioma para escribir números como 752, 1233, etc.
Como nos gusta hacer gala de nuestro enfoque a objetos, los primero que se nos ocurre es una herencia. Definiremos una clase abstracta Traductor, y para cada idioma haremos una subclase de Traductor.
public abstract class Traductor{ public abstract String traducirNumero(int numero); }
Y ahora comienza la magia a aparecer. Vamos a crear una clase especializada para diccionario, que se encargará de traducir los números. Tendremos una clase especializada para traducir los números al español, que iría algo así:
public class TraductorEspanol extends Traductor { public TraductorEspanol(){ super(); ... } public String traducirNumero(int numero){ switch(numero){ case 1: return "uno"; case 2: return "dos"; ... } } }
La clase para el inglés iría
public class TraductorIngles extends Traductor { public TraductorIngles(){ super(); ... } public String traducirNumero(int numero){ switch(numero){ case 1: return "one"; case 2: return "two"; ... } } }
Y la del alemán no la ponemos, porque ya captaron la idea. Ahora, en el momento de querer utilizar un diccionario, se llamaría algo así
Traductor t = new TraductorEspanol(); t.traducirNumero(1);
Entonces, la clase MainClient cambiaría un poco y quedaría así:
public class MainClient { public String traducirNumero(int numero){ Traductor traductor = null; if (idioma.equals("español")){ traductor = new TraductorEspanol(); } if (idioma.equals("ingles")){ traductor = new TraductorIngles(); } if (idioma.equals("aleman")){ traductor = new TraductorAleman(); } String toReturn traductor.traducirNumero(numero); return toReturn; }//traducirNumero public static void main(String args[]){ MainClient mc = new MainClient(); System.out.println(mc.traducirNumero("espanol",1)); } }//de la clase
Qué hemos ganado? Primero, nuestro código es mucho más legible. Segundo es bastante más escalable. Podemos agregar el traductor para el francés muy fácilmente. Tercero hemos escondido la manera en la que traducimos a Tradúceme. Por ejemplo, puede ser que las traducciones a chino las vayamos a traer a un web Service. En ese caso TraductorChino se encargaría de hacer todo el ajetreo de conectarse a internet y buscar el web services, pero los demás ni se enteran.
Pero el Factory Pattern no ha aperecido, Es tiempo de irlo a llamar. Bueno, Traduceme está haciendo algo que no le compete: está eligiendo la instancia de Traductor que quiere usar. Imaginen que se usa el traductor en 100 lugares, entonces en cien lugares se tiene que buscar qué clase de Traductor vamos a instanciar. El patrón de fábrica -factory pattern- nos esconde esa lógica. Vamos a agregar ahora nuestra fábrica de traductores.
public class TraductorFactory { public TraductorFactory(){ } public static Traductor createTraductor(int numero){ Traductor traductor = null; if (idioma=="español"){ traductor = new TraductorEspanol(); } if (idioma=="english"){ traductor = new TraductorIngles(); } if (idioma=="deutsch"){ traductor = new TraductorAleman(); } return traductor; } }//de la clase
¿Qué hace TraductorFactory? Simplemente elige, en base a los argumentos dados - en este caso el idioma- qué clase de traductor se instanciará. Traduceme de nuevo cambia y quedaría así:
public class MainClient { String idioma; public static void main(Strin []args){ Traductor traductor = TraductorFactory.createTraductor("espanol"); System.out.println( traductor.traducirNumero(1) ); }//main }//de la clase
MainClient se ha visto dramáticamente reducido, y su código es muy fácil de leer. Quien quiera usar un traductor simplemente hará llamar a Traduceme. Traduceme sabe el idioma que eligieron, pero no sabe que subclase de Traductor instanciar, pero sabiendo el idioma TraductorFactory sabe exáctamente qué instancia de Traductor crear. Si la aplicación desea cambiar de idioma simplemente le envía otro parámetro a Traduceme y listo. También agregar idiomas es más manejable que antes.
El Factory Pattern esconde al usuario final dle código la desición de qué sublclase instanciar, y promueve el encapsulamiento de las partes más variables del sistema. En términos generales, una fábrica abstracta consiste de las siguientes partes:
- Un cliente, que es el que llama a la fábrica (en nuestro caso MainClient).
- Una fábrica, que decidé la clase a instanciar (TraductorFactory).
- Un prodicto, lo que la fábrica devuelve (para nosotros las instancias de Traductor).
Pueden bajar los fuentes de este ejemplo aqui.
Oracle compra Sun…
Estamos en abril, pero la noticia del año en en el mundo tecnológico acaba de suceder: Oracle comró Sun. El precio por acción fue de $9.50, totalizando la pequeña cifra de 7.2 millones de dólares. Muchas cosas han aparecido y mucho se ha comentado en blogs, foros y cículos tecnológicos en general. Para muchos, como yo, que desarrollamos mucho en Java la pregunta obligada es ¿qué va a pasar con Java? Pero lejos de ser esta la única pregunta a responder, hay una lista que surge por ahí.
- ¿Qué va a pasar con MySQL? El negocio principal de Oracle han sido las bases de datos, y lo seguirá siendo. MySQL probablemente ha sido su mayor competidor. ¿Lo dejarán vivir? Yo creo que sí, que volverán a MySQL parte de su negocio.
- ¿Qué va a pasar con Netbeans? De cuando en vez visité el sitio de JDeveloper, lo bajaba y lo probaba. Sin duda un IDE bonito y completo. Lo que nunca encontré es alguien que lo usara y siempre me causó duda el que Oracle lo siguiera desarrollando. ¿Van a unir NetBeans y JDeveloper? ¿Adiós Netbeans? ¿Seguirán caminos separados?
- ¿Qué va a pasar con Solaris? Creo que vamos a comenzar a escuchar más de Solaris. Aparecerán versiones de Oracle (y MySQL) áltamente optimizadas para Solaris y cosas parecidas.
- ¿Qué va a pasar con OpenOffice? Mmmm, no sé. ¿Le interesará a Oracle?
- ¿Que pasará con VirtualBox?
- ¿Que pasará con Glassfish y parecidos? Es probable que Oracle intente unificar todo el middleware en el suyo propio. JBoss debe estar ya craneando qué camino tomará para que no se lo tomen.
Un tema que ha sucitado mucha incógnita es ¿qué pasará con el hardware de Sun? ¿Se dedicará Oracle a vender servers? Oracle ha tenido mucho acercamiento con Dell y especialmente HP para vender su base de datos en servidores de dichas compañías. ¿Querrán hacer compromisos éstas con su nuevo competidor?
En fin, la lista de preguntas es larguísima. Desde las certificaciones hasta el JCP (Java Community Process). Sólo el tiempo nos dirá. IBM hizo una propuesta de comprar son a inicios de mes … ¿se estarán mordiendo los dientes? Lo que sí sé, es que tendremos Java por mucho tiempo más.
Patrones de Diseño
Patrones de Diseño (Design Patterns)
A partir de ahora comenzaremos todos los martes con un nuevo patrón de diseño. ¿Qué son los patrones de diseño? Bueno, durante el tiempo que el paradigma de programación orientado a objetos ha estado por ahí, se han aprendido muchas cosas. Muchas de las lecciones aprendidas se han tratado de conceptualizar. El primer esfuerzo se le debe a la conocida como Gang Of Four (GoF), quienes fueron los primeros en acuñar el término.
Los patrones de diseño son un conjunto de estrategias, o buenas prácticas, que pueden facilitar el trabajo en muchas situaciones a la hora de realizar una aplicación orientada a objetos (según la RAE utilizo de mala manera el término “aplicación”). Los patrones de diseño son relativamente fáciles de comprender, no son nada del otro mundo. Lo que a veces se hace complejo es utilizarlos. Por ello hay que conocerlos bien, especialmente los más importantes, porque realmente facilitan el trabajo, y sobre todo, hacen el código más legible.
Los patrones de diseño son independientes del lenguaje en el que utilicen (siempre y cuando el lenguaje sea orientado a objetos!). Generalmente se presentan como diagramas de UML. Una lista completa la pueden encontrar en wikipedia.
Según su enfoque los patrones de diseño se agrupan en:
- Patrones de creación (o creacionales).
- Patrones estructurales.
- Patrones de comportamiento.
- Patrones de sistema.
Que quiero de mi capa de presentación?
En mi post anterior comenté la necesidad de buscar y aprender una nueva tencología de presentación. Como lo comenté en otras ocasiones, esta tecnología ha de ser web. Ya comencé mi búsqueda y se puede decir que ya he decidido (pronto lo sabrán).
Algunas características importantes que pido de la tecnología de presentación:
- Java. Por ahora me quedo con Java, con sus pros y sus contras.
- Web.
- Open, libre, gratis.
- Que las cosas se vean bonitas, out-of-the-box. No soy bueno con el diseño gráfico, y por ahora no tengo interés en enfocarme en él. Por ello es importante que la tecnología que escoja haga cosas fancy que se vean bonitas.
- Que sea sencillo generar código con él.
- La curva de aprendizaje no ha de ser muy elevada.
- Decente integración con Netbeans y/o eclipse.
Ahora, vamos con cosas puntuales.
- Binding inteligente. Mejor si la unión entre el GUI y el resto pueda hacerse con Beans.
- Tablas inteligentes. TableModel, o equivalente que permita hacer pagineos y búsquedas sobre las columnas. Las tablas son muy importantes para mí.
- Ajax….
- Templates o skins ya definidos, y una manera de personalizar un poco la presentación final.
- La menor cantidad de código goma o de plomero. No soy amigo de XML, pero tampoco enemigo: si se usa de manera inteligente puede ayudar mucho, pero hay frameworks que simplemente se pasan con sus implementaciones en xml.
- Documentación, ejemplos, etc.
- Una comunidad grande. Este es uno de los puntos de mayor peso a mi criterio. Una comunidad de mayor tamaño permite corrección rápida de errores, foros, comentarios, etc.
- Algún soporte comercial, o el patrocinio de una(s) de las grandes empresas de software.
- Una expectativa larga de vida. Importante también. La tecnología que escoja será mi caballo de batalla por los siguientes años. Al menos espero que así sea.
- Cantidad de componentes o widgets. Yo no me voy a poner a diseñar calendarios en js o comboboxes que tengan autocomplete.
- Quiero escribir las cosas una vez. Si el framework me deja “deployar” mis aplicaciones en html, flash, mobile, desktop y demás mejor.
Aparte de las mencionadas hay un “me gusta” que una nueva tecnología debe tener. Ese presentimiento interno de que mi relación con la tecnología a escoger será buena.
Buscando gui
Hace unas semanas comenté sobre las diferencias entre un ambiente de escritorio y un ambiente web. No me costó mucho comprender que debo comenzar con un ambiente web: lo conozco bien, tengo experiencia en él y manejo bien los conceptos y las tecnologías.
Por mucho tiempo mi plataforma de trabajo se basaba en hibernate, para la persistencia de datos, jsf para la presentación, más específicamente richfaces, junit para los tests. Simple pero funcional. En su momento tuve la disyuntiva richfaces-icefaces, pero decidí irme por richfaces porque me gustó más y por el hecho de que JBoss lo soportaba. Estaba comenzando con SEAM cuando tuve que hacer un deploy de un proyecto con richfaces en un weblogic 8 que costó muchísimo, lo que me hizo quererme hacer más independiente del servidor en el que instalo: que corra en tomcat.
Bueno, hoy me entero que jboss comenzó´a pasar su middleware a GWT. En pocas palabras me dijeron que abandonarán eventualmente el proyecto richfaces. Por ahora richfaces me funcionó bien, salvo algunos problemas de compatibilidad de exploradores. Pero adquirí mucho conocimiento al respecto y las cosas funcionaban como quería.
Ahora, lo más sabio es buscar y casarme con una nueva tecnología lo más pronto posible. Lo que me abruma es la cantidad de propuestas que existen. Los llamados RIAs ahora aparecen por todos lados. Cada framework con enfoques muy diferentes y propuestas más diferentes. Pero hay que elegir uno.
Hace unas semanas hice un poco de investigación. Al final creo que los competidores finales son:
- GWT.
- ZK.
- Echo
- OpenLaszlo.
- Flex.
- Appcelerator.
- AdobeAir
- JavaFx
- Wicket
- SmartClient
- SpringMVC
- OpenXava
- ItMill
- Rialto
Estas han sido mis opciones finales, sin embargo la oferta es considerablemente más amplia. Una búsqueda en google o en wikipedia les puede dar más luces. De todos estos frameworks algunos tienen un enfoque más geek, otro más “javero”, otros mas xml, otros más swing, etc. Lo bueno es que hay mucho de donde elegir. Lo malo es, irónico, que hay mucho que elgir.
Comenzando una empresa de software
Una de las razones por las que nació este blog es para documentar mi experiencia construyendo una nueva empresa de software y los proyectos nuevos que vayan surgiendo. Uno de los talones de Aquiles del mundo del software es la incapacidad de almacenar conocimiento, la constante invención de agua azucarada a la que todos los que nos movemos en esta bosque constantemente nos sometemos.
Un buen comienzo es ser sincero: ¿Para qué existe una empresa de software? Como cualquier empresa, la primera razón es: hacer dinero. Creo que cualquier empresa que olvide ese principio llegará a tener problemas de subsistencia. No es ser materialista, ni mucho menos, pero al final de los cantares, o como la llamaría Aristóteles, la causa final de una empresa de software es hacer dinero. Y, siguiendo con Aristóteles, la causa material sería el software.
Un libro que recomiendo es On The Business of Software de Erick Sink. Muchas de las ideas que presentaré vienen del libro, que también tendrá su post especial….cuando tenga tiempo.
Pero siguiendo con el punto. Así como un martillo existe para martillar, una bicicleta para moverse, una guitarra para tocarla, del mismo modo una empresa existe para hacer dinero. Entonces una empresa de software existe para hacer dinero a través del software que hace.
Tipos o divisiones en las empresas de software hay muchos. Hay empresas que se dedican a hacer sistemas operativos, otras a hacer bases de datos, otras a hacer ERPs, otras para hacer páginas web, otras para integrar distintos sistemas, otras para software bancario, otras de telecomunicaciones, otras para restaurantes, otras hacen software a la medida y un gran etc.
Resumiendo, una empresa de software es una organización dedicada a hacer dinero a través de software. El siguiente punto que se debe definir es ¿qué tipo de software hará la compañía?
En el blog hablaré de mi proyecto, con las restricciones y oportunidades que tengo (el famoso FODA). ¿Haciendo qué tipo de software podré hacer negocio? Para ser realistas por el momento han de desecharse las “grandes ligas”. Es irreal suponer, diseñar y demás, una empresa que se dedique a hacer sistemas operativos, o una competencia a MS Office, a SAP, a Oracle o alguno parecido. No digo que no se pueda, lo que digo es que una empresa pequeña NO debe empezar por ahí.
¿Entonces en donde empezar? Bueno, hay nichos, muchos nichos. Hay que elegir un nicho que sea lo suficientemente pequeño que no interese a los grandes, pero que sea lo suficientemente grande para crear ganancias. Creo que una empresa pequeña será generalmente una evolución de consultorías pequeñas o medianas de software hecho a la medida. Este creo que es un buen punto de partida. Por ello hay que elegir cuidadosamente los proyectos en los que un consultor que desea crear una empresa de software se mete.
A la fecha no sé en que nicho de mercado deseo meterme, pero ya les estaré comunicando cuál. También creo que es importante definir un proyecto e intentar separarse un poco del software a la medida ¿por qué? Porque el retorno de un producto que se vende muchas veces es muchas veces mayor que estar haciendo software a la medida.
En conclusión: una empresa de software pequeña es una organización que se dedica a ganar dinero a través de pequeños proyectos de software, consolidando uno o varios productos de los que puede obtener ganancias en un mercado en el que puede competir.
Claro, esto es una simplificación. Una empresa de software, como cualquier otra empresa, tiene mucho conocimiento, muchos trucos, mucha experiencia que debe adquirir y cultivar. No es sencillo funda una empresa próspera de software: hay muchos riesgos que hay que saber identificar y manejar. Hay metodologías técnicas y administrativas que se tienen que adquirir y refinar. El software es una ciencia-arte y para que una empresa que hace algo así es necesario que se componga de artistas-científicos que la hagan funcionar.
Luis H. Fernandez
luishernan@gmail.com
Calidad del software
Calidad en el software.
El término calidad siempre me ha parecido ambiguo. ¿Que hace que un bien o servicio “posea” calidad? No sé. Hay procesos de calidad, chequeos de calidad, y mil cosas con calidad, pero nadie entiende a ciencia cierta qué es calidad, aunque todos comprenden el término. Aunque para algunos es aquel software que no tiene bugs, para otros el que satisface al cliente, para otros es el que optimiza recursos, para otros el que se mira bonito, etc.
Cuando el término entra al contexto del software, la cosa se pone peor. ¿Qué hace que un software sea uno de calidad o no? Claro, debido a lo ambiguo del término, la discusión en este tema no tendrá fin.
Con todo, lo que hacemos es software, y nos gustaría hacer siempre software de calidad. Para poder etiquetar a un software como uno de calidad, debemos definir algunos atributos para poder poner el software en evaluación. Estos atributos, y sus prioridades, cambian cuando cambia el contexto de software: un sistema para hospitales se juzga de una manera distinta a una página web.
En FFSE R. Glass propone siete atributos del software que le confieren lo que llamamos calidad:
+Portabilidad: la portabilidad implica que un programa puede correr en distintas plataformas, no sólo de sistemas operativos sino diferentes versiones, diferentes ambientes y esquemas.
+Fiabilidad o confiabilidad: el software hace lo que debería hacer, y no “truena”.
+Eficiencia: que tanto recursos economiza en tiempo y espacio el software.
+Facilidad de uso: es fácil de usar?
+Evaluable: Es sencillo de examinar? Se le pueden correr fácilmente unit tests?
+Leíble: Es el código expresivo y fácil de comprender?
+Mofificable: Qué tan sencillo es modificar el software.
+Escalibilidad: pueden agregarse funciones de manera rápida y consistente?
Buscando en internet, encontré otros atributos que vale la pena mencionar:
+Compatibilidad: es el software amigable con otros sistemas?
+Seguridad: es el software seguro contra ataques externos?
Todos concordarán que los atributos anteriores son buenos parámetros para medir la calidad de un producto de software. Sin embargo el orden de estos productos varían de proyecto a proyecto. Un proyecto que maneja información confidencial puede que tenga la seguridad muy alta, una página de internet tendrá muy alta la facilidad de uso, un software bancario tomará más en cuenta la fiabilidad que la portabilidad.
El usuario y el código
Al usuario final le viene del norte en qué tecnología corre un programa, o que metodología de desarrollo se utilizó para su creación. Poco le importa si se utilizó un lenguaje de cuarta generación o assembler. El usuario toma por sentado ciertos estándares y cierta funcionalidad. Por ejemplo un usuario espera siempre que en el lugar que aparezca un disquete se grabe su trabajo. Si esto no funciona bien, el usuario tendrá una muy mala percepción del software, y por tanto el software no tendrá mucha calidad.
El otro lado de la moneda es la calidad del código. ¿Es sencillo de encontrar errores? ¿Hay un buen uso del modelo de programación? ¿Se optimiza el uso del hardware? Aquí cada quien tiene un criterio diferente, hay filosofías, metodologías, paradigmas y demás.
Glass expone algo que me llamó mucho la atención: la satisfacción del cliente no es lo mismo que calidad de software. Entre los elementos que evalúa el cliente están cosas como el precio del producto, el diseño, el tiempo de entrega, el soporte y otros. Un mal software puede tener una alta satisfacción (aunque poco probable), y un buen software puede ser mal valuado por el usuario (créanme, sucede). Entonces la política de calidad de la empresa en general es distinta a la política de calidad del software en sí. Pese a muchas opiniones, el software es el código y nada más. Otras cosas le van unidas, pero no son software.
En Pragmatic Programme Hunt y Thomas exponen un punto importante: software lo suficientemente bueno. En ocasiones, especialmente cuando no hay restricciones de calendario, el desarrollador quiere siempre mejorar su software. Irónicamemte un software puede ser siempre mejorado. Hay que aprender cuando un software es lo suficientemnete bueno, porque agregarle funcionalidad o mejoras puede ser hasta contraproducente si no se sabe donde parar. Al final esto es ingeniería de software, y como todas las ingenierías nuestro objetivo es calcular. Si voy a comprar alambre para cercas las plantas de mi casa puedo calcular la circunferencia usando 3 en vez de pi, si voy calcular los materiales necesarios para un edificio redondo seguramente usaré 3.14159 o tal vez más dígitos, y si estoy calculando la órbita de una nave espacial definitivamente usaré más decimales. Hay que saber cual me conviene más. Lo mismo en el software.
Existe un ISO, el 9126 que se dedica a la calidad de software tiene puntos muy interesantes. Especialmente me gustó la división que hacen para medir la calidad: la calidad del modelo, la calidad de la métrica externa, la de la métrica interna y la calidad en el uso de las métricas. Está también CMMI que se dedica a la calidad estandarizar la calidad del software y la calidad del proceso productivo de éste.
En fin la calidad de software es algo que radica entre lo objetivo y lo subjetivo. Hay mucha leña por ahí para partir, porque el universo del software es también dinámico y los parámetros también cambian. Cada equipo de trabajo tiene sus propios parámetros. Lo que quiero recalcar es que cada equipo debe definir cuales son sus parámetros para medir la calidad de su software. Luego modelar, diseñar, implementar y mantener el software apegado a esos claves. En cada proyecto el orden de prioridades cambian también y hay que tenerlo presente, porque al final de los cantares lo que queremos es que nuestro software funcione, le guste al usuario y se acerque lo más ppsible a hacer lo que tiene que hacer.
Luis H. Fernandez
luishernan@gmail.com
Algunos links.
http://synergix.wordpress.com/2008/07/02/modelo-de-calidad-tradicional-del-software/
http://blog.xebia.com/2008/11/05/what-exactly-is-software-quality/
http://en.wikipedia.org/wiki/Software_quality
http://satc.gsfc.nasa.gov/support/STC_APR96/qualtiy/stc_qual.PDF
http://en.wikipedia.org/wiki/ISO_9126
http://www.bth.se/tek/besq.nsf/(WebFiles)/CF1C3230DB425EDCC125706900317C44/$FILE/chapter_1.pdf
Web o desktop?
Web o Stand-alone?
Hay un nuevo proyecto que deseo comenzar. Es sumamente agradable poder elegir la tecnología a usar, pero a la vez puede causar un gran dolor de cabeza debido a la gran, inmensa, gigantesca, cantidad de opciones que se abren. ¿Qué tecnología uso? ¿Web o no web? ¿Java, C++ o .net? ¿Qué DBMS?
Cuando un cliente pone las reglas, el rango de acción disminuye: nosotros trabajamos IIS en Windows, o nosotros MySQL en Linux, con PHP, o nosotros una opción barata de hosting, y un gran etc. Pero cuando pensamos en desarrollar un nuevo producto ¿qué tecnología usar?
En principio, debido a mi experiencia anterior y mi área de conocimiento, siempre tiendo a ver todas las soluciones bajo la lupa web. Creo que en un futuro no muy lejano las aplicaciones de desktop irán desapareciendo. Hace más de diez años teníamos ya los applets, y es irónico como las nuevas tecnologías comienzan a tener ese punto de vista.
Hay aplicaciones que son de naturaleza web, y tendrían poco sentido hacerlas desktop, por ejemplo las redes sociales, buscadores, sitios de noticias, etc. Hay aplicaciones que son de naturaleza desktop y que no tendría sentido volverlas web: compiladores, aplicaciones de oficinas, IDEs, etc. Sin embargo las cosas han cambiado y muchas de estas aplicaciones están migrando al mundo web. Hay una intersección cada vez mayor entre las aplicaciones web y las desktop.
Web o desktop. La mayor parte de aplicaciones empresariales (tema para otro post) pueden perfectamente ser desarrolladas en ambas tecnologías, con las ventajas y desventajas de cada una. A mi opinión la decisión en cuánto al enfoque que se debe tomar depende de dos cosas: costo y tiempo.
Creo que una aplicación desarrollada bajo el paradigma web o bajo el paradigma de escritorio debería poder ser compilada o “deployada” en cualquiera de los dos contextos. Todavía no he encontrado muy asentado este concepto pero creo que debería comenzar a predominar. Pero el mundo no es color de rosa, y las cosas no funcionan así.
Hay ya muchos frameworks que permiten programar aplicaciones web como si fueran de escritorio (Wicket por ejemplo), pero todavía están un poco verdes en su desarrollo. Cada aplicación tiene un contexto definido y unas restricciones que deben respetar, pero considero que es mejor idea hacer las aplicaciones web, aunque al decirlo todavía hay algo que siento no me deja aconsejarlo tranquilamente.
Ventajas de web.
+Multiplataforma para el cliente.
+No hay necesidad de actualizaciones.
+Centralizado.
Ventajas de escritorio.
+El usuario está más acostumbrado.
+No se necesita un server.
+Aplicaciones muy pesadas deben correr en el cliente.
Luis H. Fernandez
luishernan@gmail.com
Buenas prácticas: Manejo de versiones.
Un día de trabajo pesado, muchos problemas resueltos y una de las partes más difíciles del proyecto superada. Pluck, por alguna razón el editor se cierra. Un gran puñetazo en el escritorio: perdimos los cambios. O tal vez fue un gran cambio que comenzamos a hacer y no funcionó. Todos hemos pasado uno que otro mal momento por no saber organizar nuestro trabajo.
De las buenas prácticas de desarrollo de software que quiero sacar a discusión, comenzaré con el manejo de fuentes. Sorprendentemente el manejo de fuentes y de versiones no se toma tan en serio como debería. Muchas veces he estado en proyectos, o los he visto, en los que muchos, muchísimos problemas surgen debido a espaguetis de código mal unidos, versiones que se creían diferentes, trabajo que se pierde.
Sobre la teoría del manejo de versiones se ha hablado mucho ya. No es algo sencillo en lo más mínimo, a mí me sigue asombrando lo eficientes que SVN o CVS son a pesar de lo complejo de su funcionamiento. Muchos buenos manuales existen para aprender a usar SVN o CVS. Yo en general me iría con alguno de ellos dos, aunque a la gente del entorno MS le podría servir más aprender sourcesafe.
Independientemente, mi punto es el siguiente: SIEMPRE hay que usar algún manejador de versiones. Es la primera cosa que un proyecto serio requiere. Es algo que ni siquiera debe ser apuntado, sino que siempre entendido que habrá un manejo de versiones.
¿Por qué? En lo personal las siguientes razones son los motivos por los qué uso un manejador de veriones.
+Backup. Son una manera muy sencilla para hacer copias de respaldo. Aunque sea una diaria.
+Cambios. Cuando quiero hacer un cambio peligroso, me quita el miedo de pasarme llevando algo por delante. Si eso pasara, simplemente vuelvo a una versión anterior.
+Manejo de versiones en sí. Un cliente quiere unas cosas, el otro otras, pero la base es la misma. Puedo mantener las fuentes exactas de cada instalación, añadir nuevas cosas y luego unirlas. Es una maravilla.
+Trabajo en equipo. El manejo de una manejador de versiones facilita enormemente el trabajo en equipo. Al final del día siempre hay una versión, igual para todos, y los cambios de cada uno los ve el otro. OJO un error común es es tratar al manejador como el que solucionará todos los problemas y no es cierto. La comunicación entre el equipo es siempre vital.
+Es sencillo. Cualquier IDE te permite importar tus fuentes a un repositorio y trabajar a partir de él sin mucho trabajo, incluso si estás comenzando a usar una manejador.
En resumen, en cualquier proyecto lo primero que deben hacer SIEMPRE es utilizar una manejador de versiones. Mis consejos son utlizar SVN o CVS, son sencillos, son libres, la mayoría de IDEs tiene extensiones para ellos y sobre todo les van a hacer la vida más sencilla.
Luis H. Fernández
luishernan@gmail.com
Netbeans 6.5
Hoy se dio el anuncio oficial de netbeans 6.5. Sin duda los amantes de Java están con las ganas puestas para probarlo y ver las nuevas cosas que tiene. Ahora lo estoy bajando para probarlo, ya tenía el Release Candidate 2, pero no hay nada como tener la versión final. Hay muchas cosas interesantes, entre ellas es la importación y sincronización de proyectos con eclipse. Esta característica me llama mucho la atención porque me permite trabajar con los dos editores.
De hecho creo que la comunidad Java debía proponer un JSR pronto para la organización de proyectos en los IDEs, de tal manera que al crear un proyecto en netbeans, lo pueda abrir en eclipse, intelliJ, JDeveloper, o cualquier otro que se ponga enfrente, creo que sería de mucha utlidad.
luishernan@gmail.com
Español, español…español en inglés
No sólo en el software, sino que en muchas áreas, el inglés ha sido una lengua que ha metido sus narices en todas las culturas. En la nuestra con especial fuerza: programamos en inglés. Al menos yo, no conozco un lenguaje de programación cuyas palabras clave estén escritas en otro idioma. Tiene sus ventajas el uso del inglés: es más corto. Pero sobro todo tiene la ventaja de que todos podemos ponernos de acuerdo en un idioma para comunicarnos.
Y no sólo las palabras claves se escriben en inglés. Los foros, las comunidades se construyen en inglés. Las documentaciones y los bugs, todo se hace en inglés. Cuando nos topamos con algún problema extraño, llegaremos con foros en los que muchas veces ninguno de los participantes habla inglés como lengua materna, pero todos hablan inglés para intercomunicarse. Me causa gracia cuando en un foro me comunico con personas de Irlanda, India, Brasil, Rumania, México, Alemania, Rusia y etc. Me asobmra que todos nos podamos comunicar. De no existir el inglés simplemente no habría un medio de comunicación. Cuando busco un software nuevo, o alguna herramienta por ahí, espero que la página esté en inglés. Incluso cuando la página tiene una versión española, prefiero batirme con la que está escrita en la lengua de shakespeare. Sin duda el inglés permite la existencia y el crecimiento de una comunidad muy grande de desarrolladores.
Pero hablar español nos cuesta plata. Hacer programas en español nos cuesta más plata y tiempo que hacerlos en inglés. Usar ñ,á,é,í,ó,ú,ü,¿,¡ y alguno que otro por ahí es sumamente caro. Nuestro idioma tiene poco o ninguna influencia en el mundo del software. Tanto así que la misma palabra “software” la tuvimos que traer del inglés tal y como estaba. Sí, el inglés nos ayuda a aprender, pero nuestras aplicaciones las escribimos en español. Y eso no siempre es tan sencillo como parece. Muchos de los que leen estas letras sin duda han tenido más de alguna rabieta cuando ven que en su software aparecen Ã,á�,é,à y otro buen montón de simbolitos raros. O cuando uno tiene que hacer maravillas para hacer que funcione una base de datos con encoding latin-1, un server con ISO-8859-1 y una aplicación con UTF-8. Alguien, con un toque de sátira, dijo una vez “lo bueno de los estándares es que hay muchos”. Más de alguno se ha puesto a llorar cuando hace un pequeño cambio y ve que cambia al charset que. Todos estamos acostumbrados a términos de charset, asdfasd, asdfasd.
En lo personal intento tratar de usar siempre UTF8, pero no siempre es posible debido a que en ocasiones no tengo el control sobre la plataforma en la que instalaré. Este es el primer post sobre el español y el inglés que haré. Hay muchos libros y muchos lugares en los que se puede obtener información sobre como hacer mejor software, pero esos siempre son en inglés (ironías), así que pienso comenzar la discusión para aquellos que hablamos español….¿cómo podemos mejorar el software en español? Lo gracioso es que siempre estaremos escribiendo aplicaciones en español definiéndolas en inglés.
Bienvenidos
Abro este espacio para lograr un poco de discusión y para exponer mis ideas sobre el desarrollo de software. Si estás leyendo estas letras es porque te gusta programar, porque de otra manera no te interesa mucho lo que diré.
Creo que el desarrollo de software sufre un estancamiento severo. Hemos desarrollado nuevas e interesantes técnicas, modelos de manejo de datos, metodologías de desarrollo, y un sin fin de formas para hacer las cosas. La nuestra es una tarea altamente intelectual y hemos estado viendo como hacernos la vida más sencilla.
Sin embargo los tiempos y costos de desarrollo permanecen iguales, sino es que han crecido más. El estallido de GUIs con mucho entorno gráfico han añadido dificultad a nuestra tarea. El desarrollo en web se ha tornado altamente dominante, y los usuarios esperan webs bonitas, pero a nosotros, por lo general, no nos gusta hacer cosas bonitas, nos gusta hacer cosas que funcionen. Han aparecido los diseñadores gráficos, cosa que no es mala en sí, pero no han aparecido formas de lograr una simbiosis entre programadores y diseñadores gráficos.
Todos aprendemos nuevas tecnologías y frameworks constantemente. Aparecen, y queremos usarlos. Algunas de estas ideas fructifican y se convierten en estándares de facto. Muchas otras crean un gran alboroto pero terminan quedando en lo que algunos llaman shelfware, es decir en la librera guardados y considerados como ideas interesantes pero que no aplican.
Finalmente, creo que el software es una gran oportunidad de desarrollo para Latinoamérica. La inversión en software es relativamente pequeña: una computadora y alguien que sepa usarla. No se precisan de multimilonarias fábricas ni materias primas. Necesitamos personas educadas que sepan manejar y crear y software. Siempre me he preguntado: ¿por qué de los miles de frameworks que aparecen, hay tan pocos latinoamericanos? Y cuando de casualidad me encuentro con uno de origen latinoamericano, generalmente es brasileño. Este blog tambien quiero que sea una invitación, que lance una espinita, para que desarrolladores hispanos nos pongamos las pilas y creemos. Tenemos la capacidad, aunque nos hemos dormido.
Así que bienvenidos, ojalá aparezca pronto la crítica y las ideas. El nuestro es un mundo precioso, así que démosle un toque con ñ.
