Sobes.tech
Middle

What can you tell about the D principle in SOLID?

sobes.tech AI

Answer from AI

The Dependency Inversion 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 goal of D in SOLID is decoupling high-level policies from low-level implementation. Instead of a high-level module directly depending on a specific low-level module implementation, both depend on a common interface or abstract class. This increases flexibility, testability, and maintainability of the code.

In Flutter, this often manifests through the use of abstract classes or mixins to define contracts, which are then implemented by concrete classes. For example, when working with data:

// Abstraction
abstract class DataService {
  Future<List<String>> getData();
}

// Low-level implementation (concrete detail)
class ApiDataService implements DataService {
  @override
  Future<List<String>> getData() async {
    // Logic to fetch data from API
    return ['API Data 1', 'API Data 2'];
  }
}

// Low-level implementation (another concrete detail)
class LocalDataService implements DataService {
  @override
  Future<List<String>> getData() async {
    // Logic to fetch data from local storage
    return ['Local Data 1', 'Local Data 2'];
  }
}

// High-level module depending on abstraction, not on details
class DataManager {
  final DataService _dataService; // Dependency on abstraction

  DataManager(this._dataService); // Dependency injection (inversion)

  Future<List<String>> fetchData() {
    return _dataService.getData();
  }
}

// Usage
void main() {
  final apiService = ApiDataService();
  final localService = LocalDataService();

  final apiManager = DataManager(apiService); // Injecting ApiDataService
  final localManager = DataManager(localService); // Injecting LocalDataService

  // ... use apiManager or localManager
}

In this example, DataManager (high-level module) does not depend directly on ApiDataService or LocalDataService. It depends on the abstraction DataService. The specific implementation of DataService is "injected" into DataManager from outside, which is an expression of dependency inversion. This allows easy swapping of data sources without changing the logic of DataManager.