O Modelo Mental por Trás das Regras de Engenharia do Node.js
Esta seção está repleta de regras concretas - sem I/O síncrono em um manipulador de requisições, valide todas as rotas mutáveis, limite o fetch de saída com um timeout. Cada uma delas soa como uma instrução simples, mas cada regra nesta seção na verdade codifica algo mais específico: um modo de falha que alguém já atingiu, comprimido em uma instrução barata o suficiente para ser seguida sem ter que redescobrir o raciocínio do zero a cada vez.
Uma regra de engenharia é memória institucional comprimida - uma falha passada específica, generalizada em uma instrução que permite ao próximo engenheiro evitá-la sem reaprender a lição do zero.
Por que Importa: Equipes que tratam regras como estilo arbitrário acabam ignorando-as sob pressão de prazo ou seguindo-as além do ponto em que ainda se aplicam - ambos os modos de falha remontam a não entender contra o que a regra realmente estava protegendo.
Conceitos Chave:regra, nível de aplicação, ciclo de vida da regra, processo de exceção, deterioração da regra.
Quando Usar: Decidir se uma nova convenção merece se tornar uma regra documentada, escolher quão estritamente aplicá-la, escrever uma regra para que ela sobreviva à pessoa que a escreveu, ou decidir quando uma regra antiga deve ser revisada.
Limitações / Trade-offs: Regras trocam julgamento por consistência - quanto mais você codifica, menos cada engenheiro precisa raciocinar a partir de princípios fundamentais, mas também mais um codebase acumula instruções que sobrevivem à situação que as justificou.
Tópicos Relacionados: registros de decisões de arquitetura, portões de qualidade de CI, normas de revisão de código, aplicação de análise estática.
Toda regra de engenharia duradoura começa da mesma forma: algo quebrou, alguém descobriu o porquê, e a equipe decidiu que a correção não deveria depender de todos a redescobrirem independentemente. Uma regra como "nenhum fs.readFileSync em um manipulador de requisições" não é uma preferência de estilo sobre nomes de funções - é o resíduo de um incidente onde uma leitura síncrona paralisou todas as outras requisições do processo. A regra é mais barata de declarar do que reaprender o incidente, que é toda a razão pela qual as regras existem: elas permitem que lições caras sejam pagas uma vez e reutilizadas para sempre.
Essa perspectiva importa porque distingue uma regra de duas coisas com as quais ela é frequentemente confundida. Uma diretriz é um padrão que engenheiros razoáveis podem substituir com julgamento - "preferir async/await em vez de cadeias de promessas brutas" sobrevive a ser ignorado em um caso extremo. Uma regra, no sentido que esta seção usa a palavra, é algo que a equipe decidiu que deve valer sem julgamento caso a caso, geralmente porque o custo de errar (uma falha de segurança, uma interrupção, um bug de perda de dados) é alto o suficiente para que "use seu julgamento" não seja uma resposta aceitável. Uma escolha de estilo de casa (abas vs. espaços) não é nenhuma das duas - não tem modo de falha por trás dela, que é por que ferramentas de formatação em vez de documentos de regras dominam esse território.
Uma analogia útil: pense em um documento de regras como o tecido cicatricial acumulado de um codebase, tornado legível. O tecido cicatricial se forma em resposta a uma lesão específica e depois continua protegendo contra ela muito depois que alguém se lembra do corte original - que é exatamente o trade-off que vale a pena manter em mente. Uma regra que parou de proteger contra algo real é uma regra que vale a pena questionar, não uma regra a ser obedecida reflexivamente.
Nem toda regra merece a mesma força por trás dela, e combinar a aplicação com o custo real da violação é a maior parte do que separa um documento de regras útil de uma lista de desejos que ninguém lê. As regras nesta seção estão em um espectro:
Convenção documentada - escrita, explicada, esperada em revisão, mas não verificada mecanicamente. Apropriada para chamadas de julgamento onde o contexto importa (escolher entre um barramento de eventos e uma chamada direta dentro de um monólito modular).
Aplicada por revisão de código - espera-se que um revisor capture violações, apoiado por uma lista de verificação ou modelo de PR para que não dependa da memória. Apropriada para coisas que um linter genuinamente não consegue avaliar (a seção de contexto deste ADR é realmente precisa).
Aplicada por CI (portão mecânico) - uma regra de lint, verificação de tipo ou teste que falha automaticamente a compilação. Apropriada para qualquer coisa com uma assinatura clara e verificável - padrões banidos, forma de validação de entrada ausente, um parâmetro limit sem limite.
A relação entre esses níveis é direcional e importante: uma regra geralmente começa como uma convenção documentada (porque alguém acabou de aprender a lição e a escreveu), e conquista seu caminho para a aplicação mecânica à medida que a equipe confirma que o padrão se repete e pode ser detectado automaticamente. Pular direto para um portão de CI para algo que não pode ser verificado de forma confiável mecanicamente produz falsos positivos que corroem a confiança em todo o portão; deixar uma regra verificável e de alto custo como "apenas documentada" para sempre significa que ela depende de cada revisor se lembrar dela, indefinidamente.
incidente acontece │ ▼lição é nomeada e escrita ── convenção documentada │ (padrão se repete, é verificável) ▼revisores observam explicitamente ── aplicada por revisão de código │ (um linter/verificação de CI pode expressá-la) ▼portão mecânico bloqueia violações ── aplicada por CI
Um processo de exceção é o que impede que uma regra se torne burocracia inflexível depois de ser aplicada mecanicamente. Uma regra declarada como absoluta ("nunca faça X") sem uma saída de emergência eventualmente encontra um caso legítimo que não antecipou - momento em que a equipe quebra a regra silenciosamente (minando-a para todos) ou bloqueia uma mudança legítima (minando a confiança no processo). Modelo de ADR para Node existe em parte por essa razão: um Registro de Decisão de Arquitetura é o mecanismo para registrar por que um caso específico se desvia da regra padrão, para que a exceção seja visível e deliberada em vez de silenciosa.
As regras acumulam um tipo específico de decadência que vale a pena nomear diretamente: deterioração da regra, onde uma instrução continua sendo aplicada muito depois que a situação que a justificou mudou. Uma regra de fixação de dependência escrita quando uma equipe não tinha ferramentas de auditoria automatizadas pode não valer mais a pena depois que npm audit roda em CI em cada PR - a regra não está errada, apenas foi substituída por uma aplicação melhor do mesmo objetivo subjacente. Regras que nomeiam a falha que previnem envelhecem melhor do que regras que apenas nomeiam o comportamento exigido, porque uma equipe que revisita "por que fazemos isso" pode realmente avaliar se a falha ainda é um risco real; uma regra declarada como instrução pura sem justificativa apenas é seguida - ou silenciosamente descartada - sem que ninguém possa dizer qual está correta.
É aqui também que uma seção de regras justifica seu valor em escala organizacional em vez de escala de engenheiro individual. Um único engenheiro sênior pode ter o conhecimento tácito de "não bloquear o event loop" e capturar violações em revisão por instinto. Isso não se transfere - nem para um novo contratado, nem para uma segunda equipe construindo um segundo serviço, nem para um engenheiro seis meses afastado do incidente original. Escrever a regra, definir seu nível de aplicação e colocar os verificáveis em CI é o que torna a lição organizacionalmente durável em vez de dependente da memória de uma pessoa estar presente durante a revisão de código.
O Lista de Verificação de Regras do Projeto Node vale a pena ser lido sob essa ótica especificamente: ele agrupa 25 regras em níveis (segurança/proteção bloqueia o lançamento, portões de API/qualidade bloqueiam o tráfego GA, maturidade operacional completa dentro do primeiro mês) - esse escalonamento é em si uma aplicação de "nem toda regra merece a mesma urgência", aplicada na escala de um serviço inteiro em vez de uma convenção.
Nível de aplicação
Força
Fraqueza
Melhor Encaixe
Convenção documentada
Barata de escrever; preserva o julgamento para casos extremos genuínos
Depende inteiramente de memória e cultura; se deteriora sob pressão de prazo
Decisões dependentes de contexto que um linter não consegue avaliar
Aplicada por revisão de código
Captura nuances que uma verificação mecânica perderia
Inconsistente - depende de qual revisor, quanto tempo ele tem
Regras com chamadas de julgamento reais, mas com riscos altos o suficiente para precisar de um segundo par de olhos
Portão aplicado por CI
Aplica-se uniformemente, todas as vezes, a todos os contribuidores
Só funciona para padrões genuinamente verificáveis; falsos positivos corroem a confiança
Violações de alto custo e claramente detectáveis (APIs banidas, validação ausente, consultas ilimitadas)
"Um documento de regras e um guia de estilo são a mesma coisa." Estilo não tem modo de falha por trás - nada quebra de qualquer maneira, que é por que um formatador, não um documento de regras, é responsável por essa decisão. Uma regra existe porque violá-la tem um custo real e específico; confundir os dois faz com que regras reais pareçam tão opcionais quanto preferências de largura de tabulação.
"Uma vez que uma regra é escrita, ela é aplicada." Uma regra não aplicada é um desejo - ela vale apenas enquanto cada engenheiro se lembrar e escolher segui-la, que é precisamente o modo de falha que as regras existem para eliminar em primeiro lugar.
"Toda regra deve eventualmente se tornar um portão de CI." Apenas padrões genuinamente verificáveis pertencem lá; forçar uma regra dependente de julgamento em um portão mecânico produz falsos positivos que ensinam os engenheiros a contornar o portão inteiramente.
"Regras sem exceções são regras mais fortes." Uma regra absoluta sem uma saída de emergência apenas realoca a exceção para "violada silenciosamente" em vez de "deliberadamente e visivelmente justificada" - o que é estritamente pior para qualquer pessoa que auditar o codebase mais tarde.
"Regras antigas podem ser deixadas em vigor indefinidamente." Uma regra pode sobreviver à falha que estava protegendo, especialmente depois que ferramentas melhores a substituem - regras que não são revisadas acumulam-se como atrito sem o benefício correspondente.
O que realmente distingue uma "regra" de uma "diretriz" nesta seção?
Uma diretriz é um padrão que os engenheiros podem razoavelmente substituir usando julgamento. Uma regra é algo que a equipe decidiu que deve valer sem julgamento caso a caso, geralmente porque o custo de errar é alto - uma brecha de segurança, uma interrupção, perda de dados - não porque uma formulação específica é preferida.
Por que as regras precisam de um "porquê" documentado, não apenas um "o quê"?
Uma regra que apenas declara o comportamento exigido é seguida - ou silenciosamente descartada - sem que ninguém possa avaliar se ela ainda se aplica. Nomear a falha que ela previne permite que um engenheiro futuro julgue se essa falha ainda é um risco real antes de decidir manter, relaxar ou automatizar a regra.
Como uma regra passa de "documentada" para "aplicada em CI"?
Ela conquista essa promoção quando duas coisas são verdadeiras: o padrão realmente se repete (vale o custo de configuração), e é o tipo de coisa que uma verificação mecânica pode detectar de forma confiável sem falsos positivos. Regras que precisam de julgamento real permanecem na aplicação de revisão de código em vez disso.
Por que não tornar imediatamente toda regra importante um portão de CI rígido?
Porque os portões de CI só funcionam bem para padrões que uma ferramenta pode verificar de forma confiável. Forçar uma regra dependente de julgamento em um portão mecânico produz falsos positivos, e falsos positivos ensinam os engenheiros a desconfiar ou contornar o portão - minando a aplicação para as regras que genuinamente precisam dela.
Qual é o propósito de um processo de exceção para uma regra?
Ele dá a um caso extremo legítimo um caminho visível e deliberado para contornar o padrão, em vez de forçar uma violação silenciosa ou bloquear uma mudança válida completamente. Um ADR é uma forma comum de registrar essa decisão para que a exceção seja auditável em vez de invisível.
Como uma "regra" difere de uma preferência de estilo simples como tabulações vs. espaços?
Uma preferência de estilo não tem modo de falha por trás - nada quebra de qualquer maneira, que é por que um formatador, não um documento de regras, é responsável por essa decisão. Uma regra existe especificamente porque violá-la tem um custo real e descritível.
O que é "deterioração da regra" e por que ela importa?
É quando uma regra continua sendo aplicada depois que a situação que a justificou mudou - por exemplo, uma regra manual de fixação de dependência que foi substituída por ferramentas de auditoria automatizadas. Regras que não são periodicamente revisadas acumulam-se como atrito sem um benefício correspondente.
Todo serviço em uma organização deve seguir todas as regras desta seção identicamente?
Não necessariamente com a mesma urgência - a abordagem de escalonamento em Lista de Verificação de Regras do Projeto Node agrupa regras por quão bloqueadoras de lançamento elas são, porque uma regra de segurança/proteção e uma regra de maturidade operacional não carregam o mesmo risco se deixadas sem atenção por uma semana.
Quem decide se algo se torna uma regra da equipe?
Na prática, quem quer que seja o responsável pelo postmortem ou pelo custo recorrente do padrão - mas a decisão deve ser visível, não tácita, que é exatamente o que um documento de regras e um rastro de ADRs fornecem em vez de deixá-lo na memória de um engenheiro.
Um grande documento de regras é um sinal de uma organização de engenharia madura ou burocrática?
Depende se cada regra ainda nomeia um modo de falha real e atual e tem uma aplicação correspondente ao seu custo real. Um documento de regras que é periodicamente podado e reescalonado é maturidade; um que apenas cresce e nunca é revisitado é a versão burocrática do mesmo artefato.