Este é o quinto e último artigo da série Princípios SOLID – Boas práticas de programação com C#. Nele falaremos da última letra do acrônimo do SOLID: DIP – Dependency Inversion Principle. Você pode ler o artigo anterior clicando aqui.
Princípio da Inversão da Dependência: módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações.
Na Orientação a Objetos, todo o fluxo do mundo real é abstraído para o código se comportar o mais semelhante possível com a realidade. O princípio DIP é mais uma forma de organização para melhorar essa codificação da realidade: dependa somente de abstrações e não de implementação.
Isso gera um ganho enorme para desacoplamento entre as classes, uma vez que, se o comportamento de uma mudar, a outra não sofrerá impacto já que depende somente da abstração.
Acoplamentos sempre existirão, agora, o que vale a pena ponderar é a qualidade desses acoplamentos. Logo, depender de abstrações ou de classes estáveis é o ideal, porque a mudança não impactará em quem os está utilizando.
Retornando à solução proposta no primeiro princípio do SRP, ainda há o que melhorar. Observe que a classe FuncionarioServices está diretamente dependente da implementação de Funcionario e EmailServices. Caso alguma dessas duas sejam alteradas, nossa classe FuncionarioServices também sofrerá alteração. Utilizar a inversão de dependência nesse caso faria com que a dependência das classes Funcionario e EmailServices fosse invertida, removendo essa responsabilidade de FuncionarioServices.
Uma forma de realizar essa alteração é utilizar a injeção de dependência, que é basicamente fazer com que a FuncionarioServices utilize apenas a abstração das classes que ela precisa para funcionar. Isso é feito injetando a dependência pelo construtor, como segue:
public class FuncionarioServices : IFuncionarioServices { private readonly IFuncionarioRepository funcionarioRepository; private readonly IEmailServices emailServices; public FuncionarioServices( IEmailServices emailServices, IFuncionarioRepository funcionarioRepository) { this.emailServices = emailServices; this.funcionarioRepository = funcionarioRepository; } public string AdicionarFuncionario(Funcionario funcionario) { if (!funcionario.Validar()) return "Dados inválidos"; this.funcionarioRepository.AdicionarFuncionario(funcionario); this.emailServices.Enviar("[email protected]", funcionario.Email.Endereco, "Bem Vindo", "Parabéns está Cadastrado"); return "Funcionario cadastrado com sucesso"; } }
Os princípios do SOLID se complementam, e como podemos ver nesse caso, para aplicar a inversão de dependência é preciso programar orientado a interfaces (conforme prega o ISP) além do SRP, uma vez que agora cada classe ficará responsável por ter somente uma única responsabilidade. Dessa forma conseguimos depender somente das abstrações necessárias (IEmailServices e IFuncionarioRepository):
public interface IEmailServices { void Enviar(string de, string para, string assunto, string mensagem); }
public interface IFuncionarioRepository { void AdicionarFuncionario(Funcionario funcionario); }
public interface IFuncionarioServices { string AdicionarFuncionario(Funcionario funcionario); }
Assim, definimos todos os contratos estabelecidos para que cada classe implemente seguindo a regra de negócio.
A dica aqui é:
- Não dependa de implementações, dependa de abstrações.
Conclusão
O SOLID é uma diretriz para a construção de código mais enxuto e legível. Isso ajuda muito na manutenção futura (afinal o mundo é dinâmico e quem nunca escutou um “será que você poderia fazer essa alteraçãozinha pequena aqui pra mim?”). Precisamos lembrar sempre que desenvolvemos sistemas não apenas para cumprir o prazo, mas para facilitar essa manutenção. Além do mais, aplicar o SOLID também é importante para facilitar a escalabilidade do negócio. É importante lembrar também que, embora os exemplos foram feitos em C#, as regras macros do SOLID são aplicáveis para toda e qualquer linguagem que utilize OO e em alguns casos na funcional também (como o SRP).
Os princípios servem para direcionar o pensamento durante a codificação. Mas é sempre adaptável à realidade que você está. Tudo deve ser feito com ponderação e pensamento crítico ao contexto em que você está desenvolvendo.
Caso não tenha acompanhado a série, é possível acompanhar pelos links abaixo:
- Parte 1: SRP – Single Responability Principle
- Parte 2: OCP – Open Closed Principle
- Parte 3: LSP – Liskovs Substitution Principle
- Parte 4: ISP – Interface Segregation Principle
Referências
The Single Responsibility Principle
.NET – Princípios SOLID – Princípio da Inversão da Dependência
PIRES, E. SOLID: Teoria e Prática.
ANICHE, M. Orientação a Objetos e SOLID para ninjas. São Paulo – Casa do Código
MARTIN, C. R. Código Limpo – Habilidades Práticas do Agile Software. Rio de Janeiro 2011 – Alta Books.
Samyla Dutra
Mineira, atuo na área de desenvolvimento desde 2017 e sou graduada em Engenharia de Computação pelo CEFET-MG. Gosto de entender a profundidade do backend e como melhorar a escrita de código. E isso se torna melhor em equipe! Amo estar em contato com a natureza, trilhar montanhas, ler livros e cozinhar.