Showing posts with label Design patterns. Show all posts
Showing posts with label Design patterns. Show all posts

Sunday, 31 May 2009

Diseño orientado a interfaces (parte I)

Las interfaces surgen como una evolución de la Programación Orientada a Objetos con la necesidad de agrupar y reutilizar las distintas funcionalidades de un objeto en una interfaz más manejable. El diseño Orientado a interfaces pretende que el desarrollo del software genere implementaciones de programas bien estructurados. Mediante las interfaces, podremos crear mejores diseños sin basarnos tanto en la POO. Podemos encontrar una buena explicación sobre este tipo de programación en el libro Interface-OrientedDesign , donde Ken pugh nos hace una muy buena argumentación del porqué debemos utilizar mas las iterfaces para mejorar nuestro diseño y evitar los anti-patrones de diseño sobre OO como por ejemplo utilizar demasiado la herencia, fuerte acoplamiento, etc. La lista de los anti-patrones la podéis encontrar en la wikipedia. Una de las cosas que más me ha gustado sobre el libro, es el capítulo sobre los contratos de las interfaces y sobre las 3 leyes que deben cumplir las interfaces. Estas 3 leyes se basan en las 3 leyes de la robótica por Isaac Asimov (si recordáis la película Yo, Robot, allí se mencionaban). Estas 3 leyes son las siguientes:

  1. Un robot no puede hacer daño a un ser humano o, por su inacción, permitir que un ser humano sufra daño.
  2. Un robot debe obedecer las órdenes dadas por los seres humanos, excepto si estas órdenes entrasen en conflicto con la Primera Ley.
  3. Un robot debe proteger su propia existencia en la medida en que esta protección no entre en conflicto con la Primera o la Segunda Ley.
Bien, como se comentan en estas 3 leyes, algo parecido le ocurre a las interfaces, donde el autor comenta:
1. La implementación de una interfaz debe hacer lo que sus métodos dicen que hacen.
Esta ley indica que los nombres de los métodos deben corresponder a la acción que hacen, y que cada método debe devolver un valor que indique si la operación ha tenido éxito o si al contrario hay error.
2. Una interfaz no debe interferir otros módulos de un programa o con otros programas.
En este caso, se expone que una interfaz no debe utilizar recursos de otros módulos, es decir si uno de los propósitos de la interfaz es leer un dato de un fichero, no necesita una conexión a una base de datos.
3. Si una implementación no es capaz de realizar su responsabilidad, debe notificar a quien lo llamó.
La implementación debe reportar siempre el problema que encuentra, si no es capaz de realizar la acción, debe informar a su creador o invocador e informarle del problema mediante un código de error o un estado.

La verdad es que este tipo de diseño, abre un nuevo camino a explorar y sobretodo permite comprobar si el diseño de nuestras aplicaciones es correcto o no desde el punto del aprovechamiento de las propiedades de la OO, sabiendo aplicar correctamente la herencia, el polimorfismo, etc.

En un segundo post, pondré varios ejemplos utilizando las interfaces con los diferentes patrones de diseño que se utilizan.

Friday, 29 May 2009

Refactoring

Hace tiempo que me preguntan que es todo este tema del Refactoring y aquí hago una pequeña explicación de lo que es. También os recomiendo el libro "Refactoring -> Improving the Design of Existing code" que lo explica muy bien. Está escrito por Martin Fowler, y ya tengo varios de sus libros en mis estanterías, así que os recomiendo su lectura, al igual que el que comenté en su día "Patterns of Enterprise Application Architecture (Addison-Wesley Signature Series)". El tema del Refactoring, es una técnica que se utiliza en la ingenieria del software para reestructurar el código fuente, alterando su estructura interna, sin cambiar su comportamiento externo. Por lo tanto hacer que el código sea más fácil de entender y extender. Evitamos soluciones Quick & Dirty i mejoramos el código sin cambiar la funcionalidad. Para aplicar Refactoring, no consiste ir formateando el código para que quede más bonito, consiste en analizar muy bien el código e ir encontrando patrones dentro de lo que escribimos, es decir encontrar lo que llamamos "Bad Smells in code".

Los ejemplos que se me ocurren ahora són por ejemplo el Shotgun Surgery y la envidia de capacidades. El shotgun Surgery por ejemplo consiste en que si tenemos que modificar algo, tenemos que hacer lo mismo en N clases, y por lo tanto puede ser que algún día se nos olvide hacerlo, con el consiguiente fallo. Y la envidia de capacidades consiste en que si tenemos una clase que accede mucho a los métodos de otra clase, a lo mejor es que tiene mucha envidia, y realmente esos métodos tendrían que ir en la primera clase.

En los enlaces de interés encontrareis buenos resúmenes sobre los "Code smell", pero simplemente consiste en tenerlos muy claros, y saber identificarlos. Los más comunes por ejemplo Data Clumps, Switch, Clase perezosa y Comentarios.

Data Clumps: Consiste en que si siempre pasamos los mismos 4 argumentos a nuestra función, a lo mejor es que hay una relación más estrecha y necesitamos generar un tipo de datos.

Switch: La POO es una ataque al "case". La Programación estructurada no soporta el polimorfismo, y se pueden reemplazar por tipos con métodos virtuales. El uso de Switch es un sintoma de que no estoy aprovechando el polimorfismo.

Clase perezosa: Es una clase que no hace nada, que no tiene comportamiento. A lo mejor sus métodos están en otras clases y a lo mejor las otras clases están padeciendo envidia de capacidades????. Esto es un síntoma de que algo no va bien.

Comentarios: Poner el comentario que es un candidato a una función, crea la función!. A lo mejor crear comentarios puede ser que nuestro código no sea tan bueno. Hay que comentar el propósito de las cosas, no comentar lo que hacer el código porque eso ya se puede leer en él. Hay que evitar hacer cosas redundantes y sobretodo el DRY.

Algunas categorías de refactorings:

Simplificar llamadas a métodos, de esta manera conseguimos que se pueda leer mejor el código. Análisis intuitivo y que cada objeto tenga su rol y seguir el diálogo entre objetos. Crear métodos deprecated, y sobretodo tener en cuenta que el Refactoring no es cambiar el código. Como podéis ver hay toda una filosofía detrás de la refactorización de código, y podréis encontrar muchos ejemplos ilustrados en el libro de Martin fowler.

  • Enlaces de interés:
http://sourcemaking.com/refactoring
http://es.debugmodeon.com/articulo/categorizacion-de-code-smells