quinta-feira, 14 de julho de 2016

O que é inversão de Dependência?

Princípio da Inversão de Dependência (Dependency Inversion Principle), ou simplesmente DIP, faz parte do principio SOLID:
  • Single Responsabilty Principle
  • Open/Closed
  • Liskov Substitution Principle
  • Interface Segregation
  • Dependency Inversion Principle
Definição:
  • 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.
Vantagens:
  • Melhora na manutenibilidade, pois o código fica mais flexível e reutilizável.
  • Melhora na testabilidade, pois não precisamos conhecer detalhes da dependência.
Exemplo:
O clássico exemplo do botão e da lâmpada, onde ambas as classes são concretas:

1
2
3
4
5
6
7
8
9
10
public class Botao
{
    private Lampada lampada;
    public void Acionar()
    {
        if (condicao)
            lampada.Ligar();
    }
}

O design acima viola o DIP uma vez que Botão depende de uma classe concreta Lampada. Ou seja, Botão conhece detalhes de implementação ao invés de termos identificado uma abstração para o design.

Que abstração seria essa? Botão deve ser capaz de tratar alguma ação e ligar ou desligar algum dispositivo, seja ele qual for: uma lâmpada, um motor, um alarme, etc.

Aplicando o DIP:

A solução abaixo inverte a dependência de botão para a lâmpada, fazendo com que ambos agora dependam da abstração Dispositivo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Botao
{
    private Dispositivo dispositivo;
    public void Acionar()
    {
        if (condicao)
            dispositivo.Ligar();
    }
}
public interface Dispositivo
{
    void Ligar();
    void Desligar();
}
public class Lampada implements Dispositivo
{
    public void Ligar()
    {
        // ligar lampada
    }
    public void Desligar()
    {
        // desligar lampada
    }
}

O Princípio da Inversão de Dependência é um princípio essencial para um bom design orientado a objetos, focada na resolução do problema e flexível quanto a detalhes de implementação. Identificar abstrações e inverter as dependências garantem que o software seja mais flexível e robusto, estando melhor preparado para mudanças.

2 comentários:

  1. O exemplo mais bacana de todos, no Java, é quando alguém referencia uma ArrayList ou LinkedList ou qualquer implementação da interface List. Em alguns momentos pode ser interessante pois a classe que está utilizando vai usar apenas aquela implementação em específico, porém, e se um dia todos os "clientes" que usam essa classe precisarem mudar para uma outra implementação da lista? Não conseguem...

    Esse, com certeza, é um dos princípios que qualquer programador OO precisa saber.

    Muito bom o post :)

    ResponderExcluir