Resumindo [muito] a Arquitetura Limpa

Wanderley Neto
6 min readApr 1, 2023

--

Se você está aqui, imagino que conheça o guru tech pop Robert Martin — Uncle Bob para os [não tão] íntimos. Estou lendo o livro “Arquitetura Limpa” dele e estou achando fantástico, muitos dos conceitos já estou tentando aplicar no meu dia-a-dia [Mesma sensação de quando li o “Codificador Limpo” do mesmo autor]. Ele fala sobre formas de se construir aplicações que sejam simples de manter e de mudar ao longo do tempo. Que durem mais que as mudanças que a tecnologia muitas vezes nos impõe custando o menos possível. Deviam ser leituras obrigatórias pra quem se interessa por programação.

Vou tentar resumir os conceitos que achei mais interessantes:

Primeiro: Adie decisões caras o máximo possível

Eu, sempre que queria estudar um tema novo, ou criar uma aplicação simples para praticar alguma coisa tinha um problema: Eu definia e instalava um gerenciador de banco de dados na minha máquina. Obviamente isso era bem chato [e deixava o note pesadão], mas se não fizesse não conseguiria ver o resultado do estudo.

Na vida real, não é muito diferente. Uma das primeiras decisões ao se implantar um novo sistema é a forma de armazenamento dos dados. Ou a forma de comunicação com o meio externo. Usaremos API Rest? importação de arquivos? O banco de dados vai relacional? Conseguimos usar o Mongo?

Essas decisões geralmente são complexas e podem nos custar caro se não planejadas adequadamente.

Uma das idéias apresentadas no livro Arquitetura Limpa, é que decisões como essas se tornem “detalhes” da aplicações. Vamos adiar a escolha do banco o máximo possível até termos certeza de que um banco de dados relacional é necessário, por exemplo. Ou que a comunicação via API Rest é a melhor.

Teríamos que trabalhar com foco em abstrações que permitam que esses “detalhes” sejam alterados sem afetar o coração da aplicação: a regra de negócio.

Pense nessas tecnologias como plug-ins que a gente pluga e despluga do sistema 🤯

Segundo: Arquitetura de Software é planejamento, não é UML

Na faculdade eu tinha uma matéria de Arquitetura de Software, confesso que detestava… Aqui a primeira surpresa: Arquitetura de software tem a ver com planejar como resolveremos o problema do nosso cliente [e isso é legal!]. A UML pode ser uma boa ferramenta, mas não passa disso: uma ferramenta. O principal pilar aqui é pensar que o software tem uma vida útil e a nossa tarefa é extender isso pelo máximo de tempo que conseguirmos. Nosso software tem que prever manutenções e mudanças — E acredite: Elas virão mais cedo ou mais tarde, esteja preparado!

Como prever mudanças? Como se preparar?

Terceira: Regra de dependências

Aqui o principal tópico debatido no livro. Robert nos convida a sair da nossa caixinha de tecniquês e enxergar o negócio e as abstrações que ele possui.

Partimos do princípio de que o negócio é mais “durável” que a tecnologia que o suporta.

Como assim?

Vamos fazer uma breve viagem:

Há algumas poucas décadas programadores atuavam em mainframes, programavam em C e Fortran, usavam código de baixo nível com ponteiros direto na mémória, tinham que pensar a nível de processo. Os recursos eram caros e escassos, cada byte contava. Os programas eram processadores de cálculos de grandes pilhas de dados.

Há não mais que 30 anos (alguns dos meus colegas são dessa época), os recursos ficaram mais baratos, a moda eram aplicações desktop com interface gráfica rudimentar, logo veio a arquitetura client-server.

Com o advento da internet e melhora das estruturas de redes surgiu a arquitetura orientada a serviços.

Hoje (e eu já posso estar desatualizado) a moda da vez são os micro-serviços, containers e tudo está na nuvem.

Agora pense em uma empresa de 30 anos. Provavelmente seu core-business não mudou, ou mudou muito pouco. Isso é apenas para ilustrar que a tecnologia muda muito mais rápido que o negócio que ela apoia.

a tecnologia não para…

Tendo essa premissa em mente, separamos em primeiro lugar o que é negócio do que é tecnologia. Depois definimos uma ordem de dependência. Quanto mais suscetível às mudanças tecnológicas, mais superficial é a camada, menor é o seu nível de abstração e mais dependente das camadas internas ela é.

Como separar nossas camadas?

A regra básica é: a camada mais baixa (ou mais interna) não pode saber nada, e nem vai se preocupar, com camada mais alta (ou mais externa).

A sugestão de Robert são 4 camadas iniciais. Elas podem variar mas esse número deve atender a maioria dos cenários.

Seriam elas:

Entidades: Camada mais profunda do nosso modelo. Contem os dados primordiais do negócio e regra que não dependem do uso do sistema.

Casos de Uso: São as ações realizadas pelo nosso sistema, um caso de uso pode manipular diversas entidades para chegar em um resultado que será apresentado ao usuário no final do processamento.

Adaptadores: A camada que traduz os dados da camada mais externa para um formato adequado aos casos de uso.

Inteface: É a camada que se comunica com o mundo, possui UI, API’s, banco de dados.

Image by Robert C. Martin

Vou tentar exemplificar:

Pense em uma entidade Cliente, cujo um dós métodos implementados seja o avaliarCredito(). Essa entidade muda muito pouco se comparado com o mundo externo, assim como as regras para calcular o crédito desse cliente. Note que a entidade cliente e suas informações de crédito existiriam mesmo se não houvesse nenhum sistema. Ela é puro Negócio.

Agora pense o que sistema pode fazer com essa entidade: Poderíamos ter o caso de uso LiberarPedido() ou o usecase BloquearClientePorCredito(), que usariam, entre outras entidades, a Cliente e seus informações de crédito. Note que são dados que existem para ser usados por outras rotinas do sistema e os useCases fazem a “dança das entidades” para obter algum resultado esperado.

Repare uma coisa: A entidade Cliente, não sabe onde é usada. Não sabe que existem diversos casos de uso que a manipulam. Ela também não está interessada em saber se os dados vêm do SQL ou via requisição http. Ela apenas sabe que recebe algumas informações e sabe o que fazer com elas. Já o caso de uso conhece todas as entidades, suas regras e seus métodos. O caso de uso depende da entidade, a entidade não depende de ninguém.

Vamos subir alguns níveis…

Quem executa um caso de uso? Pode ser uma chamada de botão na tela ou uma requisição via API? Sim. O caso de uso nunca saberá… Nesse caso a camada exterior de interface depende dos casos de uso. Os casos de uso, por sua vez, não dependem das interfaces.

Ok, mas e os adaptadores? Servem para traduzir os dados em um formato que os casos de uso consigam usar. Repare como a camada externa depende da interna e a interna nunca depende da camada externa.

Amanhã, o Marketing diz [galera do Marketing, nós te amamos 😉]que o caso de uso deve ser disparado a partir da nova versão mobile do sistema no seu celular. Sem problemas crie a interface necessária, crie um adapter e execute o caso de uso. O retorno será exatamente o mesmo. Troque seu banco de dados e apenas uma camada [em teoria] deve ser afetada.

Conclusão

Obviamente algumas mudanças não são tão simples de se implementar e a arquitetura limpa não é bala de prata. Mas fica claro que seria muito mais fácil mudar dezenas de fontes de uma camada do que centenas de fontes sem essa separação, onde a regra de negócio estivesse acoplada à tecnologia — Como infelizmente vejo muito em diversos clientes.

Às vezes gastar mais com o planejamento dos componentes do sistema vale a pena no futuro. Sistemas a prova de mudanças não existem, mas acredito que se podemos facilitar a manutenção futura e reaproveitar o máximo de componentes de negócio, por que não né??

Você já conhecia esse modelo ou algum outro modelo de arquitetura de software? Compartilha comigo e deixe seu feedback para eu saber se esse artigo te ajudou.

Até a próxima!

--

--