¡Hola! ¿Cómo están?. Gracias por volver a este su blog de código, esta vez les presento el comienzo de una serie de posts acerca de Patrones de Diseño. En este primer post definiremos que es un Patrón de Diseño y cuáles son las herramientas y conocimientos básicos para su construcción. Esta serie de posts está basada en el Libro Head First Design Patterns, Primera Edición - ISBN: 978-0-596-00712-6

Considero que es un muy buen libro de referencia, fácil de leer y de entender. Me considero una persona muy visual, tiendo a recordar más las cosas que veo que las que escucho o siento y este libro me ha dado una gran ayuda para visualizar mejor lo que entiendo. Este libro me lo recomendó el Ing. Juan Antonio alias @juanitodread, a quien considero un Software Developer muy bueno, bastante completo y apasionado por esto del software, a quien le he aprendido mucho. Les hago mención de esta persona y se los presento formalmente como colaborador de este blog y de esta serie de posts.
¡Vámos a Comenzar!


El código elaborado para esta serie de posts se encontrará en: Repositorio GitHub - Design Patterns


Patrón de Diseño

Un patrón de diseño es una técnica que ha sido elaborada, probada y validada para resolver un problema en específico, no es código, sino la solución para resolver el problema. La solución al problema se da en base a un comportamiento que es repetitivo (por lo general de cambio) lo cuál genera un patrón en la forma de solucionar el problema, lo que deduce que los patrones no fueron inventados, sino descubiertos. Se conoce como patrón de diseño porque la problemática se presenta (y debe ser atendida) en el momento en que estamos diseñando nuestro software. En esta etapa del desarrollo de software es donde surge la problemática de Cómo solucionarlo y Con qué y es donde se puede aplicar un patrón que enseñe como construir sistemas con las mejores cualidades del Diseño OO.
Como dijimos antes, los patrones son técnicas probadas y validadas que se obtuvieron a través de observar un mismo comportamiento en problemas de diseño de software y que se solucionaron dando nacimiento a un patrón que resolvió esos problemas y los cuales podemos aplicar a nuestro software. Ya existe alguien que resolvió nuestros problemas de diseño de software, ¡HURRA!.

Motivación


Así es como tu cerebro quedará con el conocimiento de patrones de diseño.

Conceptos Básicos de POO

Los conceptos básicos de POO que se utilizan para la creación de Patrones de Diseño son: Abstracción, Encampsulamiento, Herencia y Polimorfismo. Estos conceptos los puede ver en POO en Java (Conceptos).

Principios de Diseño

Veamos los principios de diseño como consejos a seguir en la elaboración de un Patrón de Diseño. Los principios de diseño son como una guía que si la seguimos no solo lograremos resolver nuestro problema con un Patrón, sino que mejoraremos nuestra forma de programar orientado a objetos, recuerde que los patrones de diseño no fueron creados, sino descubiertos y no nos proporcionan código sólo soluciones generales para resolver problemas. A lo largo de la serie de Posts iremos presentando nuevos principios de diseño, por lo pronto los siguientes son los básicos para lo que sigue.
  • Identifica los aspectos en nuestra aplicación que varían y separarlos de los que se mantienen igual. Esto es, tomar las partes que varían y encapsularlas, entonces después podemos alterar o extender las partes que varían sin afectar las que no lo hacen.
  • Programa una interfaz, no una implementación. Se refiere a programar un medio   que permita la conexión con otras clases sin tener que implementarlo.
  • Favorece la composición sobre la herencia. 

En el siguiente post veremos como aplicar los conceptos básicos de POO y los principios de diseño que hemos visto en un patrón de diseño.

Aquí la lista de los patrones de diseño que se han incluido en este blog:

Clase: Una clase describe las características de un conjunto de objetos mediante atributos y operaciones. Representa un Tipo. En Java el nombre de la clase debe ser igual al nombre del archivo en que la estamos guardando.

public class Cuenta { . . .
Cuenta.java
  • Atributo (variables miembro, variables clase): Describen el estado interno de cada objeto.
  • Operación (métodos, funciones miembro): Describen lo que se puede hacer con el objeto y los servicios que proporciona.

Objeto y composición: Un objeto es una Instancia de una clase. Representación de la clase con sus características propias. En Java la creación de objetos se hace de forma dinámica mediante la declaración de referencias de clase conectadas a la creación de objetos con el operador new que manda llamar al constructor adecuado. Es una buena práctica sobrecargar el constructor por default (vacío) para así poder crear un objeto con mínimo 2 formas distintas, una vacía y otra con la inicialización de todos los atributos o los más representativos.

Cuenta cuenta; //Creación de Referencia
cuenta = new Cuenta(); //Conectar referencia con objeto nuevo


La composición es la relación que existe entre clases mediante la referencia de objetos de una clase como miembros de otra. En java esto se representa haciendo una referencia a otra clase como parte de sus atributos viéndolo así como una relación de tiene un.

public class Cuenta{
  private long numero;
  private Movimiento movimiento;

  public Cuenta(long numero, Movimiento movimiento){ ... }
  . 
  .
  public Movimiento getMovimiento(){ ... }
  public void setMovimiento(){. . .

Encapsulamiento y Principio de Ocultación: Se refiere a la recolección de características que pueden pertenecer a una misma clase, y que están al mismo nivel de abstracción, las cuales serán ocultadas para la protección del estado interno de un objeto. En Java el principio de ocultación es representado por los Modificadores de Acceso public, private, protected. Una buena práctica es ocultar (con el modificador de acceso private) los atributos de una clase para que sólo puedan ser vistos por los miembros de la clase interna, y dejar el acceso de obtención y modificación a los Getters y Setters.

public class Cliente{
  private String nombre;
  . 
  .
  public String getNombre(){ ... }
  public void setNombre(){. . .

Herencia: Mecanismo por el cuál es posible crear una clase incorporando de manera implícita todas las características de una clase existente. Al igual que en la vida real vemos reflejada la herencia como una relación entre objetos clasificándolos de forma jerárquica por la generalización y especificación, para evitar redundancias en un mismo contexto y para reutilizar características, entre otros. 
En Java se hereda de una clase a otra con la palabra extends y todas las clases en Java heredan de la clase Object siguiendo así el paradigma al mismo lenguaje. Java provee dos tipos de abstracciones de clase que facilitan la herencia, las clases Abstractas (abstract) que son clases abstractas que brindan características especiales con carencia de implementación y que no requieren ser instanciadas por su misma naturaleza abstracta,  y las interfaces (interface) que son clases completamente abstractas que no tienen implementación, únicamente brindan estructura (operaciones, atributos static final) y si pueden ser instanciadas a diferencia de la clase abstracta, además de brindar una simulación de "herencia múltiple restringida" ya que en Java la herencia múltiple no está permitida por evidentes desventajas como la ambigüedad, mal diseño, mala eficiencia etc. Java promueve la creación de Interfaces por su sencillez.


//Herencia de una clase
public class CuentaAhorroFijo extends Cuenta{. . . 

//Herencia de una clase abstracta
public abstract class Cuenta{. . .
public class CuentaAhorroFijo extends Cuenta{. . .

//Herencia de una clase abstracta y una interfaz
public abstract class Cuenta{. . .
public interface Movimiento{. . .
public class CuentaAhorroFijo extends Cuenta, implements Movimiento{. . .

Polimorfismo (upcasting):  El polimorfismo ayudado de la herencia es la posibilidad de que una referencia a objetos de una clase pueda conectarse con objetos de descendientes de esa clase. El polimorfismo nos permite hacer una generalización buscando puntos en común a todos los objetos en un ancestro. En Java se puede implementar el polimorfismo de diferentes formas, ya sea como la asignación de una referencia hija a una padre, como el paso de parámetros a una operación que recibe parámetros de múltiples clases, permitiendo la creación de estructuras de datos que soporten objetos de distintas clases, entre otras. Se debe tomar en cuenta que al hacer polimorfismo el objeto polimórfico solo puede hacer referencia a las operaciones del objeto al que se ha conectado. También es posible hacer polimorfismo con las interfaces de java.

//Asignación ordinaria
A ra = new A();
//Asignación polimorfa
B rb = ra;
//Asignación polimorfa
B rb = new A();

Java resuelve las llamadas a funciones que suelen implementarse con objetos polimórficos, en tiempo de ejecución de manera dinámica, para garantizar siempre la llamada correcta a una función, a esto se le conoce como ligadura dinámica. 



La operación contraria al upcasting es el downcasting, y es cuando solemos necesitar recuperar el objeto original después de haber hecho una conexión polimorfa. Lo que quiere decir que en vez de hacer una generalización lo que hacemos es una especialización, sin embargo no se puede hacer un downcasting simplemente conectando una referencia como en el upcasting, para esto es necesario hacer un simple casting que especifique la clase original.

B rb = new A(); //upcasting
A ra = (A) rb;  //downcasting

Cohesión: Medida de relación funcional que existe entre las operaciones de una clase. Una operación cohesionada ejecutará una única tarea sencilla y relacionándose poco o nada con las demás operaciones de la clase. Una buena práctica es hacer operaciones altamente cohesivas, para que las operaciones sean independientes unas de otras y al momento de hacer modificaciones a una operación el cambio afecte al menor número implementaciones posibles, evitando los errores y mejorando el diseño de estructuras.

Acoplamiento: Grado de interdependencia que existe entre clases, refiriéndose a las relaciones dependientes que puede haber entre clases. Una buena práctica es tener un bajo acoplamiento para que al surgir una modificación el cambio afecte al menor número de implementaciones posibles. Esto disminuye errores y mejora el diseño de estructuras.
Un día me vi en la necesidad de clonar un proyecto de eclipse que estaba en un repositorio versionado en SVN y pasarlo a otro repositorio nuevo. Pensé de la forma más sencilla que fue tomar el directorio del proyecto copiarlo en otra carpeta, cambiarle el nombre y subirlo al repositorio debido, suena fácil ¿no?. Pero o sorpresa,  no había contemplado que al usar SVN como versionador éste se encarga de poner una carpeta oculta llamada ".svn" con los archivos correspondientes a las versiones en las que se encuentra cada archivo de cada carpeta y cada carpeta a su ves lo cuál me ocasionaría conflictos al momento de subir el proyecto al nuevo repositorio o peor aún, dejaría los archivos y directorios apuntando al otro repositorio.

¡Imaginen el problema en el que me había metido! De repente empecé a imaginarme toda la tarde entrando a cada directorio del proyecto borrando cada una de esas carpetas .svn, -¡NO! son demasiadas carpetas. Borré ese pensamiento de mi mente y comencé a pensar en la solución de un ingeniero, ¿Que haría un ingeniero en estos casos? -Tomar lo que tiene a su alrededor, utilizar su ingenio para transformarlo y convertirlo en una herramienta que le facilite su labor.

Sí eso es lo que iba a hacer, entonces me dispuse a ver lo que tenía a mi alrededor y vaya no fue difícil dar con lo que quería. Trabajar con Linux y saber su potencial te facilita muchas cosas, así que pensé, - Ya existe una función en consola que haga lo que yo quiero.

Primero pensé en el comando rm que es para remover algún directorio que deseemos, pero me hacía falta la pieza clave que era borrar todos los directorios .svn que quería y para eso debía encontrar todos y cada uno de ellos por lo que necesitaba un comando para buscar.

El comando para buscar en Linux es find que encuentra lo que le pidas que encuentre basado en una serie de propiedades que le especifican que buscar. Ya con las piezas claves me dispuse a armar el comando completo el cuál me ayudaría a cumplir mi cometido y aquí se los presento:

Remover directorios encontrados.

find . -type d -name ".svn" -exec rm -rf {} \;

Explicación:  
Con este comando estamos pidiendo que encuentre  find todos los directorios . -type d de nombre .svn -name ".svn" y que por cada unos de los directorios encontrados ejecute el comando de remover directorio de manera recursiva y sin preguntar si deseas borrarlo -exec rm -rf {}. Las llaves son las que indican que se tiene que ejecutar el comando por cada archivo encontrado y  \; simplemente indican que se termina la instrucción que se debe ejecutar, como ven el ; debe escaparse con la \.

Problema solucionado!

Espero no se tomen muy a pecho lo que digo sobre Linux, Fedora u otra cosa en específico, lo que comento son cosas que uso porque son de mis gustos y si otras personas difieren en gustos porque les gusta Windows o Mac, otras Distros y otra cosa es completamente Válido y respetable como lo mío.

Saludos!
Necesitando un día hacer un strip de caracteres de un String fui a dar con la novedad, para mi obviamente, de que en Java 6 existe la clase Normalizer en el paquete java.text la cuál nos brinda como dice el Java doc un método normalize el cuál transforma texto Unicode en su forma equivalente compuesta o decompuesta, que nos facilita la clasificación y búsqueda de texto, ó en mi caso un strip de caracteres o DeAccent.

Para fines prácticos, el método normalize transforma el texto Unicode que nosotros le enviemos en texto normalizado o bien, texto bajo una misma norma estándar, basado en la estandarización de normalización Unicode descrita en  Unicode Standard Annex #15 — Unicode Normalization Forms.

Esto es que como bien sabemos no estamos solos en este planeta, existen miles de personas más que usan computadora y tienen su propia forma de escribir, con sus acentuaciones, símbolos y demás. Es por eso que fue necesaria una estandarización de texto Unicode que normalizara el texto para ponerlo todo en un mismo contexto. Una palabra acentuada Día es normalizada (decompuesta) a Di'a, como ven la letra con acentuación fue separada, por lo que al tener el acento como un caracter separado es muy fácil eliminarlo.

Ejemp: Imagine que usted tiene que hacer un buscador de texto en un sitio de libros, el cuál debe permitir buscar texto libre, total y parcialmente el texto que el usuario vaya a teclear. ¿De que forma podría usted encontrar palabras acentuadas o simbolizadas? Lo primero que se me viene a la mente es que si no tuvieran acentos entonces no sería un problema, y por consiguiente necesito quitar acentos en las palabras a buscar y la biblioteca de palabras en las que lo haré. Ahora, ¿De que forma puedo quitar acentos  a esas palabras? -Normalización Unicode.
Veamos el ejemplo:


public String stripAccents(String strToStrip){
   String strStripped = null;
   //Normalizamos en la forma NFD (Canonical decomposition)
   strToStrip = Normalizer.normalize(strToStrip, Normalizer.Form.NFD);
   //Reemplazamos los acentos con una una expresión regular de Bloque Unicode
   strStripped = strToStrip.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
   
   return strStripped;
}

La forma de normalización que usamos es la llamada Canonical decomposition la cuál descompone en forma canónica en la que los caracteres están ordenados en un orden específico. Esto lo puedes ver en Normalizer.Form.

La expresión regular que usamos "\p{InCombiningDiacriticalMarks}" es una propiedad de bloque Unicode la cual engloba en un rango de caracteres diacríticos y lo reemplazamos por "" vacío para eliminar ese acento.

Problema resuelto! Es lo que yo usé más sin embargo no descarto y exista una mejor forma de hacerlo. Comenten si tienen una mejor forma de hacerlo o cualquier duda o corrección o sugerencia que tengan.
08 Enero 2013, Guadalajara, Jalisco, Mex.

A Quien Corresponda:

Decidí que es tiempo de desempolvar mi cerebro y dejarlo hacer algo de lo que más le gusta, retomando todo lo referente a Código no importando el Lenguaje, SO, Framework, Paradigma, Sintaxis  Semántica, Algoritmia, Patrón, Diseño, Tool, API, Corriente, Teoría, Religión, Sexo, Raza, o cualquier rama de la Ingeniería en Sistemas Computacionales existente. 

Aquí verán reflejada parte de mi Alma ya que sin creer en la reencarnación y hablando hipotéticamente "en mi otra vida debí ser lo mismo que soy ahora Software Developer, Ingeniero por supuesto", y no quiero sonar despectiva con mi comentario, es simplemente que realmente me gusta lo que hago así como a otros lo que hacen. El ser Ingeniero me ha abierto las puertas a mundos que no conocía y me a hecho descubrir cosas de mi que no sabía que podía hacer y es por eso que Halago mi profesión, y no es ningún misticismo racial hacia otras profesiones.

El contenido que aquí encuentre espero sea de su completo agrado y pueda ayudarlo a incrementar su conocimiento. Por supuesto es completamente ABIERTO, puede usarlo, compartirlo, comentarlo, recomendarlo, cuestionarlo, reforzarlo, Copy/Paste-arlo, y cualquier cosa que se lo ocurra siempre y cuando no vaya en contra de la ética profesional, lo siento pero me enseñaron a tener ética, valores y moral así que en esa parte se van a tener que aguantar. Estoy abierta a cualquier comentario, sugerencia, corrección o duda que tengan, y si no sé algo de lo que me pregunten pues lo investigaré hasta que no le encuentre solución y lo invente que para eso somos ingenieros ChingaO **JOKE**. Siempre trataré de darle solución a su problema y si no puedo pues seré sincera y se los diré, tal vez entre los lectores exista alguien que tenga la solución.

En caso de que alguien desee aportar algo, hágamelo saber para organizar y revisar los aportes y con gusto les daré el crédito que merecen en el Blog de esta humilde servidora.

Por último, a las personas con poco valor objetivo, falta de argumentos, orgullosa, prejuiciosa y egoísta, les solicito se abstengan de comentar, no pienso discutir ningún argumento carente de objetividad y provocador. Respeto la forma de pensar de las demás personas, pero ese tipo de comentarios no van con el fin de este Blog por lo que advierto no serán contestados. De igual forma pueden exponerse y evidenciarse ustedes mismos sin necesidad de que otros o yo lo hagamos. Que conste que yo advertí!

Les pido estén al pendiente del Blog ya que mi propósito es darle uso y compartirles lo que aprendo con el día a día. Habrá cosas que ya sé y otras que esté aprendiendo pero siempre será con el mejor de los propósitos y es compartir.

Dados a conocer los puntos deseados les doy una cordial ...

B I E N V E N I D A

Categories

Seguidores

MarceStarlet. Con la tecnología de Blogger.
Powered By Blogger