PRINCÍPIO DA INVERSÃO DE DEPENDÊNCIA

dev.to

Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações (interfaces).

Na prática, a sua regra de negócio não deve saber se você usa MySQL, Stripe ou AWS. Ela deve depender apenas de um contrato (Interface) que diz O QUE precisa ser feito, e não COMO será feito.


IMPLEMENTAÇÃO ENGESSADA

O erro mais comum no dia a dia é dar um new FerramentaExterna() direto dentro do seu caso de uso.

Quando você faz isso, seu código depende da ferramenta.

Se a ferramenta for descontinuada ou a API mudar, você terá que abrir o "coração" do seu sistema para consertar.


UM MAU EXEMPLO

A classe de negócio fortemente acoplada ao provedor de e-mail SendGrid. Isso é uma má prática.

Exemplo de Código:

import { SendGridProvider } from 'sendgrid-sdk';

// RUIM: O serviço instancia a ferramenta diretamente.
class RegisterUserUseCase {
  private mailProvider: SendGridProvider;

  constructor() {
    // Forte acoplamento!
    this.mailProvider = new SendGridProvider('API_KEY');
  }

  public async execute(email: string): Promise<void> {
    // ...lógica complexa de negócio...

    // Se o SendGrid mudar ou cair, essa classe quebra.
    await this.mailProvider.sendEmail(email, "Bem-vindo!");
  }
}
Enter fullscreen mode Exit fullscreen mode

INVERTENDO O JOGO

A solução é não depender da classe concreta SendGridProvider, mas sim criar uma interface genérica dentro do nosso próprio domínio.

O nosso serviço passa a receber essa dependência pronta pelo construtor (Injeção de Dependência).

A parte mais interessante é que nossa aplicação não precisa saber exatamente quem está por baixo dos panos, seja Resend, EmailJS ou outro, ela apenas segue o molde.


UM BOM EXEMPLO

O serviço agora depende apenas do contrato. A infraestrutura que obedeça.

Exemplo de Código:

// BOM: O contrato pertence à NOSSA aplicação.
interface IMailProvider {
  send(to: string, message: string): Promise<void>;
}

class RegisterUserUseCase {
  // Recebemos a abstração de fora (Injeção de Dependência)
  constructor(private mailProvider: IMailProvider) {}

  public async execute(email: string): Promise<void> {
    // ...lógica complexa de negócio...

    // O serviço não faz ideia de qual ferramenta está enviando
    await this.mailProvider.send(email, "Bem-vindo!");
  }
}
Enter fullscreen mode Exit fullscreen mode

O PODER DA INVERSÃO

A maior vantagem do DIP é a Modularidade.

Se amanhã o seu cliente pedir para trocar o SendGrid pela AWS SES, você só cria uma nova implementação da interface. A classe RegisterUserUseCase não sofre nenhuma alteração.

Além disso, os Testes Unitários ficam absurdamente mais fáceis, pois você pode injetar um Mock de e-mail falso sem precisar fazer disparos reais.


Meus Links
Github: victor-lis-bronzo
Linkedin: victor-lis-bronzo
Portfólio: portfolio.victorlisbronzo.me
Portfólio mais legal: victorlisbronzo.me


Deixe sua reação ❤️
Você já aplicava Injeção de Dependência antes de saber que isso era a base do DIP?

Source: dev.to

arrow_back Back to News