Arquitetura de SoftwareProgramação

S.O.L.I.D na prática: Dependency Inversion Principle (DIP)

Chegamos juntos ao quinto princípio SOLID e também o sexto e último post da série “SOLID na prática”. \o/

Para você que chegou até aqui e acompanhou os conteúdos da série, já fica aqui meu agradecimento e parabenização pela dedicação. Bora seguir nesse último post da série e em todos os próximos conteúdos, no aprendizado e desenvolvimento contínuo. \o/ (“Tamo junto!”).

Neste post veremos o Dependency Inversion Principle (DIP) – Princípio da Inversão de Dependência, que corresponde a letra D (quinta letra) do acrônimo SOLID.

O que é o Dependency Inversion Principle (DIP)?

O Princípio da Inversão de Dependência, diz que:

“Os sistemas mais flexíveis são aqueles em que as dependências de código-fonte se referem apenas a abstrações e não a itens concretos.

Robert C. Martin

Eu um “resumão”, para você lembrar seria o mesmo que dizer que: “Dependa de abstrações ao invés de depender de implementações“.

Podemos entender então que, o código de uma classe, por exemplo, deve depender (ou “fazer referência”) apenas a módulos-fonte que contenham abstrações, como interfaces e classes abstratas.

A ideia geral é que devemos sempre evitar a dependência de elementos que são voláteis, ou seja, que tendem a sofrer mais alterações, como por exemplo a implementação de classes (concretas), que normalmente podem sofrer mais mudanças em menos tempo. Ao contrário das abstrações que tendem a sofrer menos alterações ao longo do tempo.

Para refletir mais um pouquinho vou deixar a seguinte questão?

Para manutenção de um software, você acha mais seguro depender de algo que muda menos ou de algo que muda constantemente?

Mas por quêinversão de dependência“?

Muitas vezes pode ocorrer que em uma estrutura de código, os módulos de alto nível tenham dependência de módulos de nível mais baixo.

Lembrando que os “módulos” correspondem as partes de um sistema e essas partes precisam interagir entre si. Nesse sentido, podemos entender que um aplicação é composta de 2 tipos de módulos: os módulos de alto nível e os módulos de baixo nível.

  • Os módulos de alto nível correspondem a parte que contém as funcionalidades principais da aplicação. Normalmente associado a regras de negócio (interfaces e classes principais);
  • Os módulos de baixo nível correspondem aos detalhes que ajudam a compor os módulos de alto nível. Normalmente são as funcionalidades complementares (infra, conexões com banco de dados, extensões, configurações extras, etc.)

Para realizar a interação entre um módulo e outro é necessário estabelecer uma relação de dependência entre eles. Essa relação nem sempre é bem definida e pode gerar problemas como baixa coesão e/ou alto acoplamento entre os módulos. Podemos pensar aqui naquelas classes que tem dependências explícitas de outras. Sabe aquele clássico “new ( ) ” no meio do código de uma classe para instanciar objeto de outra classe, que irá precisar (e depender)!? …Pois é… Devemos evitá-lo. Se não entendeu bem essa parte, não se preocupe, segue um pequeno exemplo/lembrete abaixo (em C#) e no vídeo a seguir também falo sobre isso.

{
// outro código

var novoObjeto = new ClasseQueVouPrecisarBaixoNivel( ); // exemplo instanciando uma classe de baixo nível – violação do DIP

// outro código
}

A situação do exemplo acima é apenas um dos vários casos de dependência de uma classe concreta. Neste caso então temos uma dependência forte e um alto acoplamento entre essas classes e vale ressaltar que, quaisquer alterações nessas dependências, podem afetar as classes que as utilizam.

Portanto, o termo inversão é usado para se referir a “inversão na maneira de pensarmos” em projetos de software orientados a objetos, já que muitas vezes, de forma quase que natural, tendemos a criar dependências indesejadas entre os objetos. Observe que o simples ato de instanciar uma classe já pode gerar algum tipo de problema com dependência.

Por esse motivo é que o princípio (DIP), recomenda que os módulos devem contar com uma camada de abstração para interagir entre si. Dessa forma, as alterações nos módulos de baixo nível (detalhes de implementação) não afetariam os módulos de alto nível (funcionalidades principais), o que também significa redução do acoplamento, redução da fragilidade a mudanças no código e redução no custo com manutenção de software.

Então, quando temos uma mudança (favorável) na direção dessas dependências, ou seja, temos as dependências invertidas entre os módulos, com o bom uso de abstrações, torna-se mais fácil substituir ou estender diretamente as implementações específicas de baixo nível.

Em resumo, o lembrete então é:

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

Para entender mais sobre esses conceitos por trás do DIP e ver um exemplo prático, veja o vídeo a seguir.

Clique aqui caso queira acessar o primeiro post da série sobre SOLID

Finalmente, então chegamos ao fim da série aqui no site e lá no canal. Mas os conteúdos por aqui estão só começando. Aproveita e já deixa seu comentário aqui e lá no vídeo sobre esse assunto ou outro que queira sugerir para os próximos posts ou vídeos.

Então, conto com aquele seu apoio nos likes, compartilhamentos, comentários, sugestões. Vamos juntos! 😉

Deixe um comentário

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