Garantindo a arquitetura de uma aplicação sem complexidade

Guilherme Biff Zarelli
luizalabs
Published in
4 min readNov 30, 2022

O objetivo desse artigo é mostrar como podemos garantir a arquitetura de uma aplicação de um jeito simples e eficiente, sem a complexidade da criação de projetos modulares.

Inspirado em projetos que ferem seus próprios padrões utilizados, proporcionando uma arquitetura fŕagil e variável ao longo do tempo.

Um sistema com uma boa arquitetura traz diversas vantagens para o time de desenvolvimento. Nada melhor que pegar um código e ler como se fosse um bom livro, afinal, passamos maior parte do tempo lendo ele do que de fato escrevendo.

Arquiteturas de Software como Hexagonal, Clean Architecture, MVC entre outras, demonstram excelentes implementações para evitar o forte acoplamento de código e garantir uma boa testabilidade. Algumas demonstram uma certa complexidade de implementação se formos seguir um conceito modular adequado a fim de evitar esse acoplamento entre as camadas. Muitas pessoas seguem esses modelos em um único módulo, apenas com divisões por packages, e não tem nada errado com isso, mas conseguimos tornar esse modelo seguro para futuras implementações?

Assim como um bom código possui testes de unidade, no qual podemos entender melhor a regra do que cada trecho do que foi escrito e o que deveria fazer e como se comportar, porque sua arquitetura não deveria ter algo similar? a fim de garantir e impedir que futuras implementações quebrem essas decisões?

Testando a arquitetura de software

Existem algumas bibliotecas em diversas linguagens para tentarmos garantir a arquitetura de uma aplicação sem complexidade, por exemplo, uma das mais conhecidas e usadas em aplicações Java / C# é o ArchUnit, sua proposta é tentar garantir a arquitetura dá aplicação baseado em testes de unidade, não só a arquitetura, mas essa biblioteca nos possibilita até mesmo padronizarmos convenções de nomes de classes.

“O ArchUnit é uma biblioteca gratuita, simples e extensível para verificar a arquitetura do seu código Java. Ou seja, o ArchUnit pode verificar dependências entre pacotes e classes, camadas e fatias, verificar dependências cíclicas e muito mais. Ele faz isso analisando determinado bytecode Java, importando todas as classes para uma estrutura de código Java. O foco principal do ArchUnit é testar automaticamente a arquitetura e as regras de codificação, usando qualquer estrutura de teste de unidade Java simples.” — ArchUnit, User guide, introduction

A seguir veja exemplos de uma validação de arquitetura e de convenção de nomes:

São inúmeras possibilidades de validações, e o mais legal que a execução é realizada sobre os testes de unidade. Veja mais sobre e exemplos em:

No Python também existe uma biblioteca com a mesma proposta, por exemplo, temos o Import-Linter, tão rico quanto o ArchUnit possuindo comportamentos similares, o import-linter possui validações de arquitetura baseado em imports.

“Import Linter é uma ferramenta de linha de comando para verificar se você está seguindo uma arquitetura auto-imposta em seu projeto Python. Ele faz isso analisando as importações entre todos os módulos em um ou mais pacotes Python e compara isso com um conjunto de regras que você fornece em um arquivo de configuração.” — Import-Linter, Docs, Overview

Exemplo:

[importlinter:contract:8]
name = Modules core cannot depend on infrastructure
type = forbidden
source_modules =
src.core.domain
src.core.usecases

forbidden_modules =
src.module.infrastructure


[importlinter:contract:3]
name = modules inside core shall be independent
type = independence
modules =
src.core.domain
src.core.usecases

Veja mais em:

Como podemos ver, muitas linguagens possuem bibliotecas similares e com a mesma proposta de validar a arquitetura de seu software. Para Java / C# temos a ArchUnit, Python a Import-Linter, para TypeScript / JavaScript temos também a ts-arch (https://github.com/ts-arch/ts-arch), em GO temos a archtest (https://github.com/matthewmcnew/archtest) e assim por diante…

Conclusão

Acredito que o ideal para qualquer projeto seja manter uma boa coerência estrutural a fim de garantir uma boa manutenibilidade e durabilidade de um software, e independente de qual arquitetura for escolhida no inicio do desenvolvimento, o melhor a se fazer seja tentar assegurar o máximo possível essas definições, por isso que ferramentas como o ArchUnit e Import-Linter foram criadas, com elas, conseguimos deixar nossa arquitetura testada e principalmente documentada.

“Testing starts at project conception, or before. If you don’t know this, you don’t understand testing at all.” ― Gerald Weinberg (Perfect Software And Other Illusions About Testing)

Referências

--

--