1 pontos por GN⁺ 2024-02-26 | 1 comentários | Compartilhar no WhatsApp
  • Em projetos open source com algo entre 10 mil e 200 mil linhas de código, colocar um documento de ARCHITECTURE ao lado de README e CONTRIBUTING pode 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 .
  • 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

 
GN⁺ 2024-02-26
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...

    • Seria bem legal ter uma ferramenta que criasse diagramas Mermaid em linguagem natural. Vale pensar nisso
  • 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

    • Seria bom adicionar busca por palavras-chave ou busca vetorial com LLM a visualizações como dep-tree. Ao fazer uma consulta, os arquivos e clusters relacionados seriam destacados
  • 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/

    • Aqui, acho que “junto” é uma expressão mais adequada do que “em vez de”
      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
    • Na minha empresa também há documentos inúteis escritos por arquitetos, e a maioria é mais ou menos assim
      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?

    • Não é uma resposta direta à pergunta, mas parece que, no fim, a questão é “quero visualizar melhor a estrutura de arquivos”
      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 finalidade
      Ranger - https://github.com/ranger/ranger
      Midnight Commander - https://midnight-commander.org/
    • Eu também pensei exatamente a mesma coisa
      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
    • Como isso ficaria na prática? Por exemplo, como lidar com dependências circulares?
    • Talvez o que você queira seja uma multiárvore
  • 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

    • Fiz algumas sessões de arquitetura com equipes e elas sempre foram valiosas
      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

  • 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

    • “Explicação dos componentes” é justamente o problema. Porque alguém precisa fazer isso
      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...

    • Existe alguma forma de ver isso automaticamente no GitHub? Por exemplo, algo como um mapa de calor de alterações em arquivos
  • 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 /docs do repositório git
    Em 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