Desde Laravel Tip insistimos en que es importante aprender y aplicar los Principios SOLID siempre que sea posible. Te aseguramos que te harán un mejor programador y crearas software de mayor calidad. Por este motivo, vamos a repasar cada uno de estos conceptos aplicándolos a Laravel para que se entienda fácilmente.
Introducción: ¿Qué son los Principios SOLID?
Los principios SOLID son conceptos introducidos por Robert C. Martin en el año 2000 y son un grupo de cinco principios definidos por distintos autores, gurúes de la programación y el desarrollo de Software. Son muy importantes para crear software de calidad y están muy relacionados con los patrones de diseño, en especial, con la alta cohesión y el bajo acoplamiento.
Nos permite desarrollar sistemas fáciles de mantener, eliminando código sucio y ampliar las funcionalidades fácilmente sin hacer grandes modificaciones al código existente. Cabe decir, que los Principios SOLID se pueden aplicar a cualquier lenguaje de programación orientado a objetos, no es algo de Laravel o PHP.
S.O.L.I.D. es un acrónimo donde cada letra es un concepto. Veamos cada uno de ellos aplicados con ejemplos en Laravel.
S – Principio de responsabilidad única (Single Responsibility Principle)
El Principio de Responsabilidad Única (SRP) es la S del Principio SOLID y nos dice que una clase debe ser responsable de una única cosa.
Tal vez esto lo hayas escuchado varias veces pero, ¿qué significa que una clase tenga una única responsabilidad? ¡Con este ejemplo en Laravel lo vas a entender fácilmente!
Las clases FormRequest que nos brinda Laravel, son un claro ejemplo de principio de responsabilidad única donde estamos separando la responsabilidad de validar los datos a otra clase.
Ejemplo del Principio de Responsabilidad Única en Laravel
Veamos un ejemplo más completo. En la siguiente imagen tenemos un controlador donde podemos ver un método store()
que tiene mas de una responsabilidad:
Como sabemos, los métodos de las clases Controllers existen para recibir una solicitud, delegar la misma según el método (en este caso store) y brindar una respuesta al cliente. Esa es la responsabilidad de los controladores. Pero en esta imagen estamos viendo que el método tiene responsabilidades que no le competen a la clase Controller, como la validación de datos, la encripción de la contraseña y el guardado en la base de datos.
Veamos como sería el mismo ejemplo aplicando la S de SOLID:
- Primero, creamos una clase de tipo FormRequest que tendrá la responsabilidad de todo lo que tenga que ver con la validación de datos.
- Segundo, creamos una clase encargada de comunicarse con las clases del ORM de Laravel. Le puse de nombre Repositorio, pero no es un repositorio como tal pero sirve para el ejemplo.
Además, la encriptación de la contraseña podríamos ponerla en otra clase de tipo Mutator 😉.
- Ahora veamos como queda nuestro controlador.
Beneficios del Principio de Responsabilidad Única
Los beneficios del principio de responsabilidad única son varios. A parte de brindarnos un controlador más limpio y legible, podemos enumerar los siguientes beneficios:
- Cada clase se encarga de lo suyo.
- Hay un lugar para todo y todo esta en su lugar.
- Nombres más específicos para las clases.
- Mayor facilidad para atacar el código con pruebas.
O – Principio de Abierto/Cerrado (Open/closed principle)
El Principio de Abierto/Cerrado (OCP) establece que una clase (método o función) debe quedar abierta para extender su funcionalidad pero sin agregar o modificar su código… 🤔.
Parece raro querer agregar nueva funcionalidad a una clase pero sin agregar o modificar código fuente, no? Pero no es así! Gracias a la herencia y a las interfaces que nos provee la programación orientada a objetos.
Ejemplo del Principio de Abierto/Cerrado en Laravel
¿Cuándo debemos tener este principio en cuenta? Un caso muy común es cuando tenemos un switch()
, donde cada case
realiza una acción diferente y existe la posibilidad que en un futuro sigamos agregando más casos al switch. Veamos el siguiente ejemplo.
Aquí tenemos un controlador con un método pay()
, el cual se encarga de recibir el tipo de pago por medio de la solicitud y, según dicho tipo, el pago será procesado por medio de uno u otro método que se encuentran en la clase Payment
.
Pero ahora bien, acá tenemos dos grandes problemas.
Primero, que deberíamos agregar un case
mas por cada nuevo pago que aceptemos o eliminar un case en el caso que no aceptemos mas pagos por PayPal.
Segundo, que todos los métodos que procesan los distintos tipos de pagos, se encuentran en una única clase, la clase Payment. Por lo tanto, cuando agreguemos un nuevo tipo de pago (o quitemos), deberíamos editar la clase Payment, y como dice el principio de Abierto/Cerrado, esto no es lo ideal.
¿Cómo aplicamos el Principio de Abierto/Cerrado? Muy fácil, con interfaces.
- Creamos una interfaz con el método
pay()
. - Luego creamos una clase por cada tipo de pago e implementamos la interfaz anteriormente creada.
- Por último, escribimos el código del método
pay()
implementando la lógica necesaria, según la clase.
Ahora que ya tenemos una clase por cada tipo de pago, vamos a ver como nos quedaría el controlador.
Como podemos ver, estoy utilizando una clase de tipo Factoria para que se encargue de crear la clase correspondiente, según el tipo de pago. Aclaro que la clase factoria no es necesaria (o se podría reemplazar por otro patrón) pero nos sirve para que el controlador nos quede mucho más limpio y delegar la responsabilidad de creación de objetos a otra clase.
El código de la factoría seria el siguiente:
Beneficios del Principio de Abierto/Cerrado
- Extender las funcionalidades del sistema, sin tocar el núcleo del sistema.
- Prevenimos romper partes del sistema al añadir nueva funcionalidades.
- Facilidad en el «testeo» de clases.
- Separación de las diferentes lógicas.
L – Principio de Sustitución de Liskov (Liskov substitution principle)
La L en el acrónimo de SOLID es para el Principio de Sustitución de Liskov (LSP). Este principio fue introducido por la gurú y primera mujer en Estados Unidos en obtener un doctorada en Ciencias de la Computación, Barbara Liskov. Y es un principio muy interesante:
Según Wikipedia. El Principio de Sustitución de Liskov dice que, cada clase que hereda de otra puede usarse como su padre sin necesidad de conocer las diferencias entre ellas.
No parece muy complicado, no? Pero vamos a entrar en detalles para que se entienda mejor este principio, porque merece la pena que lo tengamos en cuenta.
Hay 3 hitos que tenemos que tener en cuenta para no violar el principio de Liskov:
- No fortalecer las pre-condiciones y no debilitar las pos-condiciones.
- Las invariantes establecidas en la clase base deben mantenerse en las subclases.
- Y no puede existir un método en la subclase que vaya en contra de un comportamiento de la clase base. Esto se lo llama Restricción Histórica.
Primer hito para no violar el principio de Liskov
Lo primero que tenemos que tener en cuenta para no violar el principio de Liskov es, no fortalecer las pre-condiciones y no debilitar las pos-condiciones de la clase padre. Veamos esto con un ejemplo.
Acá tenemos una clase base, donde su método para calcular el precio de envío tiene una pre y una post condición (esta forma de programar utilizando las pre y post condiciones, se lo llama Programación Defensiva).
El primer hito seria violado si creamos otra clase, la extendemos de Shipping
y modificamos las pre y post condiciones del método calculateShippingCost()
, de la siguiente manera.
El problema con esto es que, si uno de los programadores de nuestro equipo esta seguro que el método calculateShippingCost()
, de la clase padre Shipping
, permite destino nulo y costos de envíos mayores a cero, entonces al querer utilizar la clase WorldWideShipping
podría hacer reventar el sistema, por ejemplo, si desea utilizar el resultado de calculateShippingCost()
en una división.
Por lo tanto, la clase WorldWideShipping
esta violando el principio de sustitución de Liskov.
Segundo hito para no violar el principio de Liskov
El segundo hito habla sobre las «invariantes». Las invariantes son valores de la clase base que no pueden ser modificadas por las clases hijas. El siguiente ejemplo no esta permitido por el principio de sustitución ya que estamos cambiando el valor de una propiedad de la clase base.
¿Cómo se previene esta violación? Podríamos definir las propiedades invariables como privadas. Aunque la mejor solución es que siempre mantengamos las propiedades invariables como tal.
Tercer hito para no violar el principio de Liskov
Este tercer hito tiene que ver con las Restricciones Históricas y es un tema muy interesante. Las restricciones históricas dicen que no puede existir un método en la clase hija que vaya en contra de un comportamiento de su clase padre.
Es decir, si en la clase padre existe el método ImpuestoFijo()
, entonces en la clase hija no puede existir el método ModificarImpuesto()
. ¿O no te enseñaron que no hay que desobedecer a tus padres? 😆
Que un método de la subclase modifique el valor de una propiedad de la clase base es una violación al principio de Liskov porque las clases deben poder cambiar el valor de sus propiedades únicamente (Encapsulamiento).
Una forma fácil de no romper con el Principio de Sustitución de Liskov.
La mejor manera para no romper con LSP es utilizando Interfaces. En lugar de extender nuestras clases hijas de una clase padre, podemos prescindir de la clase padre y utilizar interfaces para no romper con el principio. Veamos como quedaría el ejemplo anterior utilizando interfaces.
Al utilizar interfaces podes implementar métodos que varias clases tienen en común, pero cada método tendrá su propia implementación, sus propias pre y post condiciones, sus propias invariables, etc. No estamos atados a una clase padre.
NOTA: Esto no quiere decir que empecemos a utilizar interfaces por todos lados, aunque son muy buenas. Pero a veces es mejor utilizar clases base y otras veces interfaces. Todo depende de la situación.
¡Pasemos al próximo Principio SOLID 🤘!
I – Principio de segregación de la interfaz (Interface segregation principle)
El Principio de Segregación de la Interfaz (ISP) es la I del Principio SOLID y tiene un nombre complicado pero es fácil de entender. El principio de segregación dice que un cliente solo debe conocer los métodos que van a utilizar y no aquellos que no utilizarán.
Básicamente, a lo que se refiere este principio es que no debemos crear clases con miles de métodos donde termina siendo un archivo enorme (Hola Models!). Ya que estamos generando una clase monstruo, donde la mayoría de veces solo utilizaremos algunos de sus métodos en cada ocasión.
Veamos un ejemplo en Laravel donde podríamos aplicar el principio de segregación de interfaz.
Ejemplo del Principio de Segregación de la Interfaz en Laravel
Como di a entender en el párrafo anterior, un claro ejemplo de violación del principio de segregación es cuando agregamos y agregamos métodos a nuestros modelos de Laravel.
Supongamos que tenemos el modelo Subscriber
con los siguientes métodos:
Y luego, tenemos una clase Notifications
encargada de ejecutar la notificación por email.
* Aclaro que la clase Notifications no tiene nada que ver con las notifications de Laravel, esto es solo a modo practico para demostrar el principio de segregación.
Como podemos ver, estamos inyectando el modelo Subscriber
únicamente para utilizar uno de sus métodos. Y la verdad, ¿para que queremos el resto de métodos que trae el modelo Subscriber
si no los vamos a utilizar?
Además, un programador que no conozca en profundidad nuestro sistema ¿cómo se daría cuenta que en la clase Subscriber se encuentra el método que necesita?
Para solucionar esto, veamos como aplicar el Principio de Segregación de Interfaces.
De esta forma podemos hacer que cualquier clase implemente la interfaz y el método getNotifyEmail()
. Esto le da una independencia absoluta a nuestro código ya que podríamos crear una clase para cada forma de obtener el email (por API, por base de datos, por archivo, etc.). Además, podríamos poner un nombre más descriptivo a nuestra interfaz para que el resto de programadores de nuestro equipo puedan a entender el código fácilmente.
Beneficios del Principio de Segregación de la Interfaz
El principio de segregación fue creado por Robert C. Martin (Uncle Bob) – ¡Me encanta como explica este tipo! – y su principal función es brindarnos un código desacoplado, permitiéndonos mayor facilidad en la refactorización, modificación y despliegue de nuestro código.
Código Limpio y Arquitectura Limpia son dos excelentes libros escritos por la misma persona que introdujo los Principios SOLID, Robert C. Martin. Además, te dejo otro libro muy bueno sobre Patrones de Diseño muy recomendado.
D – Principio de Inversión de Dependencias (Dependency inversion principle)
El Principio de Inversión de Dependencias (DIP) también fue introducido por Robert C. Martin y es la D del Principio SOLID.
Primero debo dejar en claro que la Inversión de Dependencias NO es lo mismo que Inyección de Dependencias. La inversión de dependencias es un principio, mientras que la inyección de dependencias es un patrón de diseño (en futuros artículos entraré más en detalle). Aun que si tiene que ver ya que, el patrón se basa en el principio de inversión.
Dicho esto, comencemos con la explicación de este bonito principio SOLID.
El alto acoplamiento es el enemigo
Principalmente, el principio de inversión de dependencias nos ayuda a tener un código con bajo acoplamiento de clases. ¿Y qué significa tener un acoplamiento de clases? Bueno, si vienes siguiendo esta guía atentamente, vimos al comienzo del principio anterior que estaba utilizando la clase Subscriber
y luego la cambie por NotifiableInterface
. Si dejaba la clase Subscriber eso sería un alto acoplamiento, porque estábamos dependiendo de esa (y solo de esa) clase concreta. Al cambiarla por una interface, podríamos reemplazar la clase Subscriber por cualquier otra que implemente la interface.
¿No queda claro? Vayamos a otro ejemplo.
Ejemplo del Principio de Inversión de Dependencias en Laravel
Si tenemos un código como el siguiente, estamos generando un alto acoplamiento al instanciar directamente el modelo User
en el método. Esto significa que estamos dependiendo únicamente de esta implementación.
A simple vista no parece que estemos haciendo algo mal y hasta parece muy lógico que lo hagamos así. Pero tiene varios problemas esta implementación:
- No podemos reutilizar el código ya que estamos atados a Eloquent.
- Se complica hacer test a los métodos que instancia uno o varios objetos (alto acoplamiento), ya que es complicado verificar que esta fallando.
- Se rompe el principio de responsabilidad única, porque, además de que el método haga su trabajo, también tiene que crear los objetos para poder hacer su labor.
¿Cómo no violar el Principio de Inversión de Dependencias?
¡Otra vez las interfaces al rescate! Las interfaces son geniales (como ya vimos a lo largo de los principios SOLID), ya que nos permite abstraer el código y usar cualquier implementación que queramos.
En el siguiente ejemplo vemos como abstraer el código anterior para no violar el principio de inversión de dependencias.
Ahora veamos como quedaría la interface y algunas implementaciones:
Como podemos ver, todas las clases implementan la interface UserRespositoryInterface
. Y esto nos da la libertad de obtener los usuario ya sea desde Eloquent, desde SQL o desde un archivo csv 👏😲.
Pero la pregunta del millón que te debes estar haciendo (y capaz que te la venís haciendo desde el anterior principio SOLID) es, ¿cómo le digo al método index()
que tome una u otra clase? 🤔.
¡Fácil! «bindeando» la interface con la clase concreta que queramos:
Bum, ahí tenes! en el método register()
del archivo AppServiceProvider.php
que viene en Laravel (podemos crear otro ServiceProvider si queremos mayor prolijidad), utilizamos el método bind()
donde el primer parámetro es el namespace donde tenemos la interface y el segundo parámetro es el namespace donde tenemos la clase concreta que queremos utilizar para nuestro sistema.
Conclusión
Estos fueron todos los Principios SOLID explicados con ejemplos en Laravel. Recuerda que los principios no son reglas y no siempre, en todas las situaciones deben ser aplicados. Te darás cuenta cuando y donde aplicarlas cuando vayas tomando experiencia. Insisto que empieces a implementarlos en tus desarrollos, te harán un mejor programador y en un futuro me lo agradecerás por darme bola 😆. Espero que les haya gustado, si es así compartan y comenten. Nos vemos en la próxima.
Después de leer esto me doy cuenta que programar bien no es tan sencillo como aprender un lenguaje jaja es complicado estar pensando a cada paso que das si no estás incumpliendo uno de los principios de SOLID. Quisiera saber realmente que porcentaje de los programadores aplica SOLID
Aprender un lenguaje es la punta del iceberg si queres ser un desarrollador profesional. Y los principios SOLID son el comienzo, hay mucho más todavía.
Con respecto a aplicar siempre SOLID es relativo, depende lo que estés haciendo. Si estas haciendo un blog bueno…no hay problema. Pero si estas haciendo una plataforma mucho más grande, que será el núcleo de tu negocio, en ese caso sería clave aplicarlos.
Se te dificulta en este momento porque algo que no te cuentan es que para aplicar estos principios requieres el uso de pruebas de unidad con TDD o BDD, intentar aplicar esto con pruebas manuales; creeme que es complejo y una perdida de tiempo. Lo que ocasiona que los desarrolladores nuevos se frustren y regresen a las practicas que ya conocen. Poro otro lado algo que no te dicen es que solid nacio de la aplicación del conocmiento en sistemas grandes y complejos y de la necesidad de tener limites bien definidos entre los elementos de software para reducir su acoplamiento para reducir su complejidad. Así que no es necesario que apliques todos los principios, Ahora ¿Cómo sabes que principos aplicar? haciendo uso de pruebas unitarias y dependiendo del problema.
Por qué dices que es necesario TDD para aplicar SOLID? No veo que sea necesario.
La razón la explique en mi mensaje anterior. Aplicar los principios a una sola clase es mediamente sencillo pero el detalles es que en proyectos reales los objetos colabora entre si y aplicar los principios y tener todo funcionando es mucho mas sencillo si usas TDD que hacer uso de tecnicas manuales que consumen mucho tiempo. Te unvito a que hagas un ejemplo medianamente grande y apliques los principio de la forma clasica y luego intenta haciendo uso de TDD y me cuentas lo resultados. Por otro lado el uso de pruebas automatizadas no es opcional, son necesarias siempre, es algo que debes de manejar si quieres crear software mas confiable.
En ese orden de ideas es recomendable dejar de usar los controladores cómo se usaban antes y crear un sólo controlador para cada método?. https://laravel.com/docs/5.8/controllers#single-action-controllers
Esto implicaría dejar de usar rutas resource, o sería muy excesivo?.
Como poder, podrías. Todo depende el caso. Pero tene en cuenta que una clase engloba un concepto.
No esta mal que una clase de tipo Resources Controller tenga sus correspondientes métodos index(), create(), store(), update(), etc. Pero no deja de ser un Controller, su concepto y su responsabilidad es la de recibir una request, delegar y responder al cliente o vista. Cualquier duda, volve a escribir :).
Matías tu dices: «El concepto del Controller y su responsabilidad es la de recibir un request, delegar y responder a una vista».
Yo creía que el Controller es el que hacía todo. El Model se encargaba de la DB, las VIEWS de la Interacción con el Cliente y el CONTROLLER de procesar lo que recibe de los forms, consultar al Model procesar y mandar a vista. Ahora resulta que el controller sólo Delega jajaja …
Hola Mauro. Si, es muy común ver que las personas que utilizan Laravel ponen toda la lógica en los controladores y luego te surgen preguntas como «Como puedo llamar un método de un controller desde otro?». También, si quisieras utilizar esa lógica pero ahora en un controller de una API o de un CLI, deberías crear un nuevo controller y hacer copy&paste de esa lógica. En resumen, no podes reutilizar código.
Por eso, lo mejor es separar la lógica de negocio en clases separadas. Saludos.
depende del caso, no es conveniente usar single action controllers (SAC) si estás haciendo un clásico CRUD/ABM de productos (terminarías con 4 o más SAC)
Las imágenes no cargan :c
Muy buenos ejemplos sobre como implementar SOLID a nuestros desarrollos.
Solo un comentario, tu primer ejemplo no viola SRP porque el controlador no esta manejando directamente la validación ni la inserción, esta llamando a otros objetos que se encargan de eso (Request, Model). Lo que estas haciendo en tu ejemplo, es hacer que el método haga una sola cosa; un cocepto que viene explicado en el libro de Clean Code que estas recomendando, pero aun así, tampoco se viola ese principio porque las llamadas a los otros objetos estan en el mismo nivel de abstracción, pero es valido reactorizar para hacer mas legible el método.
Discúlpame, pero no estoy de acuerdo.
En el primer ejemplo el controlador esta instanciando los objetos Request y User donde cada uno de los respectivos objetos están haciendo sus tareas dentro del método del controlador, no hay delegación de tareas.
Cuando necesites cambiar/agregar una validación o la forma en que guardas los datos, deberás tocar la clase Controller y chau SRP.
Con ese argumento estas confundiendo OSP con SRP. porque para agregar o cambiar la validación tienes que modificar el método, pero no lo haces en el controller si no en el request. Con lo cual no estas afectando la responsabilidad del controller. Si falla la validación se genera el response o en todo caso se lanzara una Exception; que tampoco genera el Controller y por lo tantno no afectan la responsabilidad. SRP se trata de lo que hace el objeto y en este caso no se viola: porque existen otros dos objetos Resquest, Model y Response que se enargan de hacer lo que no debe de hacer el controller. Ahora desde el momento en que llamas o invocas a otro objeto dentro de una clase, ya es delegación. En el libro de Erich Gamma (Patrones de diseño) que recomiendas viene un capitulo que habla sobre el tema. En resumen tu ejemplo no viola SRP, pero si OSP porque tienes que hacer cambios en el controller para modficar las validaciones de las cuales no se hace cargo el Controller, de hecho ni el request, y una forma de resolverlo es como lo hiciste. Tu articulo es muy bueno y m sugerencia es que ajustes tu ejemplo inicial.
Yo creo de que si se está violando el principio de responsabilidad única. Porque el método haciendo de todo
Disculpa Hermenio pero te estás equivocando. Si bien OCP es parecido a SRP, el principio que dice que una clase debe tener solo una razón para cambiar, es el principio de responsabilidad única. Y en el primer ejemplo tenés más de una razón, más responsabilidades y más acoplamiento, por lo tanto, claramente está violando SRP. Saludos amigo y muchas gracias por tus comentarios sobre el artículo.
SRP se trata de lo que hace la clase pos si misma, es decir lo que afecta su estado interno y en ningun lado el controller tiene la logica para validar, responder y mucho menos, insertar datos por si misma, si eso sucediera entonces si estas hablando de SRP pero en tu ejemplo no sucede esto; porque otras clases estan encargadas de gestionar la validación (Request), La inserción (Model) y la respuesta json (Response) eso no es SRP hijo. Lo que tu estas resolviendo en tu ejemplo es acoplamiento que es otro tema que sucede entre un objeto y sus dependecias. y OSP porque un cambio en las validaciones me obliga a cambiar los parametros en el Request validation y eso me obliga a pensar en una forma de poder agregar o quitar validaciones sin tener que tocar el controller. Para finalizar generalmente una clase que viola SRP sufre de Cambio Divergente (Divergent Change) otra forma de darte cuenta es aplicar GRASP.
Sigo sin compartir tu forma de verlo, pero bueno…dejemos que los lectores se interesen en el tema y saquen sus propias conclusiones, que ese es el fin del artículo. Saludos.
Hola Matias…
Tienes enlaces a los libros que mencionas en el artículo?
Si, haz click sobre las imágenes de los libros.
Tu explicación es muy clara y sencilla lo que hace que pueda entenderla (siendo esto muy difícil para mi jajajja), hoy en la mañana empece a implementar tus enseñanzas, muchas gracias por la información.
Muchas gracias a vos por tu comentario. Me alegra que te haya servido y lo empieces a implementar. Saludos.
Interesante, entendible y buenos ejemplos =)
Una pregunta cual seria la estructura mas correcta para todos esos archivos en Laravel ?? Gracias me encanta tu blog
Hola Jaime.
Para mí, la mejor opción es crear una carpeta con el nombre de tu proyecto/modulo en la raíz del proyecto y registrar el namespace en el archivo composer.json. En esta nueva carpeta aplicas lo viste y según las necesidades. Luego, desde el controlador haces los llamados a lo que necesitas.
En un próximo articulo voy a entrar mas en detalle.
Saludos.
Excelente ! Gracias
Siguiendo el hilo del amigo Jaime, tienes un articulo sobre la estructura mas correcta para saber como tener bien estructurado mejor mi proyecto.
Te dejo mi repo que subi un ejemplo el fin de semana: https://github.com/matiechaza/laravel-hexagonal-example
Excelente gracias
De antemano muy buen artículo gracias, quisiera saber si tienes un repositorio público donde se hagan aportes a buenas prácticas y el uso de SOLID con Laravel.. Gracias.
Hola Giovanny. Muchas gracias por tu comentario. No por ahora, solo los artículos que están disponibles en esta web. Pero voy a empezar a subir algunos ejemplos a mi repo.
Saludos.
Excelente artículo, bien explicado y con ejemplos muy sencillos. Es un buen punto de partida para todos aquellos desarrolladores que de alguna u otra forma queremos mejorar en las técnicas apropiadas para un código limpio, escalable y mantenible. Gracias por el aporte de tus conocimientos.
Gracias a vos Roldán por tu comentario. Saludos!
Muy buen articulo, pero las imágenes no cargan
Muy buen artículo igual que el de Hexagonal! Tiene algunos otros? Pq no veo q se pueda filtrar por user los posts
Muchas gracias! Todos los artículos que hay en el blog son míos.
Hola. Excelente artículo. Te consulto, en el primer ejemplo, cuando agregas UserRepository como parámetro al método store, lo inyectas como servicio (registrando un service provider y bindeando)? Gracias
Así es, se debería registrar el service provider. Saludos.
muy buen articulo, tengo una duda espero me la puedas aclarar.. en el ultimo ejemplo si quiero utilizar digamos las 3 clases (UserEloquentRepository, UserSqlRepository, UserCsvRepository ) en diferentes partes de mi código. como tengo que bindear esto en mi proveedor de servicios? como saber cual de las 3 clases es la que quiero instancear en determinado lugar?
Hola Nano, como estas? Para implementar distintas clases concretas en distintos controllers (por ejemplo), se utiliza los Contentex Binding de Laravel. Te dejo la parte de la docu donde lo explica muy bien: https://laravel.com/docs/7.x/container#contextual-binding
Saludos.
Excelente matias, muchas gracias!
Excelente, para seguir aprendiendo e implementando
Este articulo es lo mejor que leí sobre principio SOLID con laravel! muchas gracias!!
Gracias a vos Alejandro por tu comentario. Saludos!
Excelente la verdad estos teman caen como anillo al dedo.
¿No has pensado en hacer un tema sobre POO con PHP?
Gracias por todo el contenido que suben, un abrazo!!!
Muchas gracias por este gran articulo!
tengo que registrar en services provider el controlador repository del primer ejemplo para que funcione? porq me dice que laravel no encuentra /repositories
En teoría Laravel inyecta los repositorios automáticamente (https://laravel.com/docs/8.x/container#automatic-injection).
Me he dado cuenta que he cometido muchos errores a la hora de desarrollar, después de leer esto. Muchas gracias maestro!!
Gracias a vos por tu comentario!
Mati no me quedo claro el Ejemplo del Principio de Abierto/Cerrado en Laravel de todas formas sigue estando el switch
Como estas Ariel?
Es correcto pero ahora el switch lo estamos usando para devolver distintas clases que ejecutan formas de pago.
Al principio lo que hacia el switch era decidir que forma de pago se iba a ejecutar, que eran formas de pago que estaban codeadas dentro de la clase
Payment
y si querías agregar o quitar una forma de pago, tenías que tocar la clasePayment
y el métodopay()
para agregar esta nueva forma de pago.Al aplicar el patrón abierto/cerrado lo que nos permite es no tocar la clase
Payment
, ni el métodopay()
. Unicamente crearíamos una nueva clase para la nueva forma de pago y la agregaríamos en el switch de la factory.Como devs siempre deberíamos intentar crear nuevas clases en lugar de modificar las que existen. 😉
Hola Matias, aplique el principio de Abierto/Cerrado, pero tengo una duda, yo utilizo el método pay como metodo POST para pasarle el request con el type y otros datos necesarios y allí utilizo 2 métodos paypal y Strapi, pero cuando hago la llamada al factory para que haga el trabajo el switch, no consigo que me haga el return del link para pagar de paypal ni de strapi, que me recomiendas?
Ya conseguí mi error, como es una arquitectura un poco distinta hay que analizarla para comprenderla bien, excelente post muchas gracias.
Excelente para aprendizaje, como dicen abajo, cometemos muchos errores y mas cuando seguimos video cursos y mayoria no explican estos principios que al Parecer «Reglas» son en realidad ayudas para hacer las cosas crecer, porque creas tu proyecto pensabo en las rutas web.php y todas la respuestas en tus controllers van como corresponden a la vista respectiva pero si luego vas a conectar una app, utilizas api/controller y tener que empezar a duplicar el codigo no es viable, porque al cambiar un field «desastre» entonces en este Caso para proyectos sencillos en mi humilde opinion pueden usar Traits que facilitan esto si implementar solid del todo.
Muchas gracias por tu comentario Jonay! Personalmente no me gustan los traits, a menos que sea requerido para un caso puntual. Pero tienes mucha razón con lo que comentas sobre la duplicación de código y como las buenas prácticas nos pueden ayudar a evitarlo.
Otro gran articulo. No puedo tener adceso a los libros que mencionas, asi que me toca implementar cada uno de sus ejemplos para iteriorizar de manera correcta los principios de SOLID. En algo concuerdo con algunos comentarios. Muchos de los videos e informacion que consigues de forma libre no tienen en cuenta ninguno de estos conceptos, te das cuenta cuando te enfrentas a proyectos reales o quieres ingresar en alguna empresa la cual revisa tus códigos. Muchas gracias por compartir.