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 influenciam sistemas de software, equipes e tomada de decisão, cobrindo amplamente desde operação de equipes 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 influencia diretamente o design do sistema e a produtividade
- Na área de arquitetura, organiza restrições e princípios que devem ser considerados no design de sistemas complexos, como a Lei de Hyrum, o teorema CAP e a Lei de Gall
- As leis ligadas à qualidade tratam das dificuldades práticas de manter a qualidade do código e de depuração, como dívida técnica, a pirâmide de testes e a Lei de Kernighan
- Na área de tomada de decisão, abrange vieses cognitivos e critérios de julgamento comuns no processo de 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 naturalmente tende a seguir a estrutura de comunicação da organização que a criou
- Se a equipe está dividida em 3 partes, o sistema também tende a ser dividido em 3 grandes módulos
- Também existe a "estratégia Conway reversa" (Inverse Conway Maneuver): uma abordagem em que a estrutura da equipe é reorganizada primeiro para se adequar à 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 integrantes entram, os membros atuais da equipe gastam tempo com treinamento e coordenação, o que reduz temporariamente a produtividade total
- À medida que a equipe cresce, os canais de comunicação aumentam geometricamente (com n pessoas, são n(n-1)/2)
- Frederick Brooks formulou essa lei no livro The Mythical Man-Month, de 1975, com base em sua experiência no projeto IBM OS/360
- É possível explicar quantitativamente com a 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 pessoas, e sim ajustar o escopo ou mudar 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
- Número derivado por Robin Dunbar a partir da correlação entre o tamanho do cérebro de primatas e o tamanho de seus grupos sociais
- A estrutura hierárquica social de Dunbar: ~5 pessoas (relações íntimas), ~15 pessoas (colaboradores de confiança), ~50 pessoas (relações de trabalho próximas), ~150 pessoas (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 hierarquia formal e processos
- A "Two-Pizza Team" da Amazon (5 a 10 pessoas) reflete que, mesmo dentro de 150 pessoas, a colaboração prática 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), em que a contribuição de cada indivíduo diminui à medida que o grupo cresce
- Em equipes de software, quando o time aumenta, o senso de responsabilidade individual se dilui e o custo de coordenação sobe
- Explica por que equipes pequenas entregam mais 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 fazem metade de todo o trabalho
- Quanto maior a organização, maior a dependência de um pequeno grupo de alto desempenho
- Explica por que a produtividade não cresce linearmente quando a equipe se expande
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 a distância entre o papel de gestão e a especialização técnica em organizações tecnológicas
- Ao desenhar uma estrutura de liderança técnica, é preciso reconhecer essa lacuna e criar mecanismos de compensação
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 alguém competente em um papel é promovido e se torna incompetente em sua nova função
- Reflete a realidade de que um excelente desenvolvedor não necessariamente será um bom gerente
- Mostra a necessidade de uma estrutura de carreira em duas trilhas separando a trilha de IC (Individual Contributor) da trilha de gestão
8. Bus Factor
Número mínimo de saídas de membros da equipe que pode colocar o 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 de Dilbert (Dilbert Principle)
Empresas tendem a promover funcionários incompetentes a cargos de gestão para 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 o lugar onde se causa menos dano ao trabalho prático
Planejamento (Planning)
10. Otimização prematura / princípio de otimização de Knuth (Premature Optimization)
A otimização prematura é a raiz de todo mal
- Donald Knuth apresentou isso 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 do código é desperdício
- A ordem correta é: primeiro fazer funcionar → depois fazer corretamente → e, se necessário, tornar mais rápido
- Como código otimizado aumenta a complexidade, isso deve ser feito apenas após identificar 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 para ocupar 2 semanas; se é de 4, cresce para 4
- Isso explica por que é importante definir milestones curtos e claros em projetos de software
- Agile baseado em sprint é uma resposta prática a essa lei
12. Regra do 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, polimento e correção de bugs) levam muito mais tempo do que o esperado
- A expressão "quase pronto" pode, na prática, significar que o projeto ainda está na metade 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
- Uma lei com estrutura recursiva e autorreferente, que expressa a dificuldade intrínseca de estimar cronogramas de software
- Mesmo adicionando margem, a realidade ainda ultrapassa o prazo
- Douglas Hofstadter a apresentou no livro Gödel, Escher, Bach, de 1979
14. Lei de Goodhart (Goodhart's Law)
Quando uma métrica vira meta, ela deixa de ser uma boa métrica
- Um exemplo típico é quando cobertura de código vira KPI e passa a gerar testes sem sentido
- Se a produtividade é medida por linhas de código (LOC), surgem códigos desnecessariamente verbosos
- É preciso focar não na otimização da métrica, mas na entrega de valor real
15. Lei de Gilb (Gilb's Law)
Quando algo precisa ser quantificado, medi-lo de alguma forma é melhor do que não medi-lo
- Mesmo que uma medição perfeita seja impossível, uma medição aproximada ainda é sempre melhor do que nenhuma medição
- Isso 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 passará a depender de todo comportamento observável do sistema
- Não só a especificação oficial da API, mas também comportamentos não oficiais como timing, formato das mensagens de erro e ordem de ordenação acabam se tornando alvo de dependência
- Caso do Microsoft Windows, que manteve comportamentos de versões antigas para garantir compatibilidade com aplicativos de terceiros que dependiam de comportamentos não documentados e bugs do passado
- Observado por Hyrum Wright, do Google, por volta de 2011–2012, a partir de sua experiência com mudanças em bibliotecas internas do Google
- O colega Titus Winters deu o nome de "Lei de Hyrum" (Software Engineering at Google)
- O contrato real não é a API oficial, mas o conjunto completo do comportamento efetivamente observado
17. Lei de Gall (Gall's Law)
Um sistema complexo que funciona é necessariamente o resultado da evolução de um sistema simples que funciona
- Ao tentar projetar um sistema complexo desde o início, há variáveis desconhecidas e não validadas demais, o que aumenta muito a probabilidade de fracasso
- Base teórica da 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 migrações para microsserviços, é vantajoso começar com um monólito e separar aos poucos
- Proposta por John Gall em 1975 no livro Systemantics (um clássico cult publicado após ser recusado 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 típico é o ORM, que esconde o SQL, mas, quando surgem problemas de performance, acaba sendo necessário verificar as queries geradas
- O garbage collection de Java/Python também é uma abstração, mas comportamentos internos como pausas do GC afetam o desempenho
- A lição não é que abstrações sejam ruins, mas que é preciso se preparar para quando a abstração quebrar
- Joel Spolsky apresentou a ideia em um post de blog de 2002 com exemplos como TCP e memória virtual
- Também se conecta, em termos de 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 uma thread de e-mail transfere isso para o usuário
- Um bom design move a complexidade da experiência do usuário para dentro do sistema
- Formalizada por Larry Tesler nos anos 1980 durante o trabalho no Apple Lisa e nas primeiras GUIs
20. Teorema CAP (CAP Theorem)
Sistemas distribuídos só conseguem garantir duas entre consistência (C), disponibilidade (A) e tolerância a partições (P)
- Como partições de rede são inevitáveis na prática, a escolha real é consistência vs. disponibilidade
- Sistemas CP (ex.: MongoDB): em caso de partição, bloqueiam escritas para manter todas as réplicas sincronizadas
- Sistemas AP (ex.: Cassandra, DNS): continuam respondendo a requisições durante a partição, aceitando inconsistência temporária entre réplicas
- Proposto por Eric Brewer em 2000 no contexto de serviços web, com prova formal de Gilbert & Lynch em 2002
21. Efeito do segundo sistema (Second-System Effect)
Depois de um sistema pequeno e bem-sucedido, tende a vir um sistema sucessor inchado e excessivamente projetado
- O sucesso do primeiro sistema dá confiança demais, e no segundo surge o padrão de despejar todas as ideias
- Excesso de funcionalidades (feature creep) e generalização excessiva (over-generalization) são as causas principais
- 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 que pessoas fazendo design de sistemas distribuídos pela primeira vez costumam ter
- 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á apenas um 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 mudar um sistema complexo, é preciso esperar resultados inesperados
- Ao alterar um componente do sistema, efeitos colaterais podem surgir em lugares imprevisíveis
- Princípio que reforça a necessidade de engenharia do caos 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 passam a querer adicionar cada vez mais recursos
- Observado por Jamie Zawinski (desenvolvedor dos primeiros tempos da Netscape)
- Um alerta sobre a tendência de ferramentas simples tentarem virar plataformas para tudo com o passar do tempo
Qualidade (Quality)
25. Regra do Escoteiro (The Boy Scout Rule)
Você deve deixar o código em um estado melhor do que o encontrou
- O essencial não é um grande refactoring, mas sim uma melhoria contínua e incremental
- Corrigir nomes de funções confusos, remover código duplicado, adicionar testes ausentes e praticar pequenas melhorias sempre
- Robert C. Martin (Uncle Bob) aplicou a ideia ao desenvolvimento de software em Clean Code (2008)
- Princípio dos engenheiros do Google: "If you touch it, you own it" — ao modificar o código, você também assume a responsabilidade pela sua qualidade
- Praticar essa regra ajuda a evitar o efeito das janelas quebradas (Broken Windows) e o acúmulo de dívida técnica
26. Lei de Murphy (Murphy's Law)
Tudo que 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 você faz e liberal no que aceita dos outros
- Na criação de APIs, o princípio é seguir a especificação com rigor na saída, mas aceitar com flexibilidade formatos variados na entrada
- Princípio da robustez (Robustness Principle) estabelecido por Jon Postel no projeto dos 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) for deixada de lado, ela tende a provocar degradação adicional da qualidade
- Quando comentários TODO, código morto e warnings não resolvidos se acumulam no codebase, o código novo também tende a ser escrito em um nível mais baixo
- É importante cultivar uma cultura de corrigir mesmo os pequenos problemas assim que forem encontrados
29. Dívida técnica (Technical Debt)
Tudo aquilo que reduz a velocidade do desenvolvimento de software
- Ward Cunningham usou a metáfora financeira pela primeira vez na OOPSLA de 1992: escolher atalhos no código é como 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, prototipagem), mas um plano de quitação é indispensável
- Um caso típico é pular testes automatizados: o release pode dar certo, mas mudanças posteriores passam a gerar bugs inesperados
- Formas de resolver: refactoring, adicionar testes ausentes, 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: muitos olhos revisando o código fazem com que bugs se tornem problemas triviais
- Nome dado por Eric Raymond 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 o código da forma mais engenhosa possível, não será engenhoso o bastante para depurá-lo
- Eis por que é preciso escrever código simples e legível
- 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, de baixo custo, e os mais numerosos
- Testes de integração (meio): validam a interação entre componentes
- Testes de UI/E2E (topo): devem ser minimizados por serem 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 você executar repetidamente os mesmos testes, a eficácia deles diminui com o tempo
- Como os bugs que os testes existentes já conseguem capturar acabam sendo todos encontrados, é 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)
Softwares que refletem o mundo real precisam inevitavelmente evoluir, e essa evolução tem limites previsíveis
- Softwares do tipo E (que refletem o mundo real) precisam mudar continuamente para continuarem úteis
- A cada mudança, a complexidade aumenta e, se isso não for gerenciado ativamente, a qualidade se degrada
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 padrões elevados 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 paralelizada
- Se 5% do programa for sequencial, mesmo com infinitos processadores o ganho máximo teórico de desempenho será de 20x
- Reconhecer os limites da paralelização e reduzir os gargalos sequenciais costuma ser 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 substanciais de desempenho com processamento paralelo
- Uma visão 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; com 100 usuários, 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 (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 alterar vários pontos ao mesmo tempo, 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 compreensão, manutenção e depuração
- Soluções simples costumam ser mais eficazes na maioria dos casos e também menos propensas a falhas
- Deriva de um princípio de design proposto pela Marinha dos EUA nos anos 1960
41. Princípios SOLID (SOLID Principles)
Cinco diretrizes fundamentais 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 aberto para extensão e fechado 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: o cliente não deve depender de interfaces que não usa
- 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
- Formalizados por Robert C. Martin, com o acrônimo SOLID batizado por Michael Feathers
42. Lei de Deméter (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 reforça a encapsulação, diminuindo o impacto de mudanças
- Também conhecida como "princípio do menor conhecimento"
43. Princípio da Menor Surpresa (Principle of Least Astonishment)
Softwares e interfaces devem se comportar da forma que menos surpreenda os usuários e outros desenvolvedores
- Funções, APIs e UIs devem ter comportamento previsível em nomes e convenções
- Se uma função
delete()na prática apenas arquiva, isso gera surpresa → defeito 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" leva a overengineering e custo 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. devem ser adicionados quando forem exigidos
Tomada de decisão (Decisions)
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 tendem a ser mais humildes sobre o 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 do time
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
- Também no design de arquitetura, vale explorar 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 apenas porque tempo ou energia já foram investidos
- A dificuldade psicológica de não conseguir abandonar uma funcionalidade desenvolvida por 6 meses, mesmo quando ela seguiu na direção errada, por causa do tempo investido
- A decisão correta deve se basear não no investimento passado, mas no valor futuro
49. O mapa não é o território (The Map Is Not the Territory)
Uma representação da realidade (modelo) não é a própria realidade
- Diagramas UML, documentação 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 do sistema real e atualizá-lo
50. Viés de Confirmação (Confirmation Bias)
A tendência de favorecer informações que apoiam crenças ou ideias já existentes
- A armadilha de selecionar 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
- O Hype Cycle da Gartner: gatilho tecnológico → pico das expectativas infladas → vale da desilusão → rampa do esclarecimento → platô da produtividade
- Ao adotar novas tecnologias (blockchain, IA etc.), é preciso não se deixar levar pelo superaquecimento de curto prazo e avaliar a utilidade prática no longo prazo
52. Efeito Lindy (The Lindy Effect)
Quanto mais tempo algo é 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 chance 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 deles
- Remove práticas e suposições existentes e chega a soluções a partir de verdades fundamentais
- Famoso pelo caso em que Elon Musk aplicou isso à redução de custos de foguetes da SpaceX
- Ao projetar sistemas complexos, é preciso tomar cuidado com 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 análise de modos de falha (Failure Mode Analysis) e pre-mortem
- Um modelo mental frequentemente usado 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
- Derivado do princípio observado por Vilfredo Pareto na distribuição da propriedade de terras na Itália
56. Lei de Cunningham (Cunningham's Law)
A melhor forma de obter a resposta certa na internet não é fazer uma pergunta, mas postar uma resposta errada
- As pessoas tendem a participar mais ativamente de corrigir informações erradas do que de responder perguntas
- A lei leva o nome de Ward Cunningham (inventor do Wiki), mas na prática foi Steven McGeady quem deu esse nome
- Um insight que pode ser aproveitado para documentação e compartilhamento de conhecimento em comunidades open source
2 comentários
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
Quando se faz
vibe coding, no começo até parece bom, mas no fim parece que isso volta como karma...