Wszystkie zależności powinny w jak największym stopniu zależeć od abstrakcji, a nie od konkretnego typu.

Moduły wysokiego poziomu nie powinny zależeć od modułów niskiego poziomu. Oba powinny zależeć od abstrakcji.”

Wprowadzenie

W dzisiejszym artykule chciałabym wyjaśnić ostatnią zasadę SOLID – DIP – Dependency Inversion Principle (Zasada odwrócenia zależności). Zasada ta koncentruje się na zarządzaniu zależnościami między klasami w sposób, który sprzyja elastyczności i łatwości rozszerzania kodu. Poniżej głównie założenia zasady DIP:

  1. Atrakcje nie powinny zależeć od szczegółów, to szczegóły powinny zależeć od abstrakcji. Interfejsy oraz klasy abstrakcyjne powinny definiować ogólną funkcjonalność, bez szczegółów implementacyjnych. Natomiast klasy i moduły na niższym poziomie, które dostarczają te szczegóły, powinny implementować te abstrakcje.
  2. Moduły wysokiego poziomu nie powinny zależeć od modułów niskiego poziomu, co oznacza, że klasy i moduły na wyższym poziomie (implementują bardziej ogólne funkcje, bez szczegółów), nie powinny bezpośrednio zależeć od klas i modułów na niższym poziomie (te klasy, w których znajdują się szczegóły implementacyjne). Moduły niskiego oraz wysokiego poziomu powinny zależeć od abstrakcji (implementować abstrakcje).

W praktyce zasada DIP jest realizowana poprzez wykorzystanie klas abstrakcyjnych, interfejsów oraz mechanizmu wstrzykiwania zależności. Aby lepiej wyjaśnić tą zasadę, spójrzmy na poniższy przykład.

Przykład

Mamy klasę MySQLConnection, która zawiera metodę connect() służącą do łączenia z bazą danych MySQL. Mamy również klasę PasswordReminder służącą do przypomnienia hasła. Ta klasa wymaga połączenia z bazą danych.

class MySQLConnection {
   public function connect()
   {
       //
   }
}

class PasswordReminder {
    private $dbConnection;

    public function __construct(MySQLConnection $connection)
    {
        $this->dbConnection = $connection;
    }
}

Zwróć uwagę, że klasa MySQLConnection służy do połączenia z bazą danych MySQL. A co jeśli chcielibyśmy połączyć się z inną bazą danych np.: Postgresql? W tym przypadku nie jest to możliwe. Dla naszej klasy PasswordReminder nie powinno mieć znaczenia z jaką bazą danych się łączymy.

Poprawny kod
interface DbConnectionInterface {
    public function connect();
}

class MySQLConnection implements DbConnectionInterface {
    public function connect()
    {
        // 
    }
}

class InFileConnection implements DbConnectionInterface {
    public function connect()
    {
        // 
    }
}

class PostgresConnection implements DbConnectionInterface {
    public function connect()
    {
        //
    }
}

class PasswordReminder {
    private $dbConnection;

    public function __construct(DbConnectionInterface $connection)
    {
        $this->dbConnection = $connection;
    }
}

W ten sposób nasza klasa PasswordReminder nie jest uzależniona od jakiegokolwiek silnika baz danych. Teraz jego zależnością jest połączenie z bazą danych.

Podsumowanie

Stosując zasadę odwracania zależności oddzielamy klasy wysokiego poziomu od klas konkretnych. Zgodnie z tą zasadą nie powinniśmy tworzyć klas niskiego poziomu używając operatora new().

Jeżeli jest to niezbędne, można posłużyć się wzorcami projektowymi np.: fabryka abstrakcyjna, metoda fabrykująca. Więcej o wzorcach projektowych w innych artykułach.




0 komentarzy

Dodaj komentarz

Avatar placeholder

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *