Curso Avanzado de PHP

Curso Avanzado de PHP

H茅ctor Benitez

H茅ctor Benitez

SOLID a profundidad

13/35

Lectura

Vamos a ir mas a fondo acerca de c贸mo funcionan los principios de SOLID y para esto crearemos algunos ejemplos que nos ayudar谩n a entender mejor c贸mo se aplica esto en PHP:

Vamos a comenzar con un ejemplo de c贸digo que claramente rompe estos principios de programaci贸n y buscaremos la forma de repararlo:

<class Reporter {
	public function getExpensesReport($idReport) {
		$expenses = $this->queryDBToGetExpenses($idReport);
		return $this->renderHTML($expenses);
}

鈥 // El c贸digo de las funciones va aqu铆
}>

En este ejemplo, aunque aparentemente el c贸digo no luce tan mal, en realidad estamos violando dos veces el principio de responsabilidad 煤nica. Imagina que queremos cambiar la forma en la que se realiza esta consulta a la DB (Data Base o Base de Datos), o queremos cambiar la forma en la que se muestra el HTML del reporte, el tener al menos dos razones tan diferentes para modificar esta clase, nos indica que realmente estamos violando este principio.

Ahora cambiemos el c贸digo para ver c贸mo podr铆amos solucionar este problema:

<class ExpensesRepository {
	public function getExpensesForReport() {
		// Aqui va la consulta  a la DB
}
}

class ExpensesReportHTMLFormatter {
	public function renderHTML($expenses) {
		// Aqu铆 va el c贸digo que crea el c贸digo HTML
}
}

class Reporter {
	private $repository;
	private $formatter;

	public function __construct() {
		$this->repository = new ExpensesRepository();
		$this->formatter = new ExpensesReportHTMLFormatter();
}

public function getExpensesReport($idReport) {
		$expenses = $this->repository->getExpensesForReport($idReport);
		return $this->formatter->renderHTML($expenses);
}
}>

Ahora este c贸digo es un poco mejor, sin embargo estamos rompiendo claramente otro de los cinco principios SOLID: La Inversion de Control, este principio nos dice que debemos evitar que se dependa de clases concretas y tratar de usar siempre abstracciones para solucionar estas dependencias.

En este caso claramente podemos ver que la clase Reporter, depende directamente de la clase ExpensesRepository y de la clase ExpensesReportHTMLFormatter, esto hace que nuestro c贸digo est茅 muy acoplado y nos complique el mantener y extender la funcionalidad del mismo, imagina ahora que queremos imprimir el reporte tambi茅n en JSON, en ese caso tendr铆amos que modificar el c贸digo existente para cambiar las cosas.

En este caso, el primer paso para invertir el control ser谩 evitar crear instancias de otras clases dentro de nuestra Reporter e inyectar esas dependencias a trav茅s de nuestro constructor:

<class Reporter {
	private $repository;
	private $formatter;

	public function __construct(ExpensesRepository $repo, ExpensesReportHTMLFormatter $formatter) {
		$this->repository = $repo;
		$this->formatter = $formatter;
}

public function getExpensesReport($idReport) {
		$expenses = $this->repository->getExpensesForReport($idReport);
		return $this->formatter->renderHTML($expenses);
}
}>

Esto ya es un paso inicial para cambiar la forma en la que funciona el c贸digo, sin embargo, aun no resolvemos c贸mo haremos para poder regresar los valores usando otro formato. Bueno, para esto lo que nos recomienda el principio de Inversion de Control es no depender de clases concretas y en lugar de eso depender de abstracciones.

Para este ejemplo lo que podemos hacer es crear una interfaz que sirva como contrato de la forma en la que se imprime un reporte e implementarla en todas las clases que queramos usar para lo mismo:

<interface ExpensesReportFormatterInterface {
	public function render($expenses);
}>

Y esta interfaz la podremos implementar en diferentes clases:

<class ExpensesReportHTMLFormatter implements ExpensesReportFormatterInterface {
	public function render($expenses) {
		// Aqu铆 va el c贸digo que crea el c贸digo HTML
}
}

class ExpensesReportJSONFormatter implements ExpensesReportFormatterInterface {
	public function render($expenses) {
		// Aqu铆 va el c贸digo que crea el c贸digo JSON
}
}>

Y ahora podemos cambiar el constructor de nuestra clase para usar la abstracci贸n en lugar de la clase concreta:

<class Reporter {
	private $repository;
	private $formatter;

	public function __construct(ExpensesRepository $repo, ExpensesReportFormatterInterface $formatter) {
		$this->repository = $repo;
		$this->formatter = $formatter;
}

public function getExpensesReport($idReport) {
		$expenses = $this->repository->getExpensesForReport($idReport);
		return $this->formatter->render($expenses);
}
}>

De esta forma, ahora cuando queramos cambiar el formato de salida, lo 煤nico que tenemos que hacer es inyectar el formatter que queremos y nuestra aplicaci贸n funcionar谩 de una forma mucho m谩s clara y orientada a objetos.

Esto es solo un ejemplo de c贸mo trabajar usando los principios SOLID recuerda que nunca debes considerar nada como simples reglas a seguir, siempre sigue practicando y trata de entender el porqu茅 estos principios te pueden ayudar con tu c贸digo, es posible que al principio no sea tan clara la forma de implementarlos en tu c贸digo, pero te aseguro que si los tienes en mente y sigues practicando, con el tiempo ser谩n conceptos que podr谩s implementar de una forma mucho m谩s natural y sencilla.

Aportes 29

Preguntas 0

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Reg铆strate o inicia sesi贸n para participar.

Realmente pienso que lo que debemos repasar un poco es el tema de las interfaces, Aqui encontr茅 un video que explica con un problema de ejemplo muy bieno

https://www.youtube.com/watch?v=_59Bm1fxPmY

Tendr茅 que leer esto var铆as veces jajaja, me rompi贸 la cabeza. Voy a buscarme esos libros que dice el prof.

Si quieren aprender mas sobre este tema, les recomiendo los libros 鈥淎gile Software Development, Principles, Patterns, and Practices鈥 y 鈥淐lean Code鈥

necesito leer mas de esto, por que el ejemplo no me quedo muy clato 馃槂

Excelentiiisimooo!!! Grande Hector sos un crack! ya he trabajado con este principio pero tu ejemplo es Supremamente f谩cil! te felicito por tan buena explicaci贸n y muy clarame encanto sobre todo como cerraste al inyectar la interface uff esa fue una jugada de Messi!!! jajaja

Con dedicaci贸n es posible

A practicar los principios !

SOLID me da miedo鈥

buena explicacion!

Es como volver a aprender a programar. Ahora puedo enternder el por qu茅 de la estructura de muchas librer铆as que he visto.

Ohh incre铆ble, lo de inversi贸n de dependencias era lo 煤nico que no me hab铆a quedado claro, entonces al implementar una interfaz, no nos preocupamos de si la clase que nos pasen va a tener ese m茅todo o no, ya que la interfaz lo obligar谩 a que si lo tenga!

Muy buen art铆culo! No llego a entenderlo por completo pero me dio una gran base saber como funciona a grandes rasgos y seguir investigando.

Muy buena informaci贸n aplicar y mejorar cada d铆a.

la verdad no me queda muy claro el tema de SOLID, y tiene mucha raz贸n en eso que dice el ultimo p谩rrafo, seguir茅 indagando mas a cerca del tema hasta que llegue al punto de poder entender su l贸gica y la forma en la cual me pueda ayudar a facilitar el desarrollo de c贸digo

En el ejemplo se inyecta un repositorio y un formater pero cuano se aplica la interfaz solo se hace sobre el formater y no sobre el repositorio. Porque? Con el repositorio seguiriamos violando el principio de Inversion de control

Genial todo esto se ve muy claro y excelente, m谩s informaci贸n se puede encontrar en el libro Arquitectura Limpia

Como hago para pasar un valor calculado en una vista y guarde en la BD

Muy buena la explicaci贸n!

Gracias por la explicacion de verdad que es una buena forma de mejorar el nuestros c贸digos con todo estos principios, excelente.

Que gran explicacion.

Este art铆culo me sirvi贸 bastante para entender el tema de las interfaces en solid
https://desarrolloweb.com/articulos/2197.php

Great!

Que gran ejemplo de aplicaci贸n, me encant贸!

Definitivamente es el mejor

Es de practica!!! Vamos a darle

Super 馃槂 gracias. 馃憣馃槉

La verdad siempre escuche de estos principios pero nunca los intent茅 poner en pr谩ctica y es tal como dices toca practicar y bastante para hacerlo un h谩bito

Excelente resumen definitivamente pondr茅 en pr谩ctica estos principios鈥

Excelente. 馃憤