O que não te contaram sobre Clean Architecture
Não, este não é só mais um post sobre Clean Architecture. Nesta grande imensidão que é a internet, você já pode encontrar centenas de artigos e posts falando sobre essa queridinha do famoso Uncle Bob, textos que na maioria das vezes simplesmente repetem o que já está escrito em seu livro, que não surpreendentemente é o chamado Clean Architecture. Logo, se já existem centenas de pessoas repetindo as mesmas coisas, porque deveríamos fazer isso aqui também? Por isso, meu caro leitor, venho lhe apresentar algo um pouco diferente do que você vai encontrar por ai, e espero que seja possível te ajudar a sanar dúvidas que eu também tive, mas que são difíceis de se achar uma resposta que não seja totalmente abstrata, isto é, um famoso copy/paste do livro.
Antes de começarmos de fato, creio que seja viável acrescentar um aviso de que este não é um artigo com o intuito de ser um tutorial e/ou te apresentar conceitos básicos sobre o assunto. No caso, este artigo é mais direcionado àqueles que já conhecem um pouco sobre Clean Architecture e seus princípios, mas que ainda têm dúvidas sobre o assunto. Em resumo: algumas coisas serão faladas considerando que você já as conheça.
Para começar: Code must be SOLID
Ei, espera ai! Não iamos falar sobre Clean Architecture? Você deve estar se perguntando. A resposta para sua pergunta é SIM! E falarmos sobre os principíos de design ditados pelo SOLID é muito importante, pois estão intimamente ligados com a ideia proposta pela Clean Architecture. E não, não vou só te explicar o que é Clean Code, isso fica para outro dia, temos algo mais interessante para hoje. Bora lá?
Bom, os principios do SOLID basicamente têm a ideia de definir como devemos organizar nosso código, isto é, funções, classes e interfaces e de como as interconectar. Desta forma, podemos escrever código tolerante a mudanças, fácil de entender e que, possivelmente, possa ser reutilizado em diversos sistemas diferentes.
Mas como foi dito, não estamos aqui para falar necessariamente sobre Clean Code, e se você chegou até aqui, provavelmente também já ouviu falar muitas vezes sobre isso… Mas tá bom, vamos pelo menos refrescar um pouco suas lembranças o que cada letra do SOLID significa.
S-ingle Responsability Principle: um módulo do seu software deve ter uma, e somente uma, razão para mudar.
Ei, calma, calma, calma, você provavelmente deve estar achando que errei já na primeira letra, né? É óbvio que na verdade esse princípio diz que uma função deve realizar uma, e apenas uma, tarefa, né? Pois é meu caro leitor, essa ideia existe sim, mas vem do Clean Code, e não tem nada a ver com o Single Responsability Principle. Na verdade, o princípio diz exatamente o que escrevi, que um módulo da sua aplicação deve mudar somente por uma razão. Mas qual razão seria essa? Bom, a razão são os atores na sua aplicação. Mais especificamente, podemos dizer que um módulo da sua aplicação deve ser responsável por um, e apenas um, ator. Mas o que seria um ator? Bom, um ator pode ser uma pessoa ou um grupo de pessoas que desejam mudanças em um sistema.
Exemplo: você possui uma loja online, onde existem dois tipos de usuário, o admin e o cliente. Neste caso, nossos atores serão os administradores e clientes. Desta forma, funções do admin não devem ser diretamente misturadas com funções do cliente, pois o módulo que encapsula tais funções teria duas razões para mudar, tanto por mudança de requisitos para o admin, quanto por mudança de requisitos para o cliente.
Este princípio é comumente mal interpretado, e espero ter te trazido uma nova visão… Agora bora continuar, pois ainda não acabamos.
O-pen Closed Principle: um artefato de software deve ser aberto para extensão, mas fechado para modificações.
Bom, desta vez não temos nenhuma surpresa, o que você já conhece sobre tal princípio, possivelmente é verdade. Em resumo, queremos um software que seja facilmente extensível sem a necessidade de fazer grandes alterações no sistema. No mais, recomendo também o velho bom senso.
Na verdade, daqui em diante não há mais surpresas em relação aos princípios do SOLID especificamente, mas não vamos terminar sem ter acabado, certo?
L-iscov Substitution Principle: explicar este princípio mereceria um artigo por si só, mas para não desviarmos muito do foco, vamos nos limitar a dizer aqui (por favor, não entenda o que vou falar de forma literal hein), que a ideia é que, através de polimorfismo, o subtipo T de um tipo de dado P possa ser substituido no lugar de P no sistema de forma que o comportamento não mude, isto é, sem precisar ficar alterando seu código (uffa).
I-nterface Segregation Principle: basicamente, você não deveria estar passando para suas funções mais do que elas necessitam, pois isso pode gerar problemas que você não espera.
Isso não é algo muito seguido, não é mesmo? É muito comum vermos códigos em que objetos inteiros são passados para uma função, mas que apenas um ou outro campo do objeto são utilizados de fato.
D-ependency Inversion Principle: bom, meu caro leitor, este é o clássico princípio que diz que seu sistema, para ser flexível, deve depender de abstrações, e não de concretudes. Obviamente, na prática é quase que impossível seguir totalmente este princípio, mas use ele sempre que puder.
A partir deste princípio que temos também a ideia de dependency injection, que é um dos fortes aliados na Clean Architecture.
Falando de Clean Architecture…
Deixa eu te contar agora sobre um grande erro que nós desenvolvedores muitas vezes costumamos cometer, erro este que na verdade deve ser evitado em possivelmente qualquer arquitetura de software que você esteja desejando utilizar, ou seja, não estamos nos limitando a Clean Architecture.
O pecado da duplicação
Navegando pelos sete mares do desenvolvimento de software, você sempre vai encontrar algum dev que vive com medo do pecado da duplicação (ótimo nome, né?). Este desenvolvedor não aguenta ver nem mesmo uma única linha de código duplicada em dois lugares diferentes que já se sente desesperado e achando que seu código não é Clean, pois não está cumprindo a regra do DRY (Don’t repeat yourself).
Bom, tal dev não está totalmente errado. Duplicação no código é ruim, e sempre que possível devemos evitá-la. Contudo, isso só é válido se temos uma duplicação verdadeira.
Uma duplicação verdadeira é aquela em que toda mudança em uma instância de código precisa ser replicada para todas as outras instâncias de código que são consideradas duplicatas.
Por outro lado, existe também a chamada duplicação falsa, onde duas seções de código iguais só são iguais naquele determinado instante. Isto é, em um certo ponto do seu software os códigos podem ser literalmente iguais, mas em um momento futuro, com implementação de novos requisitos, tais código vão seguir caminhos totalmente diferentes, e já não mais serão iguais.
É neste ponto da duplicação falsa que muitos desenvolvedores pecam, pois ficam tentados a compartilhar código através de uma só fonte no código, mas quando o futuro chega, percebem que cometeram um grande erro. Para implementar novos requisitos, será necessário encher o código de condicionais ou, como última solução, refatorar o código para separar novamente a falsa duplicação em duas fontes diferentes.
Ué, mas escritor, você não disse que não ia falar sobre Clean Code?? Ora, nesta área de computação muitas coisas estão relacionadas, e este princípio sobre duplicação tem influência tanto em quão clean é seu código, quanto em quão clean é sua arquitetura. Quando falamos sobre Clean Architecture, falamos também sobre a independência entre componentes do seu código, e se você quebra tal independência cometendo o pecado da duplicação, consequentemente está prejudicando sua arquitetura.
Já acabou?
Confesso que quando comecei a escrever este artigo, achei que daria para expressar tudo o que eu desejava sobre Clean Architecture, de uma só vez. Porém, conforme fui escrevendo notei que geralmente existem certas falhas de entendimento já no início da teoria desta arquitetura, e me senti na obrigação de começar por elas.
Agora convenhamos meu caro leitor, se eu que escrevi esse texto já estou começando a achar que ficou grande demais, aposto também que você já deve estar ficando entediado.
E olha que ainda temos muito sobre o que falar:
- O que realmente são as entities em Clean Architecture?
- O que são use cases? Qual a diferença entre services e use cases?
- Controllers? Adapters? Ports?
- External devices? Detalhes de implementação?
Então que tal me esperar para uma parte 2? Responderemos as questões acima de forma assertiva, diferentemente do que você encontra por artigos e discussões na internet, onde as respostas de tais perguntas são geralmente abstratas e difíceis de entender.
Obrigado pela atenção, até a próxima :)