Gracias a las últimas versiones de PHP, el lenguaje esta evolucionando por un buen camino y así también, la comunidad. Cada vez más desarrolladores PHP se encuentran interesados por las buenas prácticas, investigando que son las patrones de diseño y aplicando test automatizados a sus desarrollos. Es algo que me emociona mucho!
Para todos esos desarrolladores que quieren mejorar día a día la calidad de su código, les traigo una serie de artículos que iré publicando sobre los Patrones GRASP.
Estos patrones son de suma importancia y no son tan populares como lo pueden ser otros como Facade, Repository, Strategy o los mismos principios SOLID. Así que acá les van!
¿Qué son los patrones GRASP?
Así como existen los patrones de comportamiento (Strategy, State, etc.), los patrones de creación (Factory Method, Abstract Factory, etc.) y los patrones estructurales (Facade, Decorator, etc.), existen los patrones de asignación de responsabilidades. Este conjunto de patrones se los llama GRASP por sus siglas en ingles General Responsibility Assignment Software Patterns.
Estos patrones se mencionaron por primera vez en el libro Uml y Patrones de Craig Larman (¡libro que recomiendo mucho!) y nos ayudan a identificar qué responsabilidad deben tener las clases de nuestro sistema y no caer en clases super gordas o clases super anémicas.
Si alguna vez usaste algún un framework moderno de PHP como Laravel, Symfony, etc., seguramente usaste los patrones GRASP sin darte cuenta y también seguramente violaste alguno de sus principios 😱, ya te darás cuenta por que.
Los cinco patrones GRASP
GRASP se compone de varios patrones pero en esta primera serie de publicación vamos a ver los cinco patrones básicos pero altamente importantes:
- Experto en información (o Experto)
- Alta Cohesión.
- Bajo Acoplamiento.
- Creador.
- Controlador.
Patrón Experto en información
Empecemos con el primero de la lista, el patrón Experto en información o simplemente Experto. Este patrón nos dice que la responsabilidad de hacer una acción debe ser asignada a la clase que tiene la información necesaria para realizar dicha acción.
Puede marear a la primera leída pero es algo muy simple y con un ejemplo se va a entender mejor.
Supongamos que tenemos un ecommerce y queremos calcular el precio total de una venta. Para esto tenemos un controlador llamado VentaController
que recibe el id de la venta. También tenemos una clase Venta
que a su vez contiene una colección de clases LineaDeVenta
. Esta clase LineaDeVenta
contiene el producto vendido, el precio y la cantidad que se vendieron. El diagrama UML sería así:
Entonces, imaginemos que desde el navegador recibimos una request con el id de la venta a nuestro controlador, ¿qué clase debería tener la responsabilidad de calcular el total? ¿cómo lo harías vos?
Normalmente veo que los desarrolladores Laravel lo resuelven así:
Pero acá no estaríamos aplicando el patrón Experto porque le estamos asignando la responsabilidad de calcular el total a la clase VentaController
y, según el patrón Experto, no es la clase más indicada para realizar esta acción porque no contiene la información necesaria para dicha acción.
Entonces ¿qué clase debería tener la responsabilidad de calcular el total?. La respuesta es la clase Venta
. Veamos cómo quedaría el ejemplo anterior.
Esta es la forma correcta porque la clase Venta tiene la información de sus lineas de venta pero… ¿se dieron cuenta? estamos usando las propiedades de la linea de venta para calcular el subtotal y sumarlo al total. Esto no es correcto según el patrón Experto. Veamos la versión final.
Ahora sí se aplico el patrón Experto en información correctamente ya que cada clase hace uso de sus propiedades para realizar la acción.
Beneficios
- Reutilización de código: ya que ahora podemos usar
total()
en distintos lugares. - Evitamos repetición de código: ¿qué hubiera pasado si dejábamos el código como la primer imagen y luego necesitaríamos calcular el total en otro controlador? Seguramente caeríamos en la repetición de código. Pero aplicando el patrón Experto el «como se calcula el total de una venta» ahora existe en un solo lugar.
- Se mantiene el encapsulamiento de la información, ya que los objetos utilizan su propia información para llevar a cabo la acción.
- Se distribuye el comportamiento entre las clases, lo que lleva a clases más cohesivas (ya veremos que es esto) y «ligeras» que son más fáciles de entender y mantener.
¿Eloquent viola el patrón Experto?
Según el patrón Experto, dijimos que la clase más adecuada para hacer alguna acción, debe ser la clase que contiene la información más certera para hacer dicha acción… pero ¿qué pasa con las acciones de persistencia? ¿qué clase es la más adecuada para guardar la información de una Venta
en la base de datos?
Es una buena pregunta que merece su propio post así que voy a crear un hilo en Twitter donde hablare sobre esto. Te invito a seguirme en mi twitter 👉 @MatyByMaty
Conclusión
Sin dudas el patrón Experto en Información es de gran ayuda para diseñar mejor código. En próximas publicaciones seguiremos con el resto de los patrones GRASP donde te prometo que tu código va a pasar al próximo nivel. 🚀
No te olvides de seguirme en Twitter, comentar que te ha parecido este patrón y compartir el artículo si te ha gustado. Nos vemos en la próxima.
Excelente post
Muchas gracias Martín!
Muy bien bajado ese balón. Gracias.
Muchas gracias Alberto.
continuaras con los otros patrones?
Hola Alberto, me gustaría pero por el momento estoy muy corto de tiempo :/
Cuando puedo retomare los artículos ✊
No he dormido esperando la segunda parte. 🤓
PD: Excelente contenido
Muchas gracias!
Estuve bastante ocupado pero espero sacarla pronto.
Genial, gracias por el post!!!
Atendiendo al libro de larman no son cinco patrones son 9: Experto en la información, Creador, Alta cohesión, Bajo acoplamiento, Controlador, Polimorfismo, Indirection (esto no se como traducirlo), Fabricación pura, Variaciones protejidas.