jueves, 28 de mayo de 2009

Hacia un Framework de Persistencia: Capítulo 4 – Patrón Facade

Continuemos. Hoy nos toca el patrón Facade (ó "Fachada" en español). Plantearemos un ejemplo "abstracto" el cuál nos servirá de guía para definir formalmente lo que provee el patrón.

Consideramos:

  • Cliente
  • Fachada
  • Subsistema (conjunto de clases, cómo un Subsistema de Persistencia :)

Nos detenemos un momento a pensar en lo siguiente: Consideramos al subsistema como un conjunto de clases "complicado", es decir, con varias tareas u operaciones que realizan (ni hablar si existen subsistemas anidados, o sea, subsistemas dentro de otros subsistemas).

Para el cliente común tener que interactuar directamente con el subsistema sería bastante tedioso. Esperen, para el cliente común, recalco. No quita que el subsistema deba ser lo más general posible, proveer todo lo que crea conveniente, garantizar extensibilidad para el cliente particular (y avanzado) que lo deseara. Pero esto es puntual, la mayoría tiene intereses comunes en lo que respecta a la funcionalidad que provee el subsistema en cuestión. Por ejemplo, poco me interesaría saber qué clases (y qué métodos de esa clase) necesitaría para realizar un cálculo complejo (que probablemente requiera ciertas configuraciones antes de invocar esa clase con ése método), yo, como cliente, me gustaría hacer algo como "calculoAvanzado()" y que alguien (¿Una clase?) hiciera la labor "complicada", que debería desacoplar al cliente con el subsistema subyacente. Despacio, vamos despacio, ya se irá aclarando.

Aquí es donde entra en juego nuestra nueva clase "Facade". La clase "Facade" nos brinda (muy amigablemente) lo que necesitamos, desacoplar al cliente del subsistema subyacente, proveyendo una interfaz genérica para usuarios comunes, haciendo del subsistema complejo un subsistema fácil de utilizar. ¡Qué bueno! Sólo tener que invocar un método con parámetros mínimos, o al menos sólo los necesarios, para que el Facade se encarga del resto, instanciar las clases del Subsistema que necesite, y todo lo demás que el Cliente antes hacía.

Claro, y a esto se le agrega la tremenda potencia que tenemos un único punto de acceso, lo que modifiquemos lo hacemos aquí, garantizando la independencia de los Clientes con el subsistema. Por supuesto, una vez más, esto no quita que un cliente particular (y avanzado) quiera extender o utilizar el subsistema a su manera para operaciones específicas las cuales muchas veces se omiten en la clase "Facade" por cuestión de simplicidad (ya que pocas veces son utilizadas).

Acabamos de mencionar el objetivo el patrón "Facade" más sus ventajas aparejadas. Desventajas, talvez la mayor, hay que saber cuándo utilizar una clase "Facade" y también (y más importante todavía) qué operaciones proveerá el Facade, considerando que tiene que proveer aquellas que son comunes a todos los usuarios, y garantizar cierto grado de simplicidad con un bajo acoplamiento entre el cliente y el subsistema. Entonces no es tan fácil hacer un "buen" Facade. No, no lo es, pero sí que vale la pena, lo vale por el sólo hecho de lo que nos provee. Es tremendamente útil (lo será en nuestro Framework de Persistencia [FWP], ya verán…).

Ya que en este capítulo no vamos a dar un ejemplo particular del Facade (lo dejaremos para nuestro FWP), mostramos una breve estructura de lo que planteamos de manera abstracta:

Tomada de http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/facade.html. La imagen es simplemente excelente. Ilustra el propósito y ventaja del patrón "Facade". En la imagen de la izquierda vemos lo que sería sin el patrón (¡flechas de los Clientes hacia el Subsistema "complejo" por todos lados!), dependencia, complejidad en cuánto con qué clase (y método) interactuaremos. En cambio en la imagen de la derecha todo se reduce a nuestra nueva amiga, la clase "Facade", quién hace de intermediario entre los clientes y el subsistema "complejo", garantizando bajo acoplamiento de clientes al subsistema, y fácil, muy fácil (créanme) interacción de clientes con el subsistema.

Hasta aquí tenemos lo que buscábamos, comprender el patrón Facade a grandes rasgos, si entendieron lo anterior, por más mínimo que sea, es más que suficiente en esta instancia. Lo que sigue lo dejo para aquellos que quedaron con un poco de ganas de saber algo más del patrón Facade.


Algo interesante a remarcar es el tema de implementación del patrón Facade. Si bien es muy sencillo crear una clase "Facade" con la interfaz (métodos) que el cliente invocaría, hay que considerar ciertos puntos:

  • A veces puede surgir la necesidad de tener un Facade abstracto y varios Facade concretos (por si hubiera varios subsistemas concretos por ejemplo), con esto garantizaríamos que el cliente se mueva únicamente con el patrón facade (abstracto) y los facade concretos (los cuáles NO son accedidos por los clientes) se encargarán de interactuar con el subsistema concreto correspondiente.
  • Otra manera es tener un solo Facade con varios objetos de los diferentes subsistemas concretos.
  • Se debería considera, para una buena programación, ver aquellas clases del subsistema que deberían ser privadas (sin posibilidad de ser accedidas por el cliente) y aquellas que sí. Es especialmente útil ya que el cliente común sólo usará aquellas que comúnmente usa (suena redundante, pero así es); las clases que quedaron privadas serán usadas para casos particulares por clientes particulares, quienes quieran extender o ampliar el subsistema.
  • Consideremos lo que planteábamos al principio que en general el Facade es un "único punto de accedo" (¿Les suena a algo parecido? ¿Quizá a un patrón visto anteriormente?), sí, no hay muchas opciones. Combinar el patrón "Facade" con el patrón "Singleton" suele ser una tarea muy común y sencilla.

Por aquí, mis amigos/as, dejamos. Sigue un poco tedioso, pero sepan que será de mucha ayuda al momento de meternos de lleno con el FWP. ¡Saludos!.

lunes, 25 de mayo de 2009

Hacia un Framework de Persistencia: Capítulo 3 – Patrón Singleton

Planteemos primeramente una situación en dónde DESCONOCEMOS la existencia de los patrones de diseño, en particular del Patrón Singleton.


public class Alumno {

private static int codigoGlobal = 0; //Atributo de clase

private int codigoAlumno; //Atributo de c/instancia de clase (cada objeto)

private String nombre; //Atributo de c/instancia de clase (cada objeto)


public Alumno(String nombre){ //Constructor por parámetros

this.nombre = nombre;

this.codigoAlumno = ++codigoGlobal; // PRIMERO se hace el incremento de codigoGlobal y luego se asigna a codigoAlumno

}

}


¡Al fin algo de código!

No hay mucho por agregar, una clase Alumno que, cómo caso particular, para generar su código se vale de una variable de clase "códigoGlobal" la cual será incrementada en cada instancia que se genere de la clase Alumno. Cada instancia almacenará su códigoAlumno.

¿Qué problemas trae este procedimiento? Estamos involucrando en la clase Alumno algo que deberían poder consultar SIN la posibilidad de modificar, además la clase Alumno no tendría por qué hacerse cargo del códigoGlobal.

Si lográramos llevar este comportamiento a una clase diferente podríamos tener un único punto de acceso. Es decir, cada cosa que quisiera modificar lo hago en esta nueva "clase", sin tocar la clase Alumno. Luego es intuitivo, podríamos tener un GestorDeAlumnos (una clase que se encargaría de instanciar nuevos Alumnos, dar de bajo a Alumnos, etc) para consultar ésta nueva "clase" que ahora llamaremos "SingletonAlumno" para hallar el códigoGlobal que antes estaba en la clase Alumno. Veamos en código cómo quedaría.


public class Alumno2 {

private int codigoAlumno;

private String nombre;


public Alumno2(String nombre){

this.nombre = nombre;

}


public void setCodigoAlumno(int codigoAlumno){

this.codigoAlumno = codigoAlumno;

}

}


public class SingletonAlumno {

private static SingletonAlumno singleton;

private int codigoGlobal;


private SingletonAlumno(){

codigoGlobal = 0;

}


public static SingletonAlumno getSingleton(){

if (singleton == null) singleton = new SingletonAlumno();

return singleton;

}


public int getCodigo(){

return ++codigoGlobal;

}

}


public class GestorAlumno {

private ArrayList list;


public void addAlumno(Alumno2 a){

int codigoAlumno = SingletonAlumno.getSingleton().getCodigo();

a.setCodigoAlumno(codigoAlumno);


list.add(a);

}

}

Ya sé, seguro dijeron, ¿pero está loco?, ¿más clases, más CÓDIGO?, ¿en qué demonios gané?

Pasemos a analizar brevemente lo que realiza el código. Lo más importante de aquí es la clase SingletonAlumno. Con esta definición estamos garantizando que será un único punto de acceso en el programa. Al declarar una variable de clase y privada "singleton" estamos asegurando que desde afuera sólo se podrá acceder con el método público getSingleton(). Piensen un ratito… ¿me pueden generar una instancia de la clase SingletonAlumno?... NO, el único constructor es privado. Listo, problema resuelto. Repito. ÚNICO punto de acceso del programa. Lo demás es comprensible.

¡Ah! Se me olvidaba, combiné algo de "filosofía objetos". Desde el programa con el cuál interactúe el usuario, nunca podrá recibirse un código de alumno por parte del mismo. Al menos en nuestro caso es así, porque por política optamos que sea "autogenerado" el códigoAlumno. Esto se puede ver claramente en el manejo del gestor. El Alumno que me pasan sólo tendrá nombre y el gestor se encargará de establecer su código (previo pedido al ÚNICO encargado de manejar el códigoGlobal de los alumnos, o sea, el SingletonAlumno).

Talvez se nos hizo un poco tedioso, no importa, lo importante de todo esto es esclarecer el uso de patrones. Retomemos la pregunta, ¿en qué gané con esto? Bien, sólo aprendimos, no ganamos más que eso. Pero, ¡no es poco! Absolutamente ¡NO es poco! No se puede ver, como dije, en esta sencilla situación la bondad del patrón singleton, pero la experiencia mostrará lo suyo.

Ahora sí estamos en condiciones, un poco más formal, junto a mí buen libro de Erich Gamma, de plantear el patrón Singleton resumidamente en dos o tres palabras:

Propósito del patrón Singleton: Garantizar que una clase sólo tenga una instancia, y proporcionar un punto de acceso global a ella.

Cuándo utilizarlo:

  • Cuando deba haber sólo una instancia de una clase y ésta ser accesible por los clientes.
  • La única instancia debería ser extensible mediante herencia y los clientes deberían poder usar ésta sin modificar su código.

Beneficios:

  • Acceso controlado a una única instancia.
  • Espacio de nombres reducidos.
  • Permite refinamiento de operaciones.
  • Más flexible que las operaciones de clase.

Listo, lo demás escapa del objetivo de este capítulo. En la próxima nos metemos con el patrón Facade, el cual usaremos en nuestro FWP.

¡Hasta luego!


domingo, 24 de mayo de 2009

Hacia un Framework de Persistencia: Capítulo 2 – Patrones

Sigamos con nuestro framework de persistencia (FWP). Para el mismo necesitamos conocer algo de "patrones". Analicemos qué son los patrones y sus ventajas/desventajas.

¿Qué es un patrón? En nuestro caso nos metemos de lleno a los patrones de diseño.

Un patrón de diseño busca resolver problemas de diseño similares con una "receta" similar.

Tengamos en cuenta que la mayoría de las veces nos enfrentamos a problemas de diseño casi idénticos pero no necesariamente iguales, de ahí surge el énfasis en la palabra "similar".

Entonces, un patrón en esta definición criolla de "receta", es un conjunto de interfaces BIEN definidas las cuáles deberían ser implementadas en el problema PARTICULAR por el desarrollador para dar solución al problema de diseño concreto.

Seguramente notaron una vez más las bondades y la BONDAD de la reutilización de la POO (Programación Orientada a Objetos)1. Y sí, si queremos tener una "receta" común a problemas similares debemos programar garantizando su extensibilidad y reutilización.

Entonces, la gran ventaja de los patrones de diseño está dada en su definición. Re-utilizar código, NO volver "nunca más" a reescribir esa porción de código qué tan difícil sea hace llevar de un lado a otro (ó de un programa a otro), ¿por qué?, porque los patrones son "abstractos" en el sentido que no están orientados hacia un problema en particular, sino a un problema de diseño "global", en cambio nuestro código de un lado a otro SÍ estarían implementados concretamente a un problema particular, invadiendo su portabilidad.

Ok, ¿Desventajas de los patrones de diseño? Indefectiblemente consume tiempo de desarrollo, muchas veces injusto para nuestro programa. Y surge algo similar a los frameworks, cuándo utilizar y cuándo no utilizarlos, cuándo estamos ante el "abuso" de los patrones de diseño. Definitivamente se gana con la experiencia, no existe otra forma.

¿Dónde encontrar patrones de diseño? En internet. También recomiendo fervorosamente el libro de Patrones de Diseño de Erich Gamma.

Pues, parece todo muy lindo, pero sigo sin entender el concepto y las ventajas de los patrones de diseño. Nada mejor que un ejemplo para esta situación. Vamos a ver el Patrón Singleton en el siguiente capítulo, algo sencillo para comenzar.

Antes de saludar, quiero encarecidamente resaltar un aspecto sumamente importante en todo ámbito de la vida. La retroalimentación. Me gustaría enormemente que cada cosa que desearan compartir, criticar, preguntar, reflexionar, etc. las hagan llegar con su comentario. De ésta manera todos nos veremos favorecidos.

Nada más gente. ¡A programar!

sábado, 23 de mayo de 2009

Hacia un Framework de Persistencia: Capítulo 1 - ¿Frameworks?

Finalmente, empecemos con algo. ¿Qué buscamos?, básicamente desarrollar un framework de persistencia aplicando la metodología del patrón DAO. Tranquilos, cada cosa se verá con detenimiento. Sentemos las bases. La idea surge nuevamente con mi amigo Nafria Federico para la universidad, en la cual debemos desarrollar un proyecto web en JEE. En este capítulo haremos un breve sondeo de los frameworks, qué son, qué ventajas/desventajas traen aparejados. Aclaremos una cosa, la idea de nuestro framework de persistencia surgió hace pocos días, por ende tendrá sus bugs, limitaciones, lo que sea; pero lo importante está, la idea.


En líneas generales, un framework no es más que una colección de objetos que buscan brindar servicios para un subsistema particular (como un subsistema de persitencia).

En nuestro caso apuntamos a un Framework de Persistencia (FWP) considerando una Base de Datos Relacional (BDR). El mismo, como tarea principal, deberá poder llevar los objetos a registros y los registros a objetos.


La principal ventaja sin duda alguna de un framework es su capacidad de reutilización. En sí, convengamos que una de las principales ventajas de la POO (Programación Orientada a Objetos) es su gran reutilización. ¡Ojo! Para poder reutilizar no basta “programar objetos” hay que saber “programar con la filosofía de objetos”, quiero decir, el arte de programar orientado a objetos. Pero éste será un tema para otro momento.


Sigamos, ¿Qué pasaría si estamos en un equipo de trabajo y lograramos reunir esfuerzo para programar hacia frameworks envés de “objetos” sueltos, empaquetados por ahí? Sin duda, los tiempos de desarrollo se reducirían a tiempos abismales. Obviamente, los resultados quizá no sean instantáneos, pero cuando tengamos que volver a desarrollar probablemente, y créanme, van a terminar usando alguna que otra función ya desarrollada; y no hay peor cosa que buscar y no encontrar las cosas reunidas y documentadas cómo debe ser. ¡Menos en un equipo de trabajo! (Es más, con sólo dos personas ya se complica el trabajo grupal…).


Pocas desventajas podemos mencionar de los frameworks, por supuesto, en aplicaciones pequeñas probablemente no necesitemos de ellos, y si necesitásemos, seguramente encontremos uno adecuado en internet. Por otro lado, convengamos que al utilizar un framework estaremos restringidos al lineamiento que propone el mismo, pero esto en general, si es un BUEN framework no tendría que traer problemas.


Entonces, ¡Usemos siempre frameworks! No, esperen. No abusemos de ellos. En aplicaciones específicas podrían llevar a una recarga, implementaríamos más de lo que nos haría falta. Entonces, mejor que siempre utilizar frameworks, aprendamos a saber cuándo utilizarlos y también a no re-desarrollar lo existente, en Internet existen miles de frameworks, conozcámoslo.


¿Pero entonces por qué un framework de persistencia cuándo los hay y de los muy buenos, como Toplink ó Hibernate? Sí, no hay necesidad. Pero sí en nuestro caso, por una cuestión de didáctica, buscamos aprender a desarrollar, a desarrollar bien, para luego hacer nuestros frameworks a “gusto y piacere”.


En la próxima empezamos viendo que patrones involucrará nuestro framework y qué son los patrones. Por ahora suficiente. ¡Saludos!

Nace un nuevo blog

¡Primera entrada! La idea surgió hace tiempo, pero recién ahora me he decidido por comenzar.

Básicamente el blog es Java, desde sus versiones para celulares (JME), estándar (JSE) hasta empresarial (JEE). Todo tema competente a Java, y a veces no, será tratado aquí.

Quien quiera saber un poco de mí, les cuento que actualmente curso cuarto año de la apasionante carrera de Ingeniería en Sistemas de Información en la Universidad Tecnológica Nacional (UTN) en la Facultad Regional de Córdoba (FRC).

A lo largo de mi vida programar fue mi pasión (desde muy chico), realicé pequeños proyectos en VB (aquella versión 6.0), exploré lenguajes como VFP, Assembly, C/C++, pero gracias a la universidad, mis energías se volcaron completamente por el maravilloso lenguaje Java.

A modo de resumen, en el primer año de la "facu" desarrollé sencillos algoritmos de encriptación, entre ellos uno mediante manejo de matrices. Para el segundo año junto a mi excelente compañero y amigo Federico Nafria desarrollamos una aplicación web (JEE) con ciertos frameworks (Toplink, Struts). En el tercer año, una vez más con mi amigo, llevamos a cabo el desarrollo de un proyecto para el envío en tiempo real de video desde un celular hacia la computadora, con detección de movimiento por software (JME).

Por ahora mis amigos es todo. Sin duda alguna, en la próxima nos metemos con algún tema de Java.

¿Sabían que Java, según el excelente diccionario Longman, se pronuncia "yava" y no "java"?