Skip to content

Reboredo.bit

Menu
  • Início
  • Sobre mim
  • Posts
Menu
solid principles

(D): Aplicando o “Princípio da Inversão de Dependências” com Typescript e Java

Posted on 25 de novembro de 202526 de novembro de 2025 by victoreboredo.dev@gmail.com

Continuação do estudo sobre os princípios SOLID. Com foco na Inversão de dependências.


Conceitos

SOLID é um acrônimo que representa cinco princípios fundamentais da programação orientada a objetos, propostos por Robert C. Martin – o uncle Bob. Aqui você pode ler mais sobre o artigo dele.
Esses princípios têm como objetivo melhorar a estrutura e a manutenção do código, tornando-o mais flexível, escalável e fácil de entender. Tais princípios auxiliam o programador a criar códigos mais organizados, dividindo responsabilidades, reduzindo dependências, simplificando o processo de refatoração e promovendo a reutilização do código.

O “D” do acrônimo significa “Dependency Inversion Principle”. A frase que o uncle bob utilizou para definir esse princípio foi:

“Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações. Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações”

O Princípio da Inversão de Dependências visa reduzir o acoplamento entre os componentes de um sistema, promovendo maior flexibilidade, manutenibilidade e testabilidade.

Problemas que o DIP Resolve

  • Acoplamento rígido: Quando um módulo depende diretamente de uma implementação concreta, mudanças nessa implementação podem afetar outros módulos.
  • Dificuldade de testes: Testar unidades de código acopladas diretamente a implementações específicas é mais complicado, pois exige o uso dessas implementações concretas, dificultando a criação de mocks ou stubs.
  • Baixa reusabilidade: Um módulo altamente acoplado a detalhes concretos é menos reutilizável em outros contextos.

Aplicação Prática

Vamos criar um código responsável por enviar notificações via e-mail, de modo a analisar os problemas e as soluções possíveis para os solucionar

Java

class EmailService {
    public void sendEmail(String message) {
        System.out.println("Sending email: " + message);
    }
}

class Notification {
    private EmailService emailService;

    public Notification() {
        this.emailService = new EmailService();
    }

    public void notify(String message) {
        this.emailService.sendEmail(message);
    }
}

// Uso
public class Main {
    public static void main(String[] args) {
        Notification notification = new Notification();
        notification.notify("Welcome to our service!");
    }
}

Typescript

class EmailService {
    sendEmail(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private emailService: EmailService;

    constructor() {
        this.emailService = new EmailService();
    }

    notify(message: string): void {
        this.emailService.sendEmail(message);
    }
}

// Uso
const notification = new Notification();
notification.notify("Welcome to our service!");

Problemas:

  • A classe Notification depende diretamente de uma implementação concreta (EmailService).
  • Se quisermos mudar o canal de notificação (ex.: SMS), precisamos alterar o código de Notification.

Soluções e Benefícios:

  • Notification não precisa saber detalhes sobre como a mensagem é enviada.
  • Facilidade de substituir ou adicionar novos canais de comunicação.
  • Podemos testar Notification isoladamente, sem depender de implementações reais.

Java

public interface MessageService {
    void sendMessage(String message);
}

public class EmailService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("Sending email: " + message);
    }
}

public class SMSService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("Sending SMS: " + message);
    }
}

public class Notification {
    private final MessageService messageService;

    public Notification(MessageService messageService) {
        this.messageService = messageService;
    }

    public void notify(String message) {
        messageService.sendMessage(message);
    }
}

// Uso
public class Main {
    public static void main(String[] args) {
        Notification emailNotification = new Notification(new EmailService());
        emailNotification.notify("Welcome via Email!");

        Notification smsNotification = new Notification(new SMSService());
        smsNotification.notify("Welcome via SMS!");
    }
}

Typescript

interface MessageService {
    sendMessage(message: string): void;
}

class EmailService implements MessageService {
    sendMessage(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class SMSService implements MessageService {
    sendMessage(message: string): void {
        console.log(`Sending SMS: ${message}`);
    }
}

class Notification {
    private messageService: MessageService;

    constructor(messageService: MessageService) {
        this.messageService = messageService;
    }

    notify(message: string): void {
        this.messageService.sendMessage(message);
    }
}

// Uso
const emailNotification = new Notification(new EmailService());
emailNotification.notify("Welcome via Email!");

const smsNotification = new Notification(new SMSService());
smsNotification.notify("Welcome via SMS!");

3. Testes Unitários

Java

public class MockMessageService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("Mock message sent: " + message);
    }
}

// Teste com o mock
public class Main {
    public static void main(String[] args) {
        MessageService mockMessageService = new MockMessageService();
        Notification mockNotification = new Notification(mockMessageService);
        mockNotification.notify("Test message");
    }
}

Typescript

class MockMessageService implements MessageService {
    sendMessage(message: string): void {
        console.log(`Mock message sent: ${message}`);
    }
}

// Teste com o mock
const mockNotification = new Notification(new MockMessageService());
mockNotification.notify("Test message");

Conclusão

O Princípio da Inversão de Dependências (DIP) é um pilar fundamental para projetos flexíveis e robustos. Ele permite reduzir o acoplamento entre classes, facilitar a reutilização de código e melhorar a testabilidade das aplicações. Ao depender de abstrações, seu sistema se torna mais adaptável a mudanças e expansível com novas funcionalidades. O exemplo prático demonstrou como pequenos ajustes no design podem resolver problemas recorrentes de manutenção. Aplicar o DIP em conjunto com outros princípios SOLID garante um código mais limpo e preparado para o crescimento. Adotar esses conceitos é essencial para desenvolvedores que buscam excelência em arquitetura de software.

Referências Bibliográficas

  • Martin, Robert C. Agile Software Development, Principles, Patterns, and Practices. Prentice Hall, 2002.
  • Thiago Leite e Carvalho. Orientação a Objetos. Casa do Código, 2014.

Navegação de Post

← (I): Aplicando o “Princípio da Segregação da Interface” com Typescript e Java
Princípio da Responsabilidade Única e as implicações na Orientação a Objetos e Arquitetura de Software →

Deixe um comentário Cancelar resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Recent Posts

  • Microsserviços: 5 Lições Aprendidas — Um Olhar Arquitetural
  • 5 Pilares financeiros que destacam negócios de alto valor
  • Princípio da Responsabilidade Única e as implicações na Orientação a Objetos e Arquitetura de Software
  • (D): Aplicando o “Princípio da Inversão de Dependências” com Typescript e Java
  • (I): Aplicando o “Princípio da Segregação da Interface” com Typescript e Java

Archives

  • novembro 2025

Categories

  • Empreendimento (1)
  • Engenharia (9)
  • Finança (2)
  • Java (6)
  • Liderança (1)
  • Orientação a Objetos (8)
  • Programação (9)
  • Programação Estruturada (2)
  • Typescript (8)
© 2025 Reboredo.bit | Powered by Minimalist Blog WordPress Theme