Princípio da Inversão de Dependência (DIP)
Definição
O Princípio da Inversão de Dependência (Dependency Inversion Principle - DIP) propõe que módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações.
Além disso, abstrações não devem depender de detalhes; os detalhes devem depender de abstrações. Esse é o quinto princípio do SOLID, um conjunto de boas práticas para design de software orientado a objetos.
Por que é importante
O DIP ajuda a reduzir o acoplamento entre camadas do sistema. Em vez de uma classe conhecer diretamente as implementações concretas que usa, ela depende de contratos (interfaces ou classes base).
Com isso, é possível trocar implementações sem modificar os módulos que as utilizam, favorecendo testes automatizados, reuso e manutenção.
Exemplo prático (Python)
Considere uma classe que depende diretamente de outra implementação concreta:
# Classe concreta
class EmailService:
def enviar(self, mensagem):
print(f"Enviando email: {mensagem}")
# Classe de alto nível depende diretamente da concreta → viola o DIP
class Notificador:
def __init__(self):
self.servico = EmailService()
def notificar(self, mensagem):
self.servico.enviar(mensagem)
Esse código viola o DIP, pois
Notificador
depende diretamente da classe concreta
EmailService
. Se quisermos usar outro meio de envio (como
SMS), precisamos modificar Notificador
.
Aplicando o DIP, extraímos uma abstração:
from abc import ABC, abstractmethod
# Abstração
class CanalDeNotificacao(ABC):
@abstractmethod
def enviar(self, mensagem):
pass
# Implementações concretas
class EmailService(CanalDeNotificacao):
def enviar(self, mensagem):
print(f"Enviando email: {mensagem}")
class SMSService(CanalDeNotificacao):
def enviar(self, mensagem):
print(f"Enviando SMS: {mensagem}")
# Classe de alto nível depende da abstração → respeita o DIP
class Notificador:
def __init__(self, canal: CanalDeNotificacao):
self.canal = canal
def notificar(self, mensagem):
self.canal.enviar(mensagem)
# Exemplos de uso
notificador_email = Notificador(EmailService())
notificador_email.notificar("Olá por email!")
notificador_sms = Notificador(SMSService())
notificador_sms.notificar("Olá por SMS!")
Agora, Notificador
depende apenas da abstração
CanalDeNotificacao
. Podemos enviar notificações por email,
SMS ou qualquer outro canal,
sem modificar a classe principal.