Sobes.tech
Middle

Rääkige SOLID-i sõltuvuspõhimõttest, mis vastab tähe D-le.

sobes.tech AI

Vastus AI-lt

Dependency Inversion Principle (DIP).

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 goal: reduce coupling between components, making the system more flexible, testable, and scalable.

Example in Swift:

Bad:

class UserRepository {
    func getAllUsers() -> [User] {
        // Logic to fetch users from a specific database or network
        // ...implementation...
        return []
    }
}

class UserService {
    private let repository = UserRepository() // Direct dependency on a specific implementation

    func fetchUsers() -> [User] {
        return repository.getAllUsers()
    }
}

Good (applying DIP):

// Abstraction
protocol UserRepositoryProtocol {
    func getAllUsers() -> [User]
}

// Low-level module (implementation)
class ConcreteUserRepository: UserRepositoryProtocol {
    func getAllUsers() -> [User] {
        // Logic to fetch users (implementation details)
        // ...implementation...
        return []
    }
}

// High-level module depending on abstraction
class UserService {
    private let repository: UserRepositoryProtocol // Dependency on abstraction

    init(repository: UserRepositoryProtocol) {
        self.repository = repository // Dependency injection
    }

    func fetchUsers() -> [User] {
        return repository.getAllUsers()
    }
}

// Assembling dependencies (preferably in a DI container)
let repository = ConcreteUserRepository()
let userService = UserService(repository: repository)

Here, UserService (high-level module) does not depend directly on ConcreteUserRepository (low-level module), but depends on the abstraction UserRepositoryProtocol. ConcreteUserRepository also depends on the abstraction, implementing it. The dependency is inverted — instead of high-level module depending on low-level, both depend on the abstraction.