ARCHITECTURE.md (2021): especificação técnica da estrutura do projeto
(matklad.github.io)- Em projetos open source com algo entre 10 mil e 200 mil linhas de código, colocar um documento de ARCHITECTURE ao lado de
READMEeCONTRIBUTINGpode reduzir o custo para novos contribuidores entenderem a estrutura do código - Em projetos desconhecidos, o problema maior não é que escrever um patch fique cerca de 2 vezes mais lento, mas sim que leva 10 vezes mais tempo para encontrar onde deve ser corrigido
- Este documento deve registrar de forma breve a estrutura de alto nível e conteúdos que não mudam com frequência; em vez de tentar mantê-lo sempre sincronizado com o código, o mais adequado é revisá-lo algumas vezes por ano
- Os componentes centrais são uma visão geral do problema e um codemap (mapa de código), que deve mostrar os grandes módulos e suas relações para responder “onde está o código responsável por X”
- Vale registrar nomes importantes, invariantes da arquitetura, fronteiras entre camadas e sistemas, e preocupações transversais; em vez de links diretos, incentivar a busca por nomes reduz o custo de manutenção
O custo que um documento ARCHITECTURE reduz
- Em projetos open source, a maior diferença entre quem contribui ocasionalmente e desenvolvedores centrais é saber ou não a arquitetura física do projeto
- Em uma base de código desconhecida, os arquivos acabam sendo lidos sequencialmente como fragmentos lógicos colocados em ordem aleatória
- Quem já fez contribuições significativas tem um mapa mental do código e vai direto ao ponto necessário; quem não tem pode até mover esse código para outro lugar
- O arquivo
ARCHITECTUREé um meio de baixo custo para reduzir essa distância - O documento deve ser curto
- porque todas as pessoas que contribuem repetidamente precisam lê-lo
- e porque, quanto mais curto, menor a chance de se tornar inválido com mudanças futuras
- O critério para incluir algo em
ARCHITECTUREé que seja conteúdo que não muda com frequência- não se tenta mantê-lo continuamente sincronizado com o código
- em vez disso, ele é revisado novamente algumas vezes por ano
O que deve conter
- Primeiro, organize o problema que o projeto resolve no nível de uma visão panorâmica
- Em seguida, escreva um codemap (mapa de código) com algum nível de detalhe
- ele explica os módulos de grande porte e as relações entre eles
- deve responder “onde está o que faz X”
- e também “o que faz isso que estou olhando”
- Não é necessário entrar profundamente no funcionamento interno de cada módulo
- esse tipo de conteúdo deve ir para documentos separados ou, melhor ainda, para documentação inline
- o mapa de código é um mapa do país, não um atlas estadual
- O processo de escrever o mapa de código também pode servir para revisar a estrutura do projeto
- é possível verificar se as coisas que você quer manter próximas no mapa de código também aparecem próximas no resultado de
tree .
- é possível verificar se as coisas que você quer manter próximas no mapa de código também aparecem próximas no resultado de
- Nomes importantes de arquivos, módulos e tipos devem ser explicitados
- links diretos podem quebrar com o tempo, então é melhor evitá-los
- em vez disso, induzir a busca de símbolos por nome permite descobrir itens relacionados com nomes parecidos sem aumentar o custo de manutenção
- Invariantes da arquitetura devem ser escritas de forma explícita
- invariantes importantes muitas vezes aparecem na forma de algo que “não existe”
- por exemplo, no desenvolvimento web, o fato de a camada de modelo não depender da view pode ser difícil de perceber apenas lendo o código
- As fronteiras entre camadas e sistemas também devem ser indicadas
- fronteiras sugerem informações sobre a implementação do sistema por trás delas
- e restringem todas as implementações possíveis
- como boas fronteiras são difíceis de encontrar aleatoriamente no código, documentá-las é útil
- Depois do mapa de código, adicione uma seção separada para preocupações transversais
- Um exemplo útil de referência pode ser visto em rust-analyzer em architecture.md
1 comentários
Opiniões no Hacker News
Gosto desta ideia e acho que, independentemente do tamanho do repositório, uma descrição da arquitetura também tem lugar no README
Por exemplo, como acho importante que todos os leitores vejam e entendam o fluxo de trabalho, coloquei de propósito um diagrama de sequência Mermaid[1] no README principal[2]
[1] https://mermaid.js.org/syntax/sequenceDiagram.html
[2] https://github.com/hbcondo/revenut-app?tab=readme-ov-file#-w...
Soa como um conselho realmente bom
Eu queria que as ferramentas para visualizar a arquitetura de um sistema em execução fossem melhores. Ainda acho estranho que ler o código ou ver um arquivo Markdown continue sendo o jeito moderno. Com sorte, pode haver pelo menos um diagrama Mermaid
Eu gostaria que a arquitetura se revelasse sozinha em tempo real. Seria bom se a observabilidade em escala macro viesse embutida por padrão, e acho que isso também ajudaria todo mundo a entender melhor a computação e a humanidade a se ampliar
Para projetos open source com muitos contribuidores temporários, parece um modelo de baixa manutenção bom. Para projetos com engenheiros dedicados, também vale considerar ADRs
ADRs exigem mais manutenção, mas registram “por que foi feito assim” e “quais alternativas foram avaliadas”, então são muito úteis ao redesenhar algo
Referência: https://adr.github.io/
ARCHITECTURE.md contém o estado atual da arquitetura, e ADR é o registro das decisões que levaram até ali. Ambos são muito úteis
Microsserviços, Kafka, Kubernetes: porque hoje há 4 mil usuários, mas e se um dia forem 1 bilhão?
GraphDB: porque e se SQL não for suficiente?
ElasticSearch: porque e se precisarmos fazer busca full-text junto com estatísticas?
Só que a maioria desses documentos acaba sendo uma forma abreviada de “quero experimentar uma nova arquitetura/tecnologia porque é divertido, um colega que trabalha em FAANG usa, li aquele livro, fica bem no currículo”
Depois que eles passam para o próximo grande projeto de design, nossa equipe precisa manter sincronizados mais serviços do que membros no time, além dos bancos de dados e tecnologias acima. Claro, tratam esse tipo de problema como algo muito mais simples do que tomar “grandes decisões de arquitetura”
Uma ideia que me veio: todos os IDEs que usei mostram a estrutura de pastas do projeto à esquerda como uma árvore de diretórios padrão. Existe algum IDE que permita navegar pelo projeto como um grafo de dependências?
Acho que uma representação em forma de sumário não se encaixa muito bem. No meu fluxo de trabalho de programação atual, abro um terminal, executo ranger nele e, quando vou navegar pela estrutura de diretórios à esquerda e à direita, alterno para essa aba do terminal. Abro o VSCode e, no terminal dividido, deixo um terminal comum em cima e o Ranger embaixo. Midnight Commander também serve; na verdade, qualquer explorador de arquivos TUI resolve
Também comecei a colocar um mapa do código no arquivo architecture.md dos projetos. Ao executar
tree -L, dá para obter um diagrama em árvore da estrutura de arquivos, bom para colocar em Markdown, na profundidade desejada. Adiciono essa saída ao Markdown e, depois de cada arquivo/pasta, coloco um comentário de menos de 10 palavras explicando sua finalidadeRanger - https://github.com/ranger/ranger
Midnight Commander - https://midnight-commander.org/
Tenho duas ideias de como isso poderia ser
Primeiro, várias árvores de diretórios que organizam os arquivos de forma ortogonal usando links simbólicos. A estrutura de diretórios comum se divide em cliente/servidor, mas e se eu quiser dividi-la por funcionalidade? Um IDE poderia tornar isso muito mais fácil
Segundo, na linha deste texto, eu queria que o IDE facilitasse criar favoritos, alternar entre eles e explicar o código para as pessoas. Às vezes quero deixar um comentário e, ao clicar, pular para outro lugar da base de código. Ao conectar essas coisas, daria para tecer uma narrativa que explica como o funcionamento se dá ao longo de toda a base de código
Fico curioso se há alguém trabalhando nessa direção
Acho que é preciso ter cuidado para não ampliar demais o que o autor está dizendo aqui para projetos de software em geral
Em grandes projetos open source com muitos contribuidores sem contexto, manter esse tipo de documento tem muito valor. Mas, em projetos pequenos de trabalho, vi que todo documento commitado por desenvolvedores acaba ficando sem manutenção
No mínimo, descobrimos que os membros da equipe tinham ideias muito diferentes entre si sobre a arquitetura atual e a arquitetura ideal. Só tornar isso explícito já vale a criação do documento
E “a documentação não é mantida” é um motivo muito fraco para não criar documentação. Qualquer documentação, mesmo antiga ou sutilmente incorreta, é melhor do que “nenhuma documentação”
Há alguns anos, experimentei uma abordagem parecida em um dos meus grandes projetos paralelos
https://github.com/shipmight/shipmight/blob/master/src/ARCHI...
No topo de cada arquivo, coloquei uma árvore de links para outros arquivos ARCHITECTURE.md dentro do repositório. Um exemplo seria: ARCHITECTURE.md <- local atual, backend/ARCHITECTURE.md, backend/api/ARCHITECTURE.md, backend/cli/ARCHITECTURE.md, backend/ui/ARCHITECTURE.md, backend/utils/ARCHITECTURE.md, frontend/ARCHITECTURE.md, internal-charts/ARCHITECTURE.md
Ele aparece em locais como este: https://github.com/shipmight/shipmight/tree/master/src/backe...
Também já vi essa abordagem em alguns projetos
Quanto mais curto, menor a chance de ficar obsoleto por mudanças futuras. A principal regra prática de um ARCHITECTURE é escrever apenas o que não muda com frequência. Não se deve tentar mantê-lo sincronizado com o código
Interfaces têm menor probabilidade de mudar e também são mais difíceis de alterar. Essa é a visão de Parnas sobre os critérios usados para decompor um sistema em módulos
Concordo que é difícil entender uma base de código. Dar nomes a “padrões” ajuda até certo ponto, mas, no fim, ainda é preciso ler bastante
No GitHub, muitas vezes as mensagens de commit por arquivo parecem uma explicação. Será que isso poderia ser mais útil?
Em todos os projetos dos quais participei, durante o onboarding recebi diagramas de arquitetura e uma breve explicação dos componentes
Por isso me surpreende que isso não seja tão comum em open source
Em projetos open source não existe o primeiro dia de trabalho de um funcionário, então essa introdução também não existe
Se não houver muito tempo disponível, esse tipo de explicação não é muito boa. Espera-se que um funcionário leve algumas semanas até conseguir fazer algo sozinho, mas nós, como consultores de segurança, ouvimos uma explicação completamente nova a cada duas semanas. O problema é que essas explicações são improvisadas e sem estrutura, e quem fala acaba mencionando muitos detalhes irrelevantes por causa da maldição do conhecimento
Talvez o ideal seja alguém recém-chegado ao repositório escrever isso uma vez e, depois, apenas manter. A segunda melhor opção é, em vez de qualquer pessoa improvisar a explicação toda vez, pensar por cerca de um minuto no que incluir e no que deixar de fora e então escrever. Como o autor disse, esse arquivo deve explicar a arquitetura de alto nível do projeto e deve ser curto. Todo contribuidor recorrente deve lê-lo, e quanto mais curto ele for, menor também a chance de ficar obsoleto por mudanças futuras
Sempre achei uma prática muito útil. Em muitos projetos há alguns arquivos centrais, ou pacotes/módulos etc., onde acontece a maior parte das mudanças
Se um novo contribuidor, ou alguém que está voltando depois de muito tempo, conseguir se familiarizar rapidamente com eles, o tempo para começar no projeto cai bastante
Em vários empregos, adicionei arquivos de arquitetura a projetos [0], [1] e a reação foi boa. Não é perfeito, mas é melhor do que não ter nada
[0]: https://github.com/zapier/zapier-platform/pull/324
[1]: https://github.com/stripe/stripe-cli/blob/master/ARCHITECTUR...
Antigamente eu gostava desses pequenos padrões de documentação/diagramas-as-code
README-driven development, ARCHITECTURE.md, ADR, arc42, C4 e afins
Hoje simplesmente coloco um cofre do Obsidian dentro da pasta
/docsdo repositório gitEm vez de usar padrões de outras pessoas, continuo organizando e refatorando a documentação como faço com minhas anotações pessoais no Obsidian
No começo eu queria usar um subconjunto comum de Markdown que funcionasse tanto no GFM do GitHub quanto no Obsidian, mas desisti; agora uso o Markdown no estilo do Obsidian como ele é, incluindo recursos próprios como o plugin Dataview e templates
Mermaid e LaTeX já vêm integrados ao Obsidian, e também há um plugin para PlantUML. Para desenhos/diagramas visuais, uso o Canvas integrado, DrawIO e Excalidraw