Sobes.tech
Middle

O que podes contar-me sobre o princípio D no SOLID?

sobes.tech IA

Resposta da IA

O princípio da inversão de dependências (Dependency Inversion Principle) afirma:

  • Os módulos de nível superior não devem depender de módulos de nível inferior. Ambos os tipos de módulos devem depender de abstrações.
  • As abstrações não devem depender de detalhes. Os detalhes devem depender de abstrações.

O objetivo do D em SOLID é desacoplar (decoupling) as políticas de alto nível da implementação de baixo nível. Em vez de um módulo de alto nível depender diretamente da implementação concreta de um módulo de baixo nível, ambos dependem de uma interface comum ou de uma classe abstrata. Isso aumenta a flexibilidade, a testabilidade e a manutenibilidade do código.

No Flutter, isso muitas vezes se manifesta pelo uso de classes abstratas ou mixins para definir contratos, que são então implementados por classes concretas. Por exemplo, ao trabalhar com dados:

// Abstração
abstract class DataService {
  Future<List<String>> getData();
}

// Implementação de baixo nível (detalhe concreto)
class ApiDataService implements DataService {
  @override
  Future<List<String>> getData() async {
    // Lógica para obter dados de uma API
    return ['API Data 1', 'API Data 2'];
  }
}

// Outra implementação de baixo nível (outro detalhe concreto)
class LocalDataService implements DataService {
  @override
  Future<List<String>> getData() async {
    // Lógica para obter dados do armazenamento local
    return ['Local Data 1', 'Local Data 2'];
  }
}

// Módulo de alto nível que depende da abstração, não dos detalhes
class DataManager {
  final DataService _dataService; // Dependência da abstração

  DataManager(this._dataService); // A dependência é injetada (inversão)

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

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

  final apiManager = DataManager(apiService); // Injeção de ApiDataService
  final localManager = DataManager(localService); // Injeção de LocalDataService

  // ... uso de apiManager ou localManager
}

Neste exemplo, DataManager (o módulo de alto nível) não depende diretamente de ApiDataService ou LocalDataService. Ele depende da abstração DataService. A implementação concreta de DataService é "injetada" em DataManager de fora, o que é uma manifestação da inversão de dependência. Isso permite trocar facilmente as fontes de dados sem alterar a lógica de DataManager.