Tell about the dependency principle in SOLID that corresponds to the D letter.
sobes.tech AI
Answer from AI
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 of the principle: reduce coupling between components, making the system more flexible, testable, and scalable.
Example in Swift:
Bad:
class UserRepository {
func getAllUsers() -> [User] {
// Logic to get 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 of the abstraction)
class ConcreteUserRepository: UserRepositoryProtocol {
func getAllUsers() -> [User] {
// Logic to get users (implementation details)
// ...implementation...
return []
}
}
// High-level module depending on the abstraction
class UserService {
private let repository: UserRepositoryProtocol // Dependency on protocol
init(repository: UserRepositoryProtocol) {
self.repository = repository // Dependency injection
}
func fetchUsers() -> [User] {
return repository.getAllUsers()
}
}
// Dependency setup (preferably done 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 by implementing it. The dependency is "inverted" — instead of the high-level module depending on the low-level one, both depend on the abstraction.