80 pontos por GN⁺ 2025-08-26 | 5 comentários | Compartilhar no WhatsApp
  • Estou tentando melhorar minhas habilidades de design de software e recebi a recomendação de estudar codebases existentes e bem projetados
  • Entre os codebases publicamente acessíveis, queria saber quais são considerados o padrão-ouro em design de software

1. Codebases recomendados

  • Projetos grandes/de referência
    • Git, Postgres, CPython
    • o "lieutenants model" do Linux Kernel
    • UNIX v6, BSDs
  • Frameworks/bibliotecas
  • Sistemas/servidores
  • Jogos/casos especiais
  • Materiais educacionais/de aprendizado
  • Outros
    • Monocypher (biblioteca de criptografia)
    • implementação da linguagem Tcl

2. Leitura de código vs. estudo de documentação/design

  • Limites do código por si só
    • Um codebase mostra a implementação, mas esconde a intenção do design e os trade-offs
  • Importância da documentação de design
    • Registros de decisão como ADR (Architectural Decision Records), RFCs do Rust e PEPs do Python são muito mais úteis para aprender design
    • Escrever documentos de design por si só também pode servir como treinamento
  • Livros e leituras recomendadas

3. Abordagem de aprendizado centrada na prática

  • Experiência e tentativa e erro
    • Design se aprende passando repetidamente por problemas e aprendendo como evitá-los
    • Só ler código não basta; o aprendizado acontece no processo de escrever, falhar e resolver esses fracassos
  • Aprendizado guiado por interesse
    • Você aprende mais profundamente ao criar projetos pelos quais realmente tem interesse
  • Baixo custo do fracasso
    • Em software, o custo de falhar é menor do que em engenharia física, então aprender tentando e errando é especialmente eficaz

4. Debate sobre a natureza da engenharia de software

  • Visão de engenharia imatura
    • Se cinco engenheiros se reúnem e produzem cinco soluções diferentes, isso seria um sinal de imaturidade como disciplina de engenharia
  • Visão de afinidade com experimentação
    • Software tem menos restrições, então admite várias soluções; ao contrário da engenharia física, não há uma resposta fixa
  • Fronteira entre arte e engenharia
    • Design também pode ser um ato artístico com elementos estéticos, mas continua sendo engenharia na medida em que atende requisitos funcionais
    • Software fica entre a flexibilidade artística e o rigor da engenharia

5. Métodos alternativos de aprendizado

  • Analisar código ruim
    • Não é só código bem projetado: corrigir codebases ruins também gera um grande efeito de aprendizado
  • Aprender com o próprio codebase
    • O codebase interno da sua equipe foi citado como uma das fontes de aprendizado mais valiosas
    • Mas, se o código do time for ruim, vale combinar isso com exemplos externos
  • Aprendizado adaptado ao domínio
    • Ler codebases parecidos com os problemas que você quer resolver é a abordagem mais eficaz

Principais insights

  • Codebases bem projetados ajudam, mas o aprendizado precisa caminhar junto com a compreensão da intenção do design e com tentativa e erro
  • Mais do que a leitura do código em si, documentos de design e registros de decisão são os principais materiais de estudo
  • Projetos de alta qualidade e bem conhecidos (Git, Postgres, CPython, biblioteca padrão do Rust etc.) têm alto valor de aprendizado
  • Além de código bom, aprender com código ruim e com o próprio código tende a ser mais prático no longo prazo

Resumo dos principais comentários

Recomendações de codebases de destaque (CraigJPerry)

  • Servidor de e-mail Postfix
    • Sua arquitetura focada em segurança já mostrava uma estrutura parecida com microservices antes mesmo de o conceito existir
    • Enquanto microservices modernos focam na distribuição em grandes organizações, o Postfix foi projetado para segurança e simplicidade
  • Spring Framework
    • Reflete uma cultura que considera profundamente as necessidades de desenvolvedores Java em ambientes enterprise
    • Dá para aprender uma abordagem de design centrada no usuário
  • Git
    • Depois de entender o banco de dados de objetos (blobs, trees, commits) e o conceito de referências, o restante é uma expansão gradual
    • A expansão consistente de conceitos centrais é apresentada como um bom exemplo de design
  • Varnish
    • Além de ser um reverse proxy de alto desempenho, tem um codebase organizado a ponto de servir também como ferramenta de aprendizado
  • Linux Kernel Lieutenants Model
    • Não é um codebase, mas vale como referência de modelo de gestão de software em larga escala
  • Mais do que simplesmente "código bem projetado", são casos em que as decisões de design deixam uma impressão forte

Ênfase no aprendizado com codebases de trabalho real (crystal_revenge)

  • O maior valor de aprendizado pode vir do codebase da sua própria equipe
  • No processo confuso de conectar requisitos reais à implementação, você vivencia ao mesmo tempo boas e más decisões
  • Entre as restrições do mundo real, o fator mais importante é a pressão de tempo, e o essencial é aprender a equilibrar design ideal e realidade
  • Bom software é aquele que resolve as necessidades do usuário, e a experiência repetida ensina a projetar com mais chance de sucesso

Discussões anteriores e links de referência (sprobertson)

Código vs. documentos de design (alphazard)

  • Um codebase é apenas o resultado da implementação, não o design em si
  • Para aprender design, escrever documentos de design é mais eficaz
    • Os documentos precisam ser claros o suficiente para que outra pessoa consiga implementá-los exatamente
    • Listar alternativas e registrar por que foram descartadas serve como evidência das considerações de design
  • Um bom designer é alguém que considera um espaço de design mais amplo e escolhe o ponto apropriado

Ênfase em entender o sistema como um todo (RossBencina)

  • O processo de compreender um codebase inteiro é muito valioso
    • Isso treina não só a leitura de código bem projetado, mas também a visão do quadro geral do sistema
    • Visualizar relações com diagramas como UML pode ajudar
  • Abordagem de aprendizado:
    • Ler o código de softwares parecidos com aquilo que você está desenvolvendo é eficaz
    • Recomenda-se começar por código de domínios que você já conhece bem (frameworks web, servidores web, biblioteca padrão do Python, VSCode etc.)
    • No início, é melhor abordar programas pequenos e domínios familiares

Critérios para um bom design (mamcx)

  • Um bom design mostra objetivos e ideias, enquanto o codebase revela o grau em que isso foi implementado
  • Bom design não é apenas um rótulo como "rápido" ou "seguro", mas deve incluir considerações concretas e registro de trade-offs
  • Exemplos: essas características podem ser observadas em Erlang, no Pascal inicial e no design de vários RDBMS
  • A biblioteca padrão do Rust é um ótimo material de estudo porque enfatiza segurança e consistência, e tanto o código quanto a documentação refletem isso fielmente

Decisões de design invisíveis (ben30)

  • Ao olhar para um codebase bem projetado, a parte mais importante é aquilo que não aparece
    • Decisões de ausência, como excluir complexidade, evitar abstrações desnecessárias e rejeitar certos padrões, são o ponto central
  • Para complementar isso, vale usar ADR (Architectural Decision Records)
    • Eles registram alternativas, motivos para rejeitá-las e fundamentos da escolha, preservando o contexto
    • Isso ajuda muito tanto futuros mantenedores quanto ferramentas de IA
  • Ao estudar, é eficaz observar não só o código, mas também projetos que vêm acompanhados de documentos de decisão de design, como ADR, RFC e PEP

5 comentários

 
shaffr0n 2025-08-27

Vi uma entrevista em que Evan You (criador do Vue.js e do Vite) disse que o express.js, feito por TJ, foi projetado de forma limpa e bonita, então já li o código algumas vezes. Não consegui entender a arquitetura como um todo, mas no geral tive muito a sensação de que o código não é complexo, é limpo e implementa exatamente a lógica necessária.

Os comentários também são bem escritos, então, mesmo sendo um código de 10 anos atrás, foi ótimo para entender inferência de tipos e o formato de DTO.

 
wedding 2025-08-27

Usar como referência um post de 2009 de um blog coberto de comentários spam...

 
GN⁺ 2025-08-26
Opinião do Hacker News
  • Não sei se é só comigo, mas sinto que a forma mais eficaz é realmente bater de frente com problemas várias vezes e aprender por conta própria como evitá-los. Com o tempo, você naturalmente passa a conseguir simular na cabeça quais problemas podem surgir no futuro e, no fim das contas, design também é um julgamento cuidadoso sobre prever e evitar vários problemas futuros, decidir quais problemas vale a pena evitar com determinado nível de esforço e se um único design consegue resolver vários problemas de uma vez, considerando esses trade-offs

    • Comigo também é assim. Coisas como “resolver exercícios” ou “estudar codebases” nunca funcionaram muito bem para mim. Eu aprendo naturalmente enquanto construo algo que realmente me interessa, buscando precisão e capricho nos exemplos. Mas às vezes ainda sinto que minha habilidade não é suficiente. Acho que estudar em si seria mais divertido se eu conseguisse ler código com fluidez como quem lê um livro e visualizar mentalmente como ele funciona

    • O que me veio à cabeça ao ouvir essa ideia de aprender batendo cabeça com problemas várias vezes é que a área de engenharia de software ainda não amadureceu. Basta imaginar o risco que seria construir pontes ou casas desse jeito, ou treinar cirurgiões assim. Com o tempo, padrões e normas vão se estabelecer, mas no momento a situação é bem fluida. Se você reunir cinco engenheiros de software e apresentar um problema, não só vão surgir cinco soluções completamente diferentes, como também haverá fortes divergências sobre qual abordagem está certa. Não acho que uma atitude do tipo “eu reconheço uma boa solução quando vejo uma” seja engenharia de verdade

    • Eu também tenho aprendido de forma consistente assim até hoje e provavelmente vou continuar. Aprender a partir de código real de produção deve ser um desafio novo para mim. Não sei o quanto isso vai valer a pena, mas de qualquer forma parece divertido

    • Acho que isso é parecido com aprender a dirigir entrando no carro pela primeira vez, batendo, refletindo sobre isso e depois tentando dirigir sem bater da próxima vez. Na prática, os dois métodos são necessários. No trânsito comum, quase nunca chegamos perto do limite, então é difícil aplicar isso diretamente, mas em corrida é essencial saber exatamente até onde dá para forçar. Claro, não acho que precisamos tratar nossa profissão como uma competição. Mas, se você não lê livros nem estuda, isso literalmente leva muito mais tempo e ainda traz acidentes e falhas sem fim. Por isso eu diria para ler, e ler muito. Talvez você não sinta necessidade agora, mas em algum momento, com mais experiência, esse conhecimento certamente vai ser útil em algum lugar, e você não vai entrar em pânico como quando aprende pela primeira vez que numa descida é preciso frear com o motor e reduzir a marcha

    • É exatamente isso

  • A primeira coisa que penso ao ouvir essa pergunta é: “a codebase da sua equipe”. Não existe caminho mais eficaz para aprender design de software do que entender profundamente por que boas e más soluções foram adotadas para problemas reais. Software é, em essência, uma camada intermediária complexa entre requisitos de usuários e o funcionamento da máquina. Se essa confusão não existisse, já teria sido automatizada e o próprio software nem seria necessário. No software, perseguir apenas algum ideal abstrato frequentemente leva a decisões ruins. Na prática, você reduz tentativa e erro ao entender “por que determinadas escolhas foram feitas sob certas pressões”. Ao mesmo tempo, é preciso aprender metodologias práticas para trabalhar de forma rápida e eficaz. O maior desafio no mundo real é a limitação de tempo. Isso quase não aparece em discussões teóricas de design de software, mas na realidade você sempre trabalha sob pressão para entregar código rápido. Muitas vezes não há tempo para fazer do jeito que você gostaria ou do jeito ideal. Bom software é software que resolve necessidades reais dos usuários. Existem soluções de design que, no futuro, tendem a gerar execuções bem-sucedidas com mais frequência, e a melhor forma de encontrá-las é observar a fundo o código que eu mesmo escrevo

    • E se a pessoa que perguntou estiver buscando conselhos externos porque sente que o software da própria equipe é uma bagunça? Ou se for simplesmente um estudante universitário fazendo a pergunta?

    • Eu nunca tinha pensado que o tempo necessário para implementar também pode ser uma métrica para avaliar a qualidade do design, mas faz muito sentido. Eu também aprendo demais com a codebase da minha equipe. Boa parte disso vem de ver coisas boas em designs excelentes e, nas partes ruins, continuar aprendendo pesquisando no Google por conta própria

  • Já tem alguns anos, mas existe a série "The Architecture of Open Source Applications", com contribuições de vários líderes de projetos open source, e dá para ler de graça online
    https://aosabook.org/en/index.html

  • Essa pergunta já apareceu várias vezes, então reuni alguns links de referência

  • Código-fonte do Yanderedev

  • Não sou qualificado o bastante para dizer qual é a resposta certa, mas li com muito prazer, uns 15 anos atrás, um livro chamado "Code Reading". É exatamente sobre esse tema
    https://www.spinellis.gr/codereading/
    Índice: https://www.spinellis.gr/codereading/toc.html
    Acho que também existia um livro com nome parecido, mas não lembro exatamente

  • Na prática, codebases costumam conter mais implementação do que design. Por exemplo, mesmo que você reescreva tudo em outra linguagem, o design ainda pode ser preservado. Eu recomendaria praticar a escrita de documentos de design. Não se preocupe com a aparência do documento nem fique preso a templates. O mais importante é que outra pessoa consiga pegar esse documento e implementar a partir dele. E o próprio documento pode servir como um “registro de reflexão”. Basta deixar claro qual abordagem foi escolhida, quais alternativas existiam e por que elas não foram escolhidas. Ao reconhecer e comparar alternativas com antecedência, você transmite ao leitor confiança de que houve reflexão suficiente. O que um bom designer de sistemas faz é olhar para um espaço de design maior do que os outros e encontrar, de forma consistente, bons pontos dentro dele. Escolha um problema, experimente diferentes espaços de design e registre tudo explicando por que alguns são melhores do que outros

  • O ponto de partida deve ser primeiro a pergunta: “qual problema eu quero resolver?”. Encontre uma codebase que resolva esse problema e analise com foco como ela foi implementada na prática. É preciso ter em mente que um bom design está muito intimamente ligado ao contexto de um domínio específico. Acho que o Internal Model Principle, de Wonham, também se aplica ao código. Por exemplo, eu queria resolver o problema de testes unitários para targets embarcados, então analisei projetos open source relacionados e examinei de forma crítica por que cada parte do código foi escrita daquela maneira. Ao construir minha própria solução e voltar a consultar esses códigos, vou aprendendo cada vez mais à medida que meu entendimento do domínio se aprofunda

  • Pela minha experiência (30 anos com software, 25 anos trabalhando com arquitetura, mestrado em arquitetura de sistemas no MIT), não existe design “bom” em abstrato. Existem, com certeza, projetos ruins (designs que levam a maus resultados), mas o critério do que é “bom” depende do contexto. O que você está construindo, requisitos como segurança e proteção e, acima de tudo, a equipe que vai implementar aquilo e a estrutura dessa equipe têm o maior impacto. Uma equipe composta só por juniores pode interpretar mal um design sofisticado e estragá-lo. Como na Lei de Conway, a estrutura da equipe de desenvolvimento acaba se refletindo diretamente no software

    • Uma coisa que certamente percebi ao aprender design de software é que não existe solução universal. Seria ótimo se existisse, mas às vezes é frustrante ter de escolher a melhor opção entre várias arquiteturas e paradigmas. Ainda assim, só de refletir corretamente os requisitos, as opções já diminuem bastante. Hoje trabalho com sistemas embarcados em que segurança é especialmente importante, e esse ambiente me leva com frequência a tomar decisões que eu jamais usaria em outras situações

    • No fim, o mais importante é evitar concessões realmente absurdas e também escapar, numa visão mais ampla, das piores escolhas. O que sempre sinto na prática é que o trabalho não é tanto uma busca pela melhor arquitetura, mas uma luta contínua para “evitar decisões fundamentalmente ruins”

  • Há algum tempo fiz uma lista de recomendações bem simples, e ela ainda continua válida
    https://medium.com/@012parth/what-source-code-is-worth-studying-8755f88f8de5

 
roxie 2025-08-27

Tem uma pegadinha no meio..

 
ffdd270 2025-08-27

O código-fonte do Yanderedev... hahaha