As leis da engenharia de software
(lawsofsoftwareengineering.com)- Uma coleção que reúne em um só lugar 56 princípios e padrões que afetam sistemas de software, equipes e tomada de decisão, cobrindo amplamente desde a operação de times até arquitetura, qualidade, design e decisões
- Leis relacionadas a equipes, como a Lei de Conway, a Lei de Brooks e o número de Dunbar, mostram que a estrutura organizacional afeta diretamente o design do sistema e a produtividade
- Na área de arquitetura, organiza restrições e princípios que precisam ser considerados ao projetar sistemas complexos, como a Lei de Hyrum, o teorema CAP e a Lei de Gall
- As leis relacionadas à qualidade tratam de dívida técnica, da pirâmide de testes, da Lei de Kernighan e das dificuldades reais de manter a qualidade do código e depurar
- Na área de tomada de decisão, abrange vieses cognitivos e critérios de julgamento nos quais é fácil cair durante o desenvolvimento, como o efeito Dunning-Kruger, a falácia do custo afundado e o princípio de Pareto
Equipes (Teams)
1. Lei de Conway (Conway's Law)
> Organizações projetam sistemas que refletem sua própria estrutura de comunicação
- A arquitetura de software tende naturalmente a seguir a estrutura de comunicação da organização que a criou
- Se a equipe estiver dividida em 3 grupos, o sistema também tende a se dividir em 3 grandes módulos
- Também existe a "estratégia inversa de Conway" (Inverse Conway Maneuver): uma abordagem em que a estrutura da equipe é reorganizada primeiro de acordo com a arquitetura desejada
- Ao adotar microservices, é eficaz alinhar os limites das equipes com os limites dos serviços
2. Lei de Brooks (Brooks's Law)
> Adicionar pessoas a um projeto de software atrasado o torna ainda mais atrasado
- Quando novos membros entram, os integrantes atuais da equipe gastam tempo com treinamento e coordenação, o que reduz temporariamente a produtividade geral
- À medida que o número de membros cresce, os caminhos de comunicação aumentam exponencialmente (com n pessoas, n(n-1)/2)
- Frederick Brooks formulou isso em seu livro de 1975 The Mythical Man-Month, com base na experiência no projeto IBM OS/360
- Pode ser explicado quantitativamente pela Lei de Little (L = λ × W): ao adicionar pessoas, o WIP (trabalho em andamento) aumenta, mas o throughput fica estagnado, fazendo o lead time crescer
- A solução não é adicionar gente, e sim ajustar o escopo ou alterar o cronograma
3. Número de Dunbar (Dunbar's Number)
> O limite cognitivo de relações que uma pessoa consegue manter de forma estável é de cerca de 150 pessoas
- Valor derivado por Robin Dunbar a partir da correlação entre o tamanho do cérebro de primatas e o tamanho dos grupos sociais
- A estrutura hierárquica social de Dunbar: ~5 pessoas (relações íntimas), ~15 (colaboradores de confiança), ~50 (relações de trabalho próximas), ~150 (conexões sociais estáveis)
- Quando uma organização de engenharia ultrapassa 150 pessoas, a comunicação informal chega ao limite e passa a exigir hierarquias e processos formais
- O "Two-Pizza Team" da Amazon (5~10 pessoas) reflete que, mesmo dentro de 150 pessoas, a colaboração real acontece em unidades menores
4. Efeito Ringelmann (The Ringelmann Effect)
> Quanto maior o grupo, menor a produtividade individual
- Fenômeno de "preguiça social" (social loafing), no qual a contribuição de cada pessoa diminui à medida que o grupo cresce
- Também em equipes de software, quando o time aumenta, o senso de responsabilidade individual se dilui e o custo de coordenação cresce
- Explica por que equipes pequenas geram mais resultado por pessoa
5. Lei de Price (Price's Law)
> Um número de pessoas equivalente à raiz quadrada do total de participantes realiza 50% de todo o trabalho
- Em uma organização de 100 pessoas, cerca de 10 pessoas respondem por metade de todo o trabalho
- Quanto maior a organização, maior a dependência de um pequeno grupo de profissionais de alto desempenho
- Explica por que a produtividade não cresce linearmente quando a equipe é expandida
6. Lei de Putt (Putt's Law)
> Quem entende de tecnologia não gerencia, e quem gerencia não entende de tecnologia
- Expressa de forma satírica o descompasso entre o papel de gestão e a expertise técnica em organizações técnicas
- Ao desenhar a estrutura de liderança técnica, é preciso reconhecer essa lacuna e criar mecanismos para compensá-la
7. Princípio de Peter (Peter Principle)
> Em uma organização, todo funcionário tende a ser promovido até seu nível de incompetência
- Padrão em que uma pessoa competente em um papel é promovida e se torna incompetente na nova função
- Reflete a realidade de que um excelente desenvolvedor não necessariamente se torna um bom gestor
- Mostra a necessidade de um sistema de carreira em dupla trilha, separando a trilha IC (Individual Contributor) da trilha de management
8. Bus Factor
> Número mínimo de saídas de membros da equipe que pode colocar um projeto em risco grave
- Se o Bus Factor é 1, existe um ponto único de falha (Single Point of Failure)
- É importante aumentar o Bus Factor por meio de compartilhamento de conhecimento, pair programming e documentação
- Code review e cross-training são formas práticas de melhorar o Bus Factor
9. Princípio Dilbert (Dilbert Principle)
> Empresas tendem a promover funcionários incompetentes para cargos gerenciais a fim de limitar os danos
- Observação satírica proposta por Scott Adams, uma variação do Princípio de Peter
- Fenômeno organizacional paradoxal em que cargos de gestão são vistos como posições que causam menos prejuízo às operações
Planejamento (Planning)
10. Otimização prematura / princípio de otimização de Knuth (Premature Optimization)
> A otimização prematura é a raiz de todos os males
- Apresentado por Donald Knuth em um artigo de 1974: "em cerca de 97% dos casos, pequenas eficiências devem ser ignoradas"
- Como cerca de 20% do código responde por 80% do tempo de execução, otimizar os 80% restantes é desperdício
- Ordem correta: primeiro fazer funcionar → depois fazer corretamente → e, se necessário, tornar rápido
- Como código otimizado aumenta a complexidade, isso deve ser feito após confirmar os gargalos reais por meio de profiling
11. Lei de Parkinson (Parkinson's Law)
> O trabalho se expande até preencher todo o tempo disponível
- Se o prazo é de 2 semanas, o trabalho cresce por 2 semanas; se é de 4, cresce por 4
- Explica por que é importante definir milestones curtos e claros em projetos de software
- O ágil baseado em sprints é uma resposta prática a essa lei
12. Regra 90-90 (The Ninety-Ninety Rule)
> Os primeiros 90% do código consomem 90% do tempo de desenvolvimento, e os 10% restantes consomem outros 90% do tempo
- Alerta que os 10% finais de um projeto de software (edge cases, polishing, correção de bugs) levam muito mais tempo do que o esperado
- A expressão "quase pronto" pode, na prática, significar o meio do cronograma total
13. Lei de Hofstadter (Hofstadter's Law)
> Sempre leva mais tempo do que o esperado, mesmo quando se leva em conta a Lei de Hofstadter
- Lei com estrutura de autorreferência recursiva, que expressa a dificuldade intrínseca de estimar cronogramas de software
- A realidade em que, mesmo adicionando buffer, o prazo ainda estoura
- Apresentada por Douglas Hofstadter no livro de 1979 Gödel, Escher, Bach
14. Lei de Goodhart (Goodhart's Law)
> Quando uma métrica se torna alvo, ela deixa de ser uma boa métrica
- Um caso representativo é quando cobertura de código vira KPI e passa a gerar testes sem sentido
- Se a produtividade é medida por linhas de código (LOC), acaba-se produzindo código desnecessariamente prolixo
- É preciso focar não na otimização da métrica, mas no alcance do valor essencial
15. Lei de Gilb (Gilb's Law)
> Quando é necessário quantificar, medir de algum modo é melhor do que não medir
- Mesmo que uma medição perfeita seja impossível, uma medição aproximada é sempre mais útil do que nenhuma medição
- Também se aplica a itens difíceis de quantificar, como qualidade de software e satisfação do usuário
Arquitetura (Architecture)
16. Lei de Hyrum (Hyrum's Law)
> Se houver usuários suficientes de uma API, alguém dependerá de todo comportamento observável do sistema
- Não apenas a especificação oficial da API, mas também comportamentos não oficiais como timing, formato das mensagens de erro e ordem de classificação acabam se tornando objetos de dependência
- Caso do Microsoft Windows, que manteve comportamentos de versões antigas para garantir compatibilidade com apps de terceiros que dependiam de comportamentos e bugs não documentados
- Observado por Hyrum Wright, do Google, por volta de 2011-2012, a partir de experiências com mudanças em bibliotecas internas do Google
- O colega Titus Winters deu o nome de "Lei de Hyrum" (incluída em Software Engineering at Google)
- O contrato real não é a API oficial, mas todo o comportamento efetivamente observável
17. Lei de Gall (Gall's Law)
> Um sistema complexo que funciona inevitavelmente evoluiu de um sistema simples que funcionava
- Ao projetar um sistema complexo desde o início, há variáveis desconhecidas demais e ainda não validadas, o que aumenta muito a probabilidade de fracasso
- Base teórica para a abordagem de MVP (Minimum Viable Product)
- Exemplo do Facebook, que começou em 2004 como um sistema simples de perfis para estudantes de Harvard e foi se expandindo gradualmente
- Mesmo em uma transição para microsserviços, é vantajoso começar com um monólito e separar gradualmente
- Proposta por John Gall no livro Systemantics (1975), um clássico cult publicado depois de ser rejeitado por 30 editoras)
18. Lei das abstrações vazantes (The Law of Leaky Abstractions)
> Toda abstração não trivial vaza em algum grau
- Um exemplo clássico é o ORM, que esconde SQL, mas quando surgem problemas de performance é inevitável inspecionar as queries geradas
- O garbage collection de Java/Python também é uma abstração, mas comportamentos internos como pausas de GC afetam o desempenho
- A lição não é que abstrações sejam ruins, e sim que é preciso se preparar para quando a abstração quebrar
- Apresentada por Joel Spolsky em um post de blog de 2002, junto com exemplos como TCP e memória virtual
- Também se conecta, em contexto, à frase de George Box: "Todos os modelos estão errados, mas alguns são úteis"
19. Lei de Tesler / Lei da conservação da complexidade (Tesler's Law)
> Toda aplicação tem uma complexidade inerente que não pode ser removida; ela só pode ser deslocada
- Pergunta central: quem vai arcar com a complexidade (usuário vs. sistema)
- O Calendly absorve no sistema a complexidade de coordenar agendas, enquanto threads de e-mail a repassam ao usuário
- Um bom design desloca a complexidade da experiência do usuário para dentro do sistema
- Formulada por Larry Tesler nos anos 1980, durante o trabalho no Apple Lisa e em GUIs iniciais
20. Teorema CAP (CAP Theorem)
> Em sistemas distribuídos, só é possível garantir duas entre consistência (C), disponibilidade (A) e tolerância a partição (P)
- Partições de rede são inevitáveis na prática, então a escolha real é entre consistência vs. disponibilidade
- Sistemas CP (ex.: MongoDB): em caso de partição, bloqueiam escrita para manter todas as réplicas sincronizadas
- Sistemas AP (ex.: Cassandra, DNS): continuam respondendo durante a partição, aceitando inconsistências temporárias entre réplicas
- Proposto por Eric Brewer em 2000, no contexto de serviços web, e formalmente provado por Gilbert & Lynch em 2002
21. Efeito do segundo sistema (Second-System Effect)
> Após um sistema pequeno e bem-sucedido, tende a vir um sistema sucessor inchado e projetado em excesso
- Padrão em que o sucesso do primeiro sistema dá confiança para despejar todas as ideias no segundo
- Feature creep e generalização excessiva (over-generalization) são as principais causas
- Identificado por Frederick Brooks em The Mythical Man-Month
22. Falácias da computação distribuída (Fallacies of Distributed Computing)
> Oito suposições equivocadas comuns entre quem projeta sistemas distribuídos pela primeira vez
- As 8 falácias: (1) a rede é confiável, (2) a latência é zero, (3) a largura de banda é infinita, (4) a rede é segura, (5) a topologia não muda, (6) há um único administrador, (7) o custo de transporte é zero, (8) a rede é homogênea
- Projetar com base nessas suposições leva a falhas inesperadas e problemas de desempenho em produção
23. Lei das consequências não intencionais (Law of Unintended Consequences)
> Ao alterar um sistema complexo, é preciso esperar resultados inesperados
- Ao mudar um componente do sistema, efeitos colaterais podem surgir em lugares imprevisíveis
- Princípio que reforça a necessidade de chaos engineering e testes abrangentes
24. Lei de Zawinski (Zawinski's Law)
> Todo programa tenta se expandir até conseguir ler e-mail
- Satiriza o fenômeno de inchaço de funcionalidades (feature bloat), em que softwares bem-sucedidos tentam adicionar cada vez mais recursos
- Observada por Jamie Zawinski (um dos primeiros desenvolvedores da Netscape)
- Um alerta sobre a tendência de ferramentas simples tentarem se transformar, com o tempo, em plataformas universais
Qualidade (Quality)
25. Regra do escoteiro (The Boy Scout Rule)
> Deixe o código em um estado melhor do que o encontrou
- O ponto central não é um grande refactoring, mas sim a melhoria contínua e incremental
- Corrigir nomes de funções confusos, remover código duplicado, adicionar testes ausentes: praticar pequenas melhorias a cada vez
- Robert C. Martin (Uncle Bob) a aplicou ao desenvolvimento de software em Clean Code (2008)
- Princípio entre engenheiros do Google: "If you touch it, you own it" — ao modificar o código, você também assume responsabilidade por sua qualidade
- Seguir essa regra ajuda a prevenir o efeito da janela quebrada (Broken Windows) e o acúmulo de dívida técnica
26. Lei de Murphy (Murphy's Law)
> Se algo pode dar errado, vai dar errado
- Base para programação defensiva, tratamento de exceções e design preparado para falhas
- Em software, é preciso projetar tratamento de erros e fallbacks com a postura de que "todo erro que pode acontecer, vai acontecer"
27. Lei de Postel / princípio da robustez (Postel's Law)
> Seja conservador no que faz e liberal no que aceita dos outros
- Ao projetar APIs, o princípio é seguir a especificação com rigor na saída, mas aceitar com flexibilidade vários formatos de entrada
- Jon Postel estabeleceu esse princípio da robustez (Robustness Principle) ao projetar os protocolos TCP/IP
- Diretriz prática para aumentar a interoperabilidade entre sistemas
28. Teoria das janelas quebradas (Broken Windows Theory)
> Não deixe design ruim, decisões erradas ou código de baixa qualidade sem correção
- Se uma "janela quebrada" (código ruim) é deixada de lado, ela provoca degradação adicional da qualidade
- Quando comentários TODO, código morto e warnings não resolvidos se acumulam na base de código, novos trechos também tendem a ser escritos em baixo nível
- É importante cultivar a prática de corrigir imediatamente mesmo problemas pequenos
29. Dívida técnica (Technical Debt)
> Tudo o que reduz a velocidade do desenvolvimento de software
- Ward Cunningham usou pela primeira vez a metáfora financeira na OOPSLA de 1992: optar por atalhos no código é pegar tempo emprestado do futuro
- Principal (custo de correção) + juros (queda contínua de produtividade causada por código bagunçado)
- Dívida técnica intencional às vezes é racional (timing de lançamento no mercado, prototipagem), mas um plano de pagamento é indispensável
- Um caso típico é pular testes automatizados: o release dá certo, mas mudanças futuras passam a gerar bugs inesperados
- Formas de resolver: refactoring, adicionar testes faltantes, melhorar o design
30. Lei de Linus (Linus's Law)
> Com um número suficiente de revisores, todo bug se torna fácil de encontrar
- Princípio central do desenvolvimento open source: com muitos olhos revisando o código, bugs viram problemas triviais
- Eric Raymond deu esse nome em The Cathedral and the Bazaar, em referência a Linus Torvalds
- Reforça a importância da cultura de code review
31. Lei de Kernighan (Kernighan's Law)
> Depurar é duas vezes mais difícil do que escrever o código originalmente
- Portanto, se você escrever código inteligente demais, provavelmente não será inteligente o bastante para depurá-lo depois
- Eis por que é preciso escrever código simples e de alta legibilidade
- Apresentado por Brian Kernighan em The Elements of Programming Style
32. Pirâmide de testes (Testing Pyramid)
> Um projeto deve ter muitos testes unitários rápidos, menos testes de integração e apenas alguns testes de UI
- Testes unitários (base): rápidos, baratos e os mais numerosos
- Testes de integração (meio): verificam a interação entre componentes
- Testes de UI/E2E (topo): devem ser minimizados, pois são lentos e frágeis
- Modelo de estratégia de testes apresentado por Mike Cohn em Succeeding with Agile
33. Paradoxo do pesticida (Pesticide Paradox)
> Se os mesmos testes forem executados repetidamente, sua eficácia diminui com o tempo
- Como os bugs que os testes existentes já conseguem encontrar acabam sendo todos capturados, é necessário adicionar continuamente novos casos de teste
- Revisar e atualizar regularmente o conjunto de testes é essencial
34. Leis da evolução de software de Lehman (Lehman's Laws of Software Evolution)
> Software que reflete o mundo real inevitavelmente precisa evoluir, e essa evolução tem limites previsíveis
- Software do tipo E (que reflete o mundo real) inevitavelmente precisa de mudanças contínuas para continuar sendo útil
- A cada mudança, a complexidade aumenta e, se isso não for gerenciado ativamente, a qualidade se deteriora
35. Lei de Sturgeon (Sturgeon's Law)
> 90% de tudo é inútil
- Proposta por Theodore Sturgeon em resposta a críticas à literatura de ficção científica
- Também se aplica ao software: entre a maior parte do código, das ferramentas e dos frameworks, apenas uma minoria é realmente excelente
- É preciso manter um alto padrão de qualidade e focar nos 10% que realmente têm valor
Escala (Scale)
36. Lei de Amdahl (Amdahl's Law)
> O ganho de velocidade obtido com paralelização é limitado pela proporção do trabalho que não pode ser paralelizado
- Se 5% de um programa for sequencial, por mais processadores que sejam adicionados, o ganho máximo teórico de velocidade será de 20x
- Reconhecer os limites da paralelização e reduzir os gargalos sequenciais é mais eficaz
- Proposta por Gene Amdahl em 1967
37. Lei de Gustafson (Gustafson's Law)
> Ao aumentar o tamanho do problema, é possível obter ganhos significativos de velocidade com processamento paralelo
- Uma perspectiva complementar à Lei de Amdahl: em problemas escaláveis, e não fixos, adicionar processadores é eficaz
- Em processamento de big data, simulações científicas etc., mais recursos permitem resolver problemas maiores
38. Lei de Metcalfe (Metcalfe's Law)
> O valor de uma rede é proporcional ao quadrado do número de usuários
- Se há 10 usuários, o valor é 100 unidades; se há 100, sobe para 10.000 unidades
- Base teórica do efeito de rede em redes sociais, mensageiros, marketplaces etc.
- Proposta por Robert Metcalfe para explicar o valor da tecnologia Ethernet
Design
39. Princípio DRY (Don't Repeat Yourself)
> Todo conhecimento deve ter uma única representação clara e autoritativa
- Inclui não apenas duplicação de código, mas também duplicação de conhecimento, lógica e dados
- A duplicação exige alterações simultâneas em vários pontos, tornando-se fonte de bugs e inconsistências
- Formalizado por Andy Hunt e Dave Thomas em The Pragmatic Programmer
40. Princípio KISS (Keep It Simple, Stupid)
> O design e os sistemas devem ser o mais simples possível
- A complexidade aumenta o custo de entendimento, manutenção e depuração
- Soluções simples costumam ser mais eficazes na maioria dos casos e também têm menor probabilidade de defeitos
- Deriva de um princípio de design proposto pela Marinha dos EUA na década de 1960
41. Princípios SOLID (SOLID Principles)
> Cinco diretrizes centrais para melhorar o design de software
- S — Princípio da responsabilidade única (Single Responsibility): uma classe deve mudar por apenas um motivo
- O — Princípio aberto-fechado (Open-Closed): deve estar aberta para extensão e fechada para modificação
- L — Princípio da substituição de Liskov: subtipos devem poder substituir seus tipos base
- I — Princípio da segregação de interfaces: clientes não devem depender de interfaces que não usam
- D — Princípio da inversão de dependência: módulos de alto nível não devem depender de módulos de baixo nível, mas de abstrações
- Formalizado por Robert C. Martin, e o acrônimo SOLID foi nomeado por Michael Feathers
42. Lei de Demeter (Law of Demeter)
> Objetos devem interagir apenas com seus amigos diretos e evitar comunicação direta com objetos estranhos
- É o princípio de evitar chamadas encadeadas como
a.getB().getC().doSomething() - Reduz o acoplamento e fortalece a encapsulação, diminuindo o alcance do impacto de mudanças
- Também é chamada de "princípio do menor conhecimento"
43. Princípio da menor surpresa (Principle of Least Astonishment)
> Softwares e interfaces devem funcionar de modo a surpreender o mínimo possível usuários e outros desenvolvedores
- Funções, APIs e UIs devem ter comportamento previsível em seus nomes e convenções
- Se uma função
delete()na prática apenas arquiva algo, isso causa surpresa → falha de design - Comportamentos não intuitivos causam bugs e erros de usuário
44. YAGNI (You Aren't Gonna Need It)
> Não adicione funcionalidades antes de elas serem necessárias
- Princípio central do Extreme Programming (XP), proposto por Ron Jeffries no fim dos anos 1990
- Escrever código porque "talvez seja necessário no futuro" gera overengineering e carga de manutenção
- Para praticar YAGNI, é preciso ter confiança no refactoring (boa cobertura de testes, CI)
- Se hoje só é necessário exportar JSON, implemente apenas JSON; XML/YAML etc. podem ser adicionados quando houver demanda
Decisões
45. Efeito Dunning-Kruger (Dunning-Kruger Effect)
> Quanto menos se sabe sobre algo, maior tende a ser a confiança
- Fenômeno em que desenvolvedores iniciantes subestimam a dificuldade de sistemas complexos, enquanto especialistas às vezes são mais humildes em relação ao próprio conhecimento
- É importante aumentar a precisão da autoconsciência por meio de code review, mentoria e aprendizado contínuo
46. Navalha de Hanlon (Hanlon's Razor)
> Não atribua à malícia aquilo que pode ser suficientemente explicado por estupidez ou descuido
- Antes de interpretar código ruim ou uma decisão equivocada de um colega como sabotagem intencional, considere primeiro ignorância, erro ou falta de tempo
- Base da confiança e da comunicação construtiva dentro da equipe
47. Navalha de Occam (Occam's Razor)
> A explicação mais simples costuma ser a mais correta
- Ao depurar, verifique primeiro a possibilidade mais simples, antes de causas complexas
- No design de arquitetura, também vale explorar primeiro soluções simples antes de adicionar camadas desnecessárias de abstração
48. Falácia do custo afundado (Sunk Cost Fallacy)
> A tendência de continuar mantendo uma escolha ruim só porque tempo ou energia já foram investidos nela
- A psicologia de não conseguir abandonar uma funcionalidade em direção errada só porque 6 meses já foram investidos em seu desenvolvimento
- A decisão correta deve se basear no valor futuro, não no investimento passado
49. O mapa não é o território (The Map Is Not the Territory)
> Uma representação da realidade (modelo) não é igual à própria realidade
- Diagramas UML, documentos de arquitetura, modelos de dados etc. são apenas aproximações da realidade
- Não se deve confiar cegamente no modelo; é preciso observar o comportamento real do sistema e atualizar o modelo
50. Viés de confirmação (Confirmation Bias)
> A tendência de preferir informações que apoiem crenças ou ideias já existentes
- A armadilha de coletar seletivamente apenas informações favoráveis à stack tecnológica ou à decisão de design que você escolheu
- Buscar ativamente evidências contrárias e aceitar diferentes perspectivas é a chave para uma tomada de decisão equilibrada
51. Hype Cycle e a Lei de Amara (The Hype Cycle & Amara's Law)
Há uma tendência de superestimar os efeitos de curto prazo da tecnologia e subestimar seu impacto de longo prazo
- Hype Cycle do Gartner: gatilho tecnológico → pico das expectativas infladas → vale da desilusão → rampa de esclarecimento → platô de produtividade
- Ao adotar novas tecnologias (blockchain, AI etc.), é preciso não se deixar levar pelo superaquecimento de curto prazo e avaliar a utilidade prática de longo prazo
52. Efeito Lindy (The Lindy Effect)
Quanto mais tempo algo foi usado, maior a probabilidade de continuar sendo usado no futuro
- Tecnologias usadas há décadas, como UNIX, SQL e a linguagem C, têm grande probabilidade de continuar sobrevivendo por muito tempo
- Base teórica para escolher tecnologias comprovadas em vez de frameworks novos
- Popularizado por Nassim Nicholas Taleb em Antifragile
53. Pensamento por primeiros princípios (First Principles Thinking)
Uma forma de pensar que decompõe problemas complexos em seus componentes mais básicos e depois os reconstrói a partir disso
- Remove práticas e suposições existentes e chega a soluções partindo de verdades fundamentais
- Ficou conhecido pelo caso de Elon Musk aplicando isso à redução de custos de foguetes da SpaceX
- Ao projetar sistemas complexos, é preciso evitar a mentalidade de "sempre foi feito assim"
54. Pensamento por inversão (Inversion)
Um método de resolver problemas assumindo o resultado oposto e raciocinando de trás para frente
- Em vez de "como ter sucesso", pensar primeiro em "como fracassar" para identificar fatores de risco
- Base teórica para a análise de modos de falha (Failure Mode Analysis) e o pre-mortem
- Modelo mental usado com frequência por Charlie Munger
55. Princípio de Pareto / Regra 80/20 (Pareto Principle)
80% dos problemas surgem de 20% das causas
- Há uma tendência de que 80% de todos os bugs se concentrem em 20% do código
- Concentrar recursos nos 20% de maior impacto é uma estratégia eficiente de alocação de recursos
- Deriva do princípio observado por Vilfredo Pareto na distribuição da posse de terras na Itália
56. Lei de Cunningham (Cunningham's Law)
A melhor maneira de obter a resposta certa na internet não é fazer uma pergunta, mas publicar uma resposta errada
- As pessoas tendem a participar mais ativamente corrigindo informações erradas do que respondendo perguntas
- É uma lei que leva o nome de Ward Cunningham (inventor do Wiki), mas na prática foi Steven McGeady quem lhe deu esse nome
- Um insight aplicável à documentação e ao compartilhamento de conhecimento em comunidades open source
2 comentários
Quando se faz
vibe coding, no começo até parece bom, mas no fim parece que isso volta como karma...Comentários do Hacker News
Eu detesto especialmente a frase "otimização prematura é a raiz de todo mal". Essa frase surgiu no contexto de 1974, então as premissas são diferentes das de hoje. Naquela época, otimização era algo mais próximo de assembly e contagem de ciclos, mas hoje desempenho é, em grande parte, uma questão de escolhas de arquitetura, então precisa ser considerado desde o início. O conselho de usar profiling para encontrar bugs de desempenho acidentais, como um O(n²), ainda continua válido, mas quando o custo das abstrações vira gargalo, é fácil acabar só empilhando cache e paralelismo e criando um sistema mais complexo e mais lento. Hoje, acho que otimização tardia é tão ruim quanto otimização prematura, talvez até pior
ConcurrentHashMapporque depois talvez o código vá para um contexto multithread, e na maioria dos casos a diferença de desempenho não é grande. Mesmo assim, PRs acabam bloqueados e surgem discussões intermináveis porque "HashMapé mais rápido". Em vez disso, faz mais sentido focar nos lugares que realmente mudam a experiência, como 40 chamadas bloqueantes ao PostgreSQL ou requisições web desnecessárias. Dito isso, acho perfeitamente válido fazer otimização cedo no nível de algoritmoSenti falta da Lei de Curly. Uma variável deve ter um único significado e não deve armazenar valores de domínios diferentes dependendo da situação, nem cumprir dois papéis ao mesmo tempo. A metáfora de não virar algo que é "cera para piso e cobertura de sobremesa" cai perfeitamente
Quando juntam todas essas "leis" de software num lugar só, sinto que há contradições internas demais, e no fim fica fácil escolher a frase que melhor justifica o argumento que a pessoa já queria defender. A parte realmente difícil é saber quando quebrar qual lei, e por quê
Como lei da engenharia de software versão 2026, eu queria brincar que todos os sites vão ser feitos por vibe coding com Claude Opus. O resultado seria um fundo em tom creme lembrando a Anthropic, uma mistura exagerada de fontes e pesos como se alguém tivesse acabado de descobrir tipografia, uma abundância de interfaces em cartões, e aquele padrão repetido de borda colorida arredondada em apenas um lado do cartão
Acho que a Lei da Iteração de Boyd também deveria entrar. A ideia é que, ao lidar com complexidade, iteração rápida muitas vezes produz resultados melhores do que análise profunda, o que fica ainda mais marcante quando se lembra que Boyd foi o criador do loop OODA
Acho que havia um melhor meta-princípio nos comentários apagados sobre este texto. Era algo como: "toda lei da engenharia de software é imediatamente mal interpretada e aplicada sem senso crítico de um jeito que horrorizaria o autor original". Olhando para o comportamento de LLMs sem o contexto principal, isso fica ainda mais compreensível. No fim, há um limite para comprimir décadas de sabedoria e experiência em uma frase de efeito
Em vez de fazer por vibe coding um site inteiro de "leis da engenharia de software", quero perguntar que lei foi quebrada ao não simplesmente criar uma página na Wikipedia
Acho que esse tipo de conteúdo deveria ser conhecimento básico a ponto de virar requisito de contratação. Parece o tipo de coisa que todo mundo deveria saber
Mesmo não sendo uma lei específica de software, costumo ensinar a Cerca de Chesterton primeiro a estagiários e recém-contratados
Acho que a Lei da Conservação da Complexidade de Tesler já traz uma percepção interessante só na formulação. A ideia de que toda aplicação tem uma complexidade inerente que não pode ser removida, apenas deslocada. Mas quando entra na explicação, parece acabar reduzida ao conselho comum de incomodar menos o usuário, e aí isso perde um pouco do brilho para mim. O usuário inevitavelmente terá de lidar com o nível necessário de complexidade, e reduzi-la à força muitas vezes transforma tudo num brinquedo sem flexibilidade. Por isso, ao refatorar, acho mais útil lembrar que simplificar uma parte pode tornar outra mais complexa