Nesta sexta-feira os estagiários do nosso time fizeram apresentações sobre os princípios SOLID para o time. O D acabou “sobrando” para mim, pois são apenas quatro estagiários. Eu fiz uma apresentação bem simples, quase simplista. Mas como o material já estava pronto, decidi colocar aqui no blog.
Disclaimer: Este código é um simples exemplo cuja única motivação é apresentar o princípio em questão. Tentar utilizá-lo pode causar dor de cabeça, impotência sexual e outras complicações.
Dependency Inversion Principle
Vamos considerar um exemplo simples de aplicação que copia mensagens do console e as escreve novamente no console.
No dia seguinte é necessário adicionar uma nova funcionalidade, a opção de copiar para o Clipboard ao invés do Console. Posso utilizar uma enumeração como um discriminador do output desejado.
Para isto preciso alterar a função que implementa minhas regras de negócio (vamos fingir que existe algum valor em copiar mensagens). O motivo é que minha classe, que está em nível de abstração mais alto depende diretamente de uma classe de um nível mais baixo de abstração.
O “Dependency inversion principle” nos diz que:
Ou seja, módulos de alto nível não devem depender de módulo de baixo nível, mas sim de abstrações, algo como:

Então para aplicar o princípio em meu exemplo, seria necessário abstrair as atividades de mais baixo nível.
Abstraindo a atividade de escrever a mensagem
Utilizando uma interface abstraio a função de escrever a mensagem. Meu módulo de alto nível não sabe mais como imprimir a mensagem no console, conhece apenas a abstração.

Para atender os requisitos, implemento dois writers concretos:

Agora abstraio a função de ler, que também está ligada a módulos de níveis mais baixos.
O código cliente, o que utiliza a minha API, fica deste jeito:

Repare que minha solução aumenta a complexidade neste código, agora o cliente precisa saber qual “escritor” e qual “leitor” utilizar. É um trade-off que você deve decidir se vale a pena, ou não.
Design é tentar maximizar as escolhas e os trade-offs. Dificilmente você irá encontrar decisões sem pontos negativos. Se você não consegue encontrá-los, procure melhor, eles devem estar escondidos em algum lugar.