Sobes.tech
Middle

Tell about the letter D in SOLID and its connection to interfaces.

sobes.tech AI

Answer from AI

D in SOLID stands for the Dependency Inversion Principle (DIP).

The principle states:

  • High-level modules should not depend on low-level modules. Both should depend on abstractions.
  • Abstractions should not depend on details. Details should depend on abstractions.

The essence of DIP is that high-level policies should not depend on low-level implementations directly. Instead, both should depend on abstractions (interfaces or abstract classes).

Relation to interfaces:

Interfaces act as these abstractions. They define a contract that a specific implementation must fulfill.

Example without DIP:

<?php
class MySqlConnection {
    public function connect() {
        // MySQL connection details
    }
}

class UserRepository {
    private $dbConnection;

    public function __construct() {
        $this->dbConnection = new MySqlConnection(); // Dependency on a specific implementation
    }

    public function getUserById($id) {
        $this->dbConnection->connect();
        // Logic to get user
    }
}

In this example, UserRepository (a high-level module representing business logic) directly depends on MySqlConnection (a low-level module representing implementation details). If you need to switch to PostgreSQL, you would have to change UserRepository.

Example with DIP and using an interface:

<?php
interface DbConnectionInterface { // Abstraction
    public function connect();
}

class MySqlConnection implements DbConnectionInterface { // Implementation detail depending on abstraction
    public function connect() {
        // MySQL connection details
    }
}

class PgSqlConnection implements DbConnectionInterface { // Another implementation depending on abstraction
    public function connect() {
        // PostgreSQL connection details
    }
}

class UserRepository { // High-level module depending on abstraction
    private $dbConnection;

    public function __construct(DbConnectionInterface $dbConnection) { // Dependency on abstraction
        $this->dbConnection = $dbConnection;
    }

    public function getUserById($id) {
        $this->dbConnection->connect();
        // Logic to get user
    }
}

// Usage
$mysqlConn = new MySqlConnection();
$userRepoMysql = new UserRepository($mysqlConn);

$pgsqlConn = new PgSqlConnection();
$userRepoPgsql = new UserRepository($pgsqlConn);

In this improved example, UserRepository depends on the DbConnectionInterface interface, not on a specific implementation. This makes it easy to change the database type by passing different implementations of this interface to the constructor of UserRepository.

Thus, interfaces play a key role in implementing DIP by providing abstractions that allow high-level modules to remain independent of low-level implementation details. This increases flexibility, testability, and maintainability of the code.