Fala ai Radizeiros e Radizeiras, tudo bem com vocês?

Neste post estarei mostrando mais um conceito do SOLID, onde estarei falando sobre o DIP – Princípio da inversão de dependência.

O que é o DIP?

Ele é muito importante quando queremos reduzir acoplamento, aumentar a coesão, escrever códigos concisos, códigos que sigam as boas práticas.

O princípio da inversão de dependência é fundamental para a manutenção do nosso software ficar mais fácil e coeso.

O DIP mata em muito de seus processos, por exemplo a questão da herança, eu sempre falo que “herança é uma carta que devemos usar uma única vez”, passou disso começa não ser uma boa prática.

DIP possui dois conceitos que devemos aplicar:

  1. As classes maiores, módulos maiores em seu software não devem depender de módulos menores, de classes menores, todos os dois devem depender de interfaces.
  2. Você já abstrai toda a complexidade para uma interface, métodos e tudo mais, você não tem mais dependência de classes maiores ou menores, as abstrações não devem depender dos detalhes que estão implícitos e sim os  detalhes depender das abstrações.

 

Mas como isso é feito?

Em nosso exemplo irei mostrar de como a inversão de dependência reduz o acoplamento dentro do seu código.

Eu tenho duas classes que são TLampada e TBotao.


TLampada = class
    procedure Ligar;
    procedure Desligar;
end;

TBotao = class
    Lampada = TLampada;
    constructor Create;
    procedure Acionar;
end;
...
procedure TBotao.Acionar;
begin
    Lampada.Ligar;
end;

constructor TBotao.Create;
begin
    Lampada := TLampada.Create;
end;

Podemos observar que neste nosso código as dependências que estamos criando, por exemplo, na minha classe TBotao precisa conhecer a lampada, e esse meu botão só serve para ligar a lampada, imagine então que eu tenha um ventilador, esse botão não poderia pegar o botão do mesmo tipo e utilizar no ventilador, porque ele está amarrado na minha lampada, neste ponto eu não poderei reutilizar por causa de dependência.

Como resolveríamos essas dependências?

Nós faríamos da seguinte forma:


iDispositivo = interface
    ['{07B0D206-0BC5-4DFA-9EC6-3666EE56EDDE}']
    procedure Ligar;
    procedure Desligar;
end;

TLampada = class(TInterfacedObject, iDispositivo)
    procedure Ligar;
    procedure Desligar;
end;

TBotao = class
    FDispositivo : iDispositivo;
    constructor Create(Dispositivo : iDispositivo);
    procedure Acionar;
end;
...
procedure TBotao.Acionar;
begin
    FDispositivo.Ligar;
end;

constructor TBotao.Create(Dispositivo : iDispositivo);
begin
    FDispositivo := Dispositivo;
end;
...
procedure TLampada.Desligar;
begin
    ShowMessage('Lampada Desligada');
end;

procedure TLampada.Ligar;
begin
    ShowMessage('Lampada Ligada');
end;

Nós colocamos o botão para que ele ligue um dispositivo, não importa qual seja esse dispositivo, ele simplesmente irá ligar e desligar um dispositivo, ou seja, o dispositivo que estiver com os métodos Ligar Desligar ele pode ser utilizado no botão.

Por este motivo nós criamos uma interface iDispositivo e a classe TLampada implementa a interface, por ser um dispositivo.

Na classe TBotao, simplesmente criamos um objeto do tipo iDisponsitivo,  e em seu create passamos por parâmetro essa interface.

No método Acionar ele simplesmente irá ligar e desligar pelo fato dele está implementando uma interface.

Nós invertemos a dependência, o nosso botão agora não depende mais da lampada, ele simplesmente precisa receber um dispositivo.

Se depois eu quiser implementar uma classe de outro dispositivo, como por exemplo um TVentilador.


...
TVentilador = class(TInterfacedObject, iDispositivo)
    procedure Ligar;
    procedure Desligar;
end;
...
procedure TVentilador.Desligar;
begin
    ShowMessage('Ventilador Desligado');
end;

procedure TVentilador.Ligar;
begin
    ShowMessage('Ventilador Ligado');
end;

Agora nós podemos utilizar nosso botão para trabalhar com qualquer ação.

Em nosso exemplo no botão de ligar lampada implementamos simplesmente dessa forma:


procedure TForm4.Button1Click(Sender: TObject);
begin
    TBotao.Create(TLampada.Create).Acionar;
end;

Onde no create do nosso botão precisa receber um dispositivo, sendo assim como irei ligar a lampada passo a minha classe TLampada.

Da mesma forma podemos fazer para ligar o ventilador.


procedure TForm4.Button2Click(Sender: TObject);
begin
    TBotao.Create(TVentilador.Create).Acionar;
end;

Agora eu estou utilizando o mesmo botão para acionar métodos em dispositivos diferente, coisa que não era possivel quando criamos a nossa dependência entre esses objetos.

Viu como é simples a inversão de dependência.

Agente não injeta a dependência ali dentro, nós criamos uma interface abstraindo tudo isso.

Uma classe maior não pode depender de uma classe menor, o primeiro conceito do DIP, e o segundo, abstrações não podem depender de detalhes, mas os detalhes dependem das abstrações, em nosso exemplo nós temos os detalhe de ligar e desligar da nossa abstração, mas o detalhe do nosso dispositivo é que depende da abstração e não a abstração dependendo desse detalhe.

Seguindo esses conceitos você reduzirá até 100% o retrabalho em seu software.

Este post foi retirado de um dos meus treinamentos o SOLID no Delphi.

O QUE VOCÊ IRÁ APRENDER?

O treinamento de SOLID dará a você a oportunidade de melhorar seu desenvolvimento, otimizar o seu tempo e te dar a possibilidade de atender melhor os seus clientes.
Implementar e refatorar suas rotinas de código seguindo os padrões SOLID e utilizar todos os seus benefícios irá facilitar muito a sua vida, quando seu cliente disser “toda atualização é uma surpresa diferente, algo novo não funciona e o que funcionava para de funcionar, não aguento mais isso”.

Você estará preparado para entregar uma solução robusta e eficaz. Nesse treinamento você irá aprender de forma prática a dominar as técnicas de boas praticas de programação com SOLID, para ter um código organizador e de fácil manutenção.

CLIQUE AQUI E SAIBA MAIS SOBRE O TREINAMENTO SOLID NO DELPHI.