Ya sea que seas un desarrollador de software experimentado o que a penas comiences tus primeros pasos en este apasionante mundo, seguramente en más de una ocasión te toparás con el término "patrones de diseño". O si no lo has escuchado como tal, seguramente ya estás usando alguno sin darte cuenta.
Los patrones de diseño son una de las herramientas más útiles que deben encontrarse en el arsenal de todo programador. Y si bien hay bastantes patrones distintos, no está de más que todo desarrollador conozca, al menos, los más utilizados.
¿Qué son los patrones de diseño?
Los patrones de diseño fueron definidos por primera vez por Christopher Alexander en 1977 de la siguiente forma:
Un patrón describe un problema que ocurre una y otra vez en nuestro entorno, y luego procede a describir la esencia de la solución a dicho problema de un modo tal que uno puede utilizar la solución un millón de veces, pero sin aplicarla dos veces de la misma manera.
Lo interesante de la definición anterior es que Alexander no está hablando sobre diseño de software sino sobre arquitectura (como en la construcción de edificios, casas, puentes, etc.). Tomemos un momento para analizar la definición a fin de comprender su significado.
Un patrón describe un problema que ocurre una y otra vez en nuestro entorno...
En el desarrollo de software, sin importar la aplicación que estemos desarrollando, siempre nos encontramos con la misma clase de problemas: tal vez necesitamos recibir una notificación cuando un proceso termine (como cuando se completa una llamada asíncrona), o tal vez necesitemos ser notificados cuando el estado de una propiedad particular cambie. Tal vez tenemos una API compleja que queremos compartir con otros desarrolladores, pero deseamos que sea fácil interactuar con ella, de modo que no se necesiten comprender los detalles complejos de dicha API. Tal vez queremos añadir funcionalidades aun objeto existente aún cuando no tenemos el código fuente de dicho objeto o somos incapaces de heredarlo (como en el caso de las clases selladas en C#). Tal vez queramos recorrer los elementos de una colección de modo que podamos mostrarlos o realizar alguna otra acción sobre ellos. Estos son sólo algunos de los problemas comunes con los que nos encontramos al desarrollar software, pero puede haber muchísimos más.
...y luego procede a describir la esencia de la solución a dicho problema...
Los patrones de diseño no nos dan una implementación específica, sino que nos describen simplemente las partes que debe incluir una solución y la interacción entre ellas. En otras palabras, son sólo el esqueleto de la solución a problemas comunes en el desarrollo de software. Los patrones de diseño, pues, brindan una solución ya probada y documentada a problemas de desarrollo de software que están sujetos a contextos similares.
...de un modo tal que uno puede utilizar la solución un millón de veces, pero sin aplicarla dos veces de la misma manera.
Este es un aspecto importante de los patrones de diseño: nosotros elegimos cómo implementarlos. Los patrones son conceptuales en naturaleza, por lo que su implementación concreta depende de la necesidad particular que queramos resolver. Por ejemplo, en el mundo de la arquitectura podemos tener un problema común: la necesidad de colocar un techo sobre un espacio abierto. Para resolverlo, podemos contar con diferentes patrones de techo: abovedado, con arcos, plano, de dos aguas, etc. Y cuando vamos a cada uno de estos patrones, podemos encontrarnos con aplicaciones más especificas para cada uno; por ejemplo, si elegimos el techo de dos aguas, este puede ser piramidal, en forma de cruz, con capo, etc. Y aún cuando seleccionemos uno de estos patrones, no tenemos todavía una implementación particular del mismo, como las consideraciones sobre la superficie a cubrir, los materiales a usar, los ángulos en los que se levantarán los techos, etc. Dada su naturaleza conceptual, los patrones de diseño serán interpretados e implementados de manera diferente por personas diferentes. No hay ningún problema en ello, pues los patrones sólo nos muestran la esencia de la solución y no sus detalles particulares.
Partes de un patrón de diseño.
Los patrones de diseño se encuentran descritos usualmente en catálogos, libros y artículos especiales sobre el tema y siempre poseen varios elementos en comun:
- Nombre del patrón. Este es el nombre particular con el cual se identifica al patrón en las conversaciones entre desarrolladores. Algunos ejemplos de nombres de patrones de diseño son: Fábrica abstracta (Abstract Factory), Método de Fabricación (Factory Method), Fachada (Facade), Observador (Observer), Singleton, Cadena de Responsabilidad (Chain of Responsibility) entre muchos otros.
- Descripción del problema. Como descubrimos en la definición de Alexander, existen problemas comunes en el desarrollo de software con los que nos toparemos en más de una ocasión, y en esta parte del patrón se define dicho problema a detalle.
- Solución al problema. Consiste en la descripción de los elementos que conforman el diseño de la solución incluyendo las relaciones entre ellos, sus responsabilidades y la forma en que colaboran entre si para resolver el problema. Recordemos que esta es sólo la esencia de la solución y no una implementación concreta. Le toca al desarrollador determinar qué implementación es la más apropiada para un problema específico.
- Consecuencias. Cada patrón tiene un costo, el cual es frecuentemente ignorado. Como desarrolladores acostumbramos hablar de las ventajas de un patrón en particular y de cómo representa la solución perfecta a un problema. Pero la realidad es que cada beneficio tiene un costo asociado. Cuando se trata de patrones de diseño, el costo suele ser un incremento en la complejidad de nuestro código. Debemos conocer bien las consecuencias de un patrón para sopesarlas cuidadosamente contra los beneficios de su implementación.
Clasificación de los patrones de diseño
Dado que el desarrollo de software es una disciplina que se encuentra en constante evolución, existen muchos patrones de diseño distintos que se aplican a distintos problemas comunes. Sin embargo y a pesar de su diversidad, los patrones de diseño pueden clasificarse en tres grandes grupos:
- Patrones creacionales: Tratan sobre la mejor forma de instanciar, inicializar y configurar objetos en una aplicación.
- Patrones estructurales: Se utilizan para separar la interfaz de la implementación. Se ocupan de cómo las clases y objetos se agrupan, para formar estructuras más grandes.
- Patrones de comportamiento: Se usan para definir cómo las clases y los objetos interactúan entre ellos.
Esta clasificación aparece por primera vez en el libro
Design Patterns: Elements of Reusable Object-Oriented Software, escrito en 1994 por un grupo de autores conocidos como
The Gang of Four: Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides. Este libro se ha convertido en el referente obligado sobre el tema y permanece vigente hasta hoy, por lo que debería formar parte de la biblioteca personal de cualquier desarrollador de software.
¿Por qué usar patrones de diseño?
Existen varias razones por las cuales un desarrollador debe aprender, comprender e implementar el uso de los patrones de diseño en su práctica diaria de escritura de código:
- Los patrones de diseño son soluciones probadas. Alguien más listo que nosotros ya analizó el problema y desarrolló una solución. No hay necesidad de que reinventemos la rueda. Lo mejor que podemos hacer es comenzar con la solución de alguien más y ajustarla a las necesidades específicas de nuestra aplicación.
- Los patrones de diseño nos proveen un vocabulario común. Todas las profesiones poseen términos especializados que emplean para comunicar conceptos específicos entre especialistas. Los patrones de diseño le dan a los desarrolladores de software esa misma clase de lenguaje especializado. Un vocabulario común nos permite usar lenguaje preciso cuando nos comunicamos con otros desarrolladores.
- Hablar de patrones de diseño anima a otros desarrolladores a investigar y aprender sobre el tema. Después de todo, si un desarrollador escucha a otros hablando sobre el patrón de fachada y cómo resultó ser una buena solución para una aplicación particular, entonces dicho desarrollador probablemente será lo suficientemente curioso como para averiguar qué es ese patrón y por qué es tan bueno. Esto ayuda a difundir el uso de los patrones de diseño en nuestra industria y, por lo tanto, a mejorar la calidad del software que construimos.
En conclusión
El uso de patrones de diseño nos ayudará a estandarizar nuestro código de modo que sea más entendible para otros programadores (y aún para nosotros mismos). Si nunca has usado patrones de diseño, es hora de comenzar a hacerlo.
Enlaces