Curso Principios SOLID - 5. Principio de Inversión de Dependencias

Curso Principios SOLID - 5. Principio de Inversión de Dependencias

La D de SOLID representa el Principio de Inversión de Dependencias (DIP) y gracias a él podemos hacer que el core de nuestra aplicación no dependa de los detalles de implementación como la base de datos, el framework que se utilice, el servidor, etc. Dichos detalles se van a especificar mediante interfaces y no tenemos por qué saber cuál es la implementación real para funcionar.

Por ejemplo, en Geeky Theory utilizamos Laravel para realizar la web, MySQL para almacenar los datos, caché, etc. Sin embargo, el código está preparado para que podamos cambiar de base de datos sin ningún problema y utilizando el mismo código.

El Principio de Inversión de Dependencias establece dos puntos importantes:

  1. Los módulos de alto nivel no dependen de módulos de bajo nivel. Ambos deben depender de abstracciones.
  2. Las abstracciones no deben depender de los detalles, sino que los detalles deben depender de las abstracciones.

Cuando un módulo depende de otro, simplemente se crea una nueva instancia y se utiliza. Por ejemplo, podría utilizar el módulo MySQL directamente en mis modelos que se conectan a base de datos, pero esto haría que yo fuese dependiente de dicho módulo, que es un detalle de implementación.

Ejemplo práctico

<?php

class Logger 
{
    private $fileSystem;

    public function __construct()
    {
        $this->fileSystem = new NTFSFileSystem();
    }

    public function log(string $text)
    {
        $stream = $this->fileSystem->openFile("application.log");
        $stream->write($text);
        $stream->close();
    }
}

Tras refactorizar el código:

<?php

interface LoggableInterface
{
    public function log(string $text);
}

class NTFSFileSystem implements LoggableInterface
{
    public function log(string $text)
    {
        echo "Logging $text to NTFS..." . PHP_EOL;
    }
}

class SqlLogger implements LoggableInterface
{
    public function log(string $text)
    {
        echo "Logging $text to SQL..." . PHP_EOL;
    }
}

class Logger
{
    private $logService;

    public function __construct(LoggableInterface $logService)
    {
        $this->logService = $logService;
    }

    public function log(string $text)
    {
        $this->logService->log($text);
    }
}

class Program
{
    public static function run()
    {
        $ntfsLogger = new Logger(new NTFSFileSystem());
        $ntfsLogger->log("Hello from Geeky Theory!");

        $sqlLogger = new Logger(new SqlLogger());
        $sqlLogger->log("This is a SOLID course!");
    }
}

Program::run();