Princípios SOLID: Princípio da Inversão de Dependência (DIP)

Olá, galera

Chegamos, enfim, ao último post da série sobre os cinco princípios SOLID, o qual abordará o Princípio da Inversão de Dependência (Dependency Inversion Principle), ou simplesmente DIP.

O DIP é base para um bom design orientado a objetos e extremamente importante para o projeto de uma arquitetura de software flexível e focada no domínio.

Então vamos ao que interessa.

DEFINIÇÃO

O DIP diz que:

– 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.

Inverter a dependência faz com que um cliente não fique frágil a mudanças relacionadas a detalhes de implementação. Isto é, alterar o detalhe não quebra o cliente. Além disso, o mesmo cliente pode ser reutilizado com outro detalhe de implementação.

Vamos deixar isso mais claro com exemplos.

EXEMPLO DE VIOLAÇÃO

Vejam o clássico exemplo do botão e da lâmpada, onde ambas as classes Botao e Lampada são classes concretas:

public class Botao
{
    private Lampada _lampada;

    public void Acionar()
    {
        if (condicao)
            _lampada.Ligar();
    }
}

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

Que abstração seria essa? Botao 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.

INVERTENDO A DEPENDÊNCIA

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:

public class Botao
{
    private Dispositivo _dispositivo;

    public void Acionar()
    {
        if (condicao)
            _dispositivo.Ligar();
    }
}

public interface Dispositivo
{
    void Ligar();
    void Desligar();
}

public class Lampada : Dispositivo
{
    public void Ligar()
    {
        // ligar lampada
    }
    public void Desligar()
    {
        // desligar lampada
    }
}

Ilustrando com UML, o que antes era:

botao-lampadaPassa a ser:

botao-lampada-inversao

DIP E ARQUITETURA DE SOFTWARE

O Princípio da Inversão de Dependência é um dos pilares para uma boa arquitetura de software, focada na resolução do problema e flexível quanto a detalhes de implementação, como bancos de dados, serviços web, leitura/escrita de arquivos, etc.

Este princípio reforça que a abstração está mais relacionada ao seu cliente do que ao servidor (a classe que realiza a abstração). No exemplo ilustrado acima, Dispositivo (a abstração) está diretamente ligado ao cliente (Botao). Sua implementação (Lampada) é um mero detalhe.

Sendo assim, Dispositivo ficaria no mesmo pacote (ou componente) do Botao e não junto com sua implementação Lampada. (Esta separação de interface e implementação em componentes distintos é um padrão conhecido por Separated Interface, como catalogado no livro PoEAA, do Martin Fowler.)

Outro exemplo bem comum deste padrão está no uso do padrão Repositório. Neste caso, aplicamos o DIP para que nosso domínio dependa de uma abstração do Repositório, ficando totalmente isolado de detalhes sobre persistência:

separatedinterface

Levando a interface para junto do cliente, estamos dizendo “o cliente funciona dessa maneira” e quem implementa a interface (em outro componente) é que deve atender a essa exigência. Ou seja, a interface só mudará por necessidade DO CLIENTE.

Por fim, quando há vários clientes em componentes distintos para a mesma interface, esta fica em um componente a parte. Voltando ao exemplo do Botao, ao colocar Dispositivo em um componente próprio (nem com o cliente nem com o servidor), ele poderia ser utilizado por Botao e por qualquer outro objeto capaz de ligar/desligar um dispositivo:

separatedinterface-compseparado

CONCLUSÃO

O Princípio da Inversão de Dependência é um princípio essencial para um bom design orientado a objetos, ao passo que o oposto leva a um design engessado e procedural.

Identificar abstrações e inverter as dependências garantem que o software seja mais flexível e robusto, estando melhor preparado para mudanças.

Encerramos assim a série sobre os princípios SOLID, que juntos formam um conjunto de boas práticas que devemos ter em nosso cinto de utilidades e que devemos aplicar sempre que pudermos para melhorar a qualidade do design e da arquitetura do software.

Retornarei a estes princípios em posts futuros.

Espero que tenham gostado. Aguardo feedback!

Até!
—————————–

Toda a série:
Princípio da Responsabilidade Única (SRP)
Princípio do Aberto/Fechado (OCP)
Princípio da Substituição de Liskov (LSP)
Princípio da Segregação de Interface (ISP)
Princípio da Inversão de Dependência (DIP)

Anúncios

23 comentários em “Princípios SOLID: Princípio da Inversão de Dependência (DIP)

  1. Eai Castilho, tudo bem ?
    Poderia mostrar em um post futuro, como realizar DI através de um Container.

    Abraços.

    1. Olá, alguém (tem nome? 🙂 )
      Tenho que dar vazão a uns rascunhos e aí formulo algo.
      Não tem segredo.
      Você basicamente precisa configurar o container no ponto de entrada da app. Em uma app ASP.NET MVC, este ponto é o global.asax, onde você define seu custom Controller Factory.
      Também existe o pacote Ninject.MVC3 (NuGet) que agiliza ainda mais para uso com o Ninject (sem a criação de um ControllerFactory).

      []s!

  2. se no caso a interface dispositivo fosse uma classe abstrata, eu estaria violando o princípio de inversão de dependêmcia?

  3. Você explica muito bem, parabéns, consegui entender esses princípios só depois que li sua explicação!

  4. Nossa muito show essa serie sobre SOLID.
    Entendi mais aqui do que com meu professor.

    Obrigado, sempre estarei acompanhando seu site e post.

  5. Estou usando vários de seus exemplos da “trilha” SOLID em minha aulas na HighTech. Os alunos entendem com muita facilidade. Obrigado pelo compartilhamento de conhecimento. Admiro muito seu trabalho.

  6. Excelente série! Clara, simples e objetiva! Vai ajudar bastante a pensar de forma diferente antes de iniciar um projeto.

Participe! Vamos trocar uma ideia sobre desenvolvimento de software!

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s