Durante las últimas semanas he estado trabajando bastante en el curso de Patrones de Diseño con PHP para Styde, lo que me ha permitido completar varias lecciones sobre los patrones Strategy, Observer, Decorator y Template Method las cuales he sumado a las lecciones sobre Composite y Builder para un total de 25 lecciones en 4 horas y media de contenido hasta ahora. En este post quiero hablarte sobre los diferentes aspectos y recursos que he tomado en cuenta para preparar el contenido.
El curso de Patrones de Diseño es uno de los que más trabajo me ha costado producir; aunque la mayoría de estos patrones los he estudiado y utilizado a lo largo de mi carrera, explicarlos requiere un conocimiento más detallado de las matices de cada uno así como su adaptación al lenguaje PHP.
Sin embargo, para ayudarte a adaptar y utilizar estos patrones en tus proyectos sin importar si estás trabajando con Legacy Code o no, me he puesto como objetivo enseñarte cómo refactorizar código escrito con lógica estructurada hasta la aplicación del patrón con sus principios de programación orientada a objetos.
Para refactorizar es muy conveniente que apoyes tu código en pruebas unitarias, de lo contrario cada cambio que realices puede dañar el comportamiento del sistema de manera inesperada y lo peor de esto es que puedes no darte cuenta de que has cometido un error o darte cuenta demasiado tarde, luego de haber editado decenas de archivos y cientos de líneas de código o, peor aún, luego de haber puesto el sistema en producción.
Muchos programadores creen que la gran mayoría del tiempo la pasamos escribiendo código, pero en realidad programar está mucho más asociado a pensar, analizar y descubrir problemas que a golpear el teclado, y la gran mayoría del tiempo -si no me crees puedes medirlo por ti mismo- la pasamos leyendo código y depurando nuestra aplicación.
Por ejemplo, si trabajas sin pruebas quizás puedas hacer varios cambios en el código en poco tiempo y creer que estás progresando sin que nada te detenga. Pero eventualmente encontrarás un problema y tendrás que regresar en el tiempo, revisar cada cambio que has hecho, tratando de descubrir qué salió mal, cuándo y cómo corregirlo. A continuación aplicarás una solución pero un par de días después te darás cuenta que has dañado algo más, pero no sabes qué, ni porqué y así sucesivamente. Todos hemos pasado por esta situación y la idea de escribir pruebas unitarias, de integración, funcionales, etc. es disminuir al máximo estos escenarios, puesto que si has escrito pruebas de forma correcta y cometes un error, una de las pruebas te avisará casi de inmediato lo que sucede en el código, por lo que resultará mucho más fácil detectar dónde se produjo el error (por ejemplo, en el último cambio que hiciste), así como prevenir subir dicho error a producción.
Refactorizar también significa trabajar con cambios pequeños, ejecutando las pruebas luego de cada paso (visualiza una persona escalando una montaña un paso a la vez), nuevamente con el objetivo de prevenir llegar a una situación donde has dañado el sistema y no sabes cómo ni cuándo.
Aunque refactorizar equivale a hacer cambios para mejorar la calidad del código de manera que sea más fácil entenderlo, reutilizarlo, cambiarlo o extenderlo, muchas veces decimos que vamos a refactorizar cuando en realidad nuestra intención es agregar funcionalidad adicional al código. Por lo tanto resulta muy importante entender que: refactorizar y agregar funcionalidad son dos procesos diferentes y como tal deberían ser realizados en momentos diferentes. Aunque quieras o debas refactorizar para poder agregar nuevas funcionalidades, debes primero hacer todos los cambios que permitan agregar la nueva funcionalidad y luego agregar dicha funcionalidad, no al revés ni al mismo tiempo.
Cuando refactorizas por lo tanto no debes escribir pruebas nuevas ni hacer cambios en las pruebas ya existentes, al menos que estos cambios estén estrechamente ligados al proceso de refactorización como tal y sean inevitables, por ejemplo si renombras un método público invocado en las pruebas tendrás que proceder a modificar la prueba como tal.
Así que, aún partiendo desde cero, en algún momento en la vida de tu sistema tendrás que refactorizar para aplicar un patrón de diseño que te permita reorganizar el código y extender la funcionalidad del sistema de manera ordenada.
Es por ello que decidí explicar Técnicas de Refactorización en el Curso de Patrones de Diseño así como cubrir lo explicado con pruebas unitarias, para brindarte un escenario más real y profesional de trabajo, en vez de limitarme a los típicos ejemplos que imprimen texto con echo
o var_dump
pero te dejan solo a la hora de implementar los patrones en tus proyectos de desarrollo.
Hablando de echo
y var_dump
, en el curso de patrones de diseño busco plasmar ejemplos como la generación de estructuras de HTML, el envío de correos electrónicos o la manipulación de imágenes, entre otros, con el objetivo de mostrar la aplicación de estos patrones en escenarios más reales. Aunque esto en sí mismo trae sus propios desafíos, puesto que tengo que hacer el ejemplo lo suficientemente complejo para que pueda representar un escenario real pero lo suficientemente sencillo para explicar el patrón en una hora o menos sin alejarme de la teoría del patrón como tal.
Con respecto a la teoría, cada patrón está rodeado de mucha teoría y aunque las lecciones de Styde son bien prácticas y tienen mucho código, encontrarás un resumen de dicha teoría con notas adaptadas a PHP al finalizar cada lección. Por lo tanto, podrás leer texto sobre:
- Aplicación: cuando usar el patrón
- Participantes: qué clases e interfaces se definen
- Interacción entre los participantes: cómo trabajan unas clases con otras
- Beneficios y contras: aunque aplicar patrones es muy útil, estos pueden complicar el diseño de tu aplicación si lo usas de manera incorrecta o innecesaria.
Todo esto lo estoy haciendo para darte una perspectiva mucho más amplia sobre el uso de patrones de diseño en PHP y ampliar muchos de los conocimientos y principios vistos en el Curso de Programación Orientada a Objetos. Por último debo mencionar que al ver el curso sobre patrones también estarás aprendiendo algunos principios SOLID, aunque más adelante planeo dedicar una serie en particular sobre SOLID, algunos principios como el Single Responsability Principle o el Open Close Principle son cubiertos al aplicar algunos de los patrones como Decorator, por lo tanto los menciono según sea el caso.
En resumen, el Curso de Patrones de Diseño está cargado de muchos principios de programación orientada a objetos, pruebas unitarias, técnicas de refactorización y, por supuesto, patrones de diseño, todo con ejemplos muy prácticos y resúmenes teóricos. Espero que si lo estás viendo lo estés disfrutando y si aún no lo has visto te animes a hacerlo.
Si quieres aprender más sobre Patrones de Diseño te recomiendo también las siguientes obras, sobre las cuales me estoy apoyando para preparar este curso, mucho de los ejemplos están escrito en C, JAVA y hasta en UML pero son fáciles de entender:
- Design Patterns (Gang of Four)
- Refactoring to Patterns, Joshua Kerievsky
- Refactoring, Martin Fowler (edición en JAVA)
- PHP Objects, Patterns, and Practice (Matt Zandstra)
¿Cuáles patrones te gustaría aprender a continuación?
Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.