- Armadilhas nada intuitivas em que desenvolvedores costumam cair são organizadas para apresentar as causas de bugs que tendem a ocorrer com facilidade
- Aborda problemas frequentes em várias tecnologias, como HTML, CSS, Unicode/codificação de texto, ponto flutuante e tempo
- Enfatiza que diferenças sutis de sintaxe e comportamento em cada linguagem e framework podem gerar mal-entendidos ou erros
- Explica com exemplos as armadilhas que podem surgir em ambientes reais de produção em áreas centrais de backend, como concorrência, redes e bancos de dados
- Por meio de vários exemplos e links de referência, orienta sobre situações problemáticas, formas de resolvê-las e melhorias para comportamentos inesperados
HTML e CSS
-
Valor padrão de min-width em Flexbox/Grid
min-widthéautopor padrãomin-width: autoé determinado pelo tamanho do conteúdo e tem precedência sobreflex-shrink,overflow: hidden,width: 0,max-width: 100%- Recomendação: declarar
min-width: 0
-
Diferença entre horizontal e vertical no CSS
width: autotenta preencher o espaço do elemento pai, enquantoheight: autose ajusta ao conteúdowidth: autode elementos inline, inline-block e float não se expandemargin: 0 autocentraliza na horizontal,margin: auto 0não centraliza na vertical (mas emflex-direction: column, a centralização vertical é possível)- Colapso de margem só ocorre na vertical
- Se a direção do layout mudar, como em
writing-mode: vertical-rl, o comportamento também se inverte
-
Block Formatting Context (BFC)
- É possível criar um BFC com
display: flow-root(também é possível comoverflow: hidden/auto/scroll,display: tableetc., mas há efeitos colaterais) - Um BFC pode evitar que margens verticais de irmãos adjacentes se sobreponham ou que a margem do filho “vaze” para fora do pai
- Se o pai contiver apenas filhos com float, sua altura colapsa para 0 → isso pode ser corrigido com BFC
- Se houver
borderoupadding, não ocorre colapso de margem
- É possível criar um BFC com
-
Stacking Context
- Condições que criam um novo stacking context
- Propriedades de renderização como
transform,filter,perspective,mask,opacityetc. position: fixedoustickyz-indexdefinido + posicionamentoabsolute/relativez-indexdefinido + elemento dentro de flexbox/gridisolation: isolate
- Propriedades de renderização como
- Características
z-indexsó se aplica dentro do stacking context- As coordenadas de
position: absolute/fixedse baseiam no ancestral posicionado mais próximo stickynão funciona atravessando o stacking context- Mesmo
overflow: visibleé recortado pelo stacking context background-attachment: fixedé posicionado com base no stacking context
- Condições que criam um novo stacking context
-
Unidades de viewport
- Em navegadores móveis, quando a barra de endereço/barra de navegação some da tela ao rolar, o valor de
100vhmuda - Solução mais recente: usar
100dvh
- Em navegadores móveis, quando a barra de endereço/barra de navegação some da tela ao rolar, o valor de
-
Referência para Absolute Position
position: absolutenão se baseia no pai, mas no ancestralrelative/absoluteou stacking context mais próximo
-
Comportamento do blur
backdrop-filter: blurnão leva em conta os elementos ao redor
-
Float sem efeito
- Se o pai for
flexougrid, ofloatdo filho não tem efeito
- Se o pai for
-
width/height em porcentagem
- Não funciona se o tamanho do pai não tiver sido definido previamente (para evitar referência circular)
-
Características de elementos inline
display: inlineignorawidth,height,margin-topemargin-bottom
-
Tratamento de whitespace
- Por padrão, quebras de linha em HTML são tratadas como espaço, e espaços consecutivos são reduzidos a um só
- `` evita a redução de espaços, mas tem um comportamento peculiar no início/fim
- Em geral, espaços no início/fim do conteúdo são ignorados, mas `` é uma exceção
- Espaços/quebras de linha entre
inline-blockaparecem como espaçamento real (isso não ocorre em flex/grid)
-
text-align
- Aplica-se ao alinhamento de texto e elementos inline, mas não ao alinhamento de elementos block
-
box-sizing
- O valor padrão é
content-box→ não inclui padding/border - Com
width: 100%+padding, o elemento pode ultrapassar a área do pai - Solução:
box-sizing: border-box
- O valor padrão é
-
Cumulative Layout Shift
- Se `` não tiver os atributos
widtheheight, o atraso no carregamento da imagem pode causar instabilidade no layout - Recomendação: definir os atributos para evitar CLS
- Se `` não tiver os atributos
-
Requisições de rede de download de arquivos no Chrome
- Não aparecem no painel Network do DevTools (são processadas em outra aba)
- Se precisar analisar, use
chrome://net-export/
-
Problemas de parsing de JavaScript dentro de HTML
- Em casos como
console.log(''), o primeiro `` é interpretado como tag de fechamento - Referência: Safe JSON in script tags
- Em casos como
Unicode e codificação de texto
-
Code points e grapheme clusters
- Grapheme cluster é a “unidade de caractere” na GUI
- Em caracteres ASCII visíveis, 1 code point = 1 grapheme cluster
- Um emoji pode ser um único grapheme cluster composto por vários code points
- Em UTF-8, um code point ocupa de 1 a 4 bytes, e a quantidade de bytes não coincide com a de code points
- Em UTF-16, um code point ocupa 2 ou 4 bytes (par substituto, surrogate pair)
- O padrão não impõe limite ao número de code points dentro de um cluster, mas implementações costumam ter limites por desempenho
-
Diferenças no comportamento de strings por linguagem
- Rust: internamente usa strings UTF-8,
len()retorna número de bytes, indexação direta não é possível,chars().count()retorna o número de code points, valida rigorosamente a validade do UTF-8 - Golang: string é, na prática, um array de bytes; comprimento e indexação são em bytes; UTF-8 é o mais usado
- Java, C#, JS: baseados em UTF-16, medem comprimento em unidades de 2 bytes, e a indexação também é nessa base; há surrogate pairs
- Python:
len()retorna o número de code points, e a indexação retorna uma string contendo um code point - C++:
std::stringnão impõe restrições de codificação, funciona como um vetor de bytes, e comprimento/indexação são em bytes - Entre as linguagens mencionadas, nenhuma mede comprimento/faz indexação por grapheme cluster
- Rust: internamente usa strings UTF-8,
-
BOM (Byte Order Mark)
- Alguns arquivos de texto têm BOM; por exemplo, EF BB BF indica codificação UTF-8
- É usado principalmente no Windows, e softwares fora do ecossistema Windows podem não conseguir lidar com BOM
-
Outros cuidados
- Ao converter dados binários em string, partes inválidas são substituídas por � (U+FFFD)
- Existem confusable characters (caracteres que parecem muito semelhantes entre si)
- Normalização (Normalization): por exemplo,
épode ser representado como U+00E9 (um único code point) ou U+0065+U+0301 (dois code points) - Existem zero-width characters e invisible characters
- Diferença de quebra de linha: no Windows é CRLF
\r\n, no Linux/MacOS é LF\n - Unificação de Han (Han unification): caracteres com formas ligeiramente diferentes em cada idioma usam o mesmo code point
- A fonte renderiza corretamente incluindo variantes por idioma
- Em internacionalização, é necessário selecionar a variante de fonte correta
Ponto flutuante (Floating point)
-
Propriedades de NaN
- NaN não é igual a nenhum valor, incluindo ele mesmo (
NaN == NaNé sempre false) NaN != NaNé sempre true- O resultado de operações que incluem NaN geralmente se propaga como NaN
- NaN não é igual a nenhum valor, incluindo ele mesmo (
-
Valores especiais
- Existem +Inf e -Inf, diferentes de NaN
- -0.0 é um valor distinto de +0.0
- Em operações de comparação eles são iguais, mas em alguns cálculos se comportam de forma diferente
- Exemplo:
1.0 / +0.0 == +Inf,1.0 / -0.0 == -Inf
-
Compatibilidade com JSON
- O padrão JSON não permite NaN nem Inf
- Em JS,
JSON.stringifyconverte NaN e Inf emnull - Em Python,
json.dumps(...)imprime NaN e Infinity como estão (violando o padrão)- Com a opção
allow_nan=False, ocorreValueErrorse houver NaN/Inf
- Com a opção
- Em Golang,
json.Marshalretorna erro se houver NaN/Inf
- Em JS,
- O padrão JSON não permite NaN nem Inf
-
Problemas de precisão
- Comparação direta de ponto flutuante pode falhar → recomenda-se a forma
abs(a - b) < ε - Em JS, todos os números são tratados como ponto flutuante
- O intervalo seguro de inteiros é
-(2^53 - 1)~2^53 - 1 - Fora desse intervalo, a representação de inteiros fica imprecisa
- Para inteiros grandes, recomenda-se usar
BigInt - Se JSON contiver inteiros além do intervalo seguro, o valor resultante de
JSON.parsepode ser impreciso - Timestamps em milissegundos são seguros até o ano 287.396; em nanossegundos já causam problema
- O intervalo seguro de inteiros é
- Comparação direta de ponto flutuante pode falhar → recomenda-se a forma
-
Leis de operação que não se aplicam
- Dependendo da ordem das operações, por perda de precisão, associatividade e distributividade não valem estritamente
- Operações paralelas (multiplicação de matrizes, soma etc.) podem produzir resultados não determinísticos
-
Desempenho
- Divisão é muito mais lenta que multiplicação
- Ao dividir várias vezes pelo mesmo número, é possível otimizar calculando primeiro o recíproco e multiplicando
-
Diferenças conforme o hardware
- Suporte a FMA (Fused Multiply-Add): alguns hardwares fazem cálculos intermediários com maior precisão
- Tratamento de subnormal range: hardwares modernos suportam, mas alguns antigos tratam como 0
- Diferenças de modo de arredondamento
- Existem modos como RNTE (arredondar para o par mais próximo), RTZ (truncar para 0) etc.
- Em x86/ARM, isso pode ser configurado como estado mutável local à thread
- Em GPU, o modo de arredondamento varia por instrução
- Diferenças no comportamento de funções matemáticas como trigonométricas e logaritmos
- x86 tem FPU legada de 80 bits e rounding mode por núcleo → não recomendado usar
- Além disso, vários outros fatores podem fazer o resultado de ponto flutuante variar conforme o hardware
-
Como melhorar a precisão
- Montar um grafo de cálculo mais raso (reduzir cadeias longas de multiplicação)
- Evitar casos em que valores intermediários fiquem muito grandes ou muito pequenos
- Aproveitar operações de hardware como FMA
Tempo (Time)
-
Segundo intercalar (Leap second)
- O timestamp Unix ignora segundos intercalares
- Quando ocorre um segundo intercalar, o tempo pode se alongar ou encurtar na região ao redor (Leap smear)
-
Fuso horário (Time zone)
- UTC e timestamp Unix são comuns no mundo todo
- Horários legíveis por humanos dependem do fuso horário local
- Recomenda-se armazenar timestamps no banco de dados e converter na UI
-
Horário de verão (DST)
- Em algumas regiões, o relógio é ajustado em 1 hora durante o verão
-
Sincronização NTP
- Durante a sincronização, pode acontecer de o tempo “voltar para trás”
-
Configuração de fuso horário do servidor
- Recomenda-se configurar servidores em UTC
- Em sistemas distribuídos, diferenças de fuso entre nós causam problemas
- Após mudar o fuso do sistema, pode ser necessário reconfigurar ou reiniciar o banco de dados
-
Relógio de hardware vs relógio do sistema
- O relógio de hardware não tem conceito de fuso horário
- Linux: trata o relógio de hardware como UTC
- Windows: trata o relógio de hardware como horário local
Java
==compara referências de objetos; para comparar o conteúdo do objeto, é preciso usar.equals- Se
equalsehashcodenão forem sobrescritos, a identidade do objeto em map/set é julgada com base na referência - Se o conteúdo de um objeto usado como chave de map ou elemento de set for alterado, o comportamento do contêiner quebra
- Métodos que retornam
Listpodem, dependendo do caso, retornar umArrayListmutável ouCollections.emptyList()imutável; ao modificar o segundo, ocorreUnsupportedOperationException - Existem métodos que retornam
Optionalmas devolvemnull(não recomendado) - Se houver
returnem um blocofinally, uma exceção ocorrida emtryoucatché ignorada e o valor retornado porfinallyprevalece - Existem bibliotecas que ignoram interrupt, e a inicialização de classes, incluindo IO, pode ser quebrada por interrupt
- Em thread pool, exceções de tasks passadas com
.submit()não são registradas em log por padrão e só podem ser verificadas via future; se o future for ignorado, não há como ver a exceção- Tarefas
scheduleAtFixedRateparam silenciosamente quando ocorre exceção
- Tarefas
- Se um literal numérico começa com 0, ele é tratado como octal (
0123→ 83) - O depurador chama
.toString()de variáveis locais, etoString()em algumas classes tem efeitos colaterais, então o comportamento do código pode mudar durante a depuração (pode ser desativado na IDE)
Golang
append()reutiliza memória quando há folga de capacity; ao fazer append em um subslice, é possível sobrescrever até a memória do paideferé executado quando a função retorna, não quando o escopo do bloco terminadefercaptura variáveis mutáveis- Sobre
nil- nil slice e empty slice são diferentes
- string não pode ser nil, só existe string vazia
- nil map permite leitura, mas não escrita
- comportamento peculiar de nil em interface: se o data pointer é null mas a type info não é null, então não é igual a
nil
- Dead wait: existem casos reais desse tipo de bug de concorrência em Go
- Existem vários tipos de timeout, tratados em detalhe em net/http
C/C++
- Ao armazenar ponteiros para elementos de
std::vector, se o vector crescer pode ocorrer realocação, invalidando os ponteiros - Um
std::stringcriado a partir de uma string literal pode ser um objeto temporário; chamarc_str()nesse caso é arriscado - Modificar um contêiner durante a iteração pode invalidar iterators
std::removenão remove de fato os elementos, apenas os reorganiza; para remover é preciso usarerase- Se um literal numérico começa com 0, ele é tratado como octal (
0123→ 83) - Undefined behavior (UB): durante a otimização, UB pode ser alterado livremente, então depender disso é perigoso
- Acesso a memória não inicializada é UB
- Ao converter
char*para ponteiro de struct, acessar antes do início da vida útil do objeto é UB; recomenda-se inicializar commemcpy - Acesso inválido à memória (como ponteiro nulo) é UB
- Overflow/underflow de inteiro é UB (tipos unsigned podem sofrer underflow abaixo de 0)
- Aliasing: se ponteiros de tipos diferentes referenciam a mesma memória, pode ocorrer UB pela strict aliasing rule
- Exceções: 1) tipos em relação de herança 2) conversão para
char*,unsigned char*,std::byte*(a conversão inversa não se aplica) - Para conversão forçada, recomenda-se
memcpyoustd::bit_cast
- Exceções: 1) tipos em relação de herança 2) conversão para
- Acesso a memória não alinhada é UB
- Alinhamento de memória
- Inteiros de 64 bits devem estar em endereços divisíveis por 8
- Em ARM, acesso não alinhado pode causar crash
- Interpretar diretamente um buffer de bytes como struct pode gerar problemas de alinhamento
- O alinhamento pode criar padding em structs e desperdiçar memória
- Algumas instruções SIMD (como AVX) só conseguem processar dados alinhados, normalmente exigindo alinhamento de 32 bytes
Python
- Argumentos padrão de função não são recriados a cada chamada; o valor inicial fica armazenado
SQL Databases
-
Tratamento de Null
x = nullnão funciona; deve-se usarx is null- Null não é igual a si mesmo (semelhante a NaN)
- Índices unique permitem Null duplicado (exceto no Microsoft SQL Server)
- Em
select distinct, a forma de tratar Null varia conforme o banco count(x)ecount(distinct x)ignoram linhas com valor Null
-
Comportamento geral
- Conversão implícita de datas pode depender de timezone
- Join complexo + distinct pode ser mais lento do que consulta aninhada
- No MySQL(InnoDB), se um campo string não estiver em
utf8mb4, inserir caracteres UTF-8 de 4 bytes causará erro - O MySQL(InnoDB) por padrão não diferencia maiúsculas de minúsculas
- O MySQL(InnoDB) permite conversão implícita:
select '123abc' + 1;→ 124 - Gap lock no MySQL(InnoDB) pode causar deadlock
- No MySQL(InnoDB), quando
group bye as colunas deselectnão batem, o resultado pode ser não determinístico - No SQLite, se não estiver em modo
strict, o tipo do campo tem pouca importância - Foreign key pode gerar locks implícitos e causar deadlock
- O locking pode quebrar o isolamento repeatable read dependendo do banco
- Bancos SQL distribuídos podem não oferecer suporte a locking ou ter comportamentos peculiares (varia conforme o banco)
-
Desempenho/operação
- O problema de N+1 query não aparece no slow query log porque cada query individual é rápida
- Transações de longa duração podem causar problemas de lock etc. → recomenda-se encerrá-las rapidamente
- Casos de lock na tabela inteira
- No MySQL 8.0+, ao adicionar unique index/foreign key, na maioria dos casos o processamento concorrente é possível
- Versões antigas do MySQL podem causar lock da tabela inteira
- Se
mysqldumpnão usar a opção--single-transaction, ocorre read lock na tabela inteira - No PostgreSQL,
create unique indexoualter table ... add foreign keycausam read lock na tabela inteira- Como evitar: usar
create unique index concurrently - Para foreign key, usar
... not valide depoisvalidate constraint
- Como evitar: usar
-
Consultas de intervalo
- Intervalos que não se sobrepõem:
- A condição simples
p >= start and p file 2>&1→ stdout+stderr vão para o arquivo;cmd 2>&1 > file→ só stdout vai para o arquivo, stderr permanece como está
- A condição simples
- Intervalos que não se sobrepõem:
-
Nomes de arquivo diferenciam maiúsculas de minúsculas (diferente do Windows)
-
Arquivos executáveis têm um sistema de capabilities (
getcappara verificar) -
Risco com variável unset: se
DIRestiver unset,rm -rf $DIR/pode virarrm -rf /→ dá para evitar comset -u -
Aplicação do ambiente: para aplicar um script no shell atual, use
source script.sh→ para aplicar permanentemente, adicione em~/.bashrc -
O Bash faz cache de comandos: ao mover arquivos dentro de
$PATH, pode ocorrerENOENT→ atualize o cache comhash -r -
Ao usar variáveis sem aspas, quebras de linha são tratadas como espaços
-
set -e: encerra o script imediatamente em caso de erro, mas não funciona dentro de condicionais (||,&&,if) -
Conflito entre livenessProbe do K8s e debugger: um debugger com breakpoint pode parar o app inteiro e fazer o health check falhar → o Pod pode ser encerrado
React
- Modificar state diretamente no código de renderização
- Usar Hook dentro de if/loop → violação das regras
- Omitir valores necessários no dependency array do
useEffect - Omitir o código de clean up no
useEffect - Armadilha de closure: bugs causados por capturar um state antigo
- Alterar dados no lugar errado → componente impuro
- Deixar de usar
useCallback→ rerenderizações desnecessárias - Passar valores não memoizados para componentes memoizados invalida a otimização de memo
Git
-
Rebase reescreve o histórico
- depois de um rebase, um push normal gera conflito → é necessário fazer force push
- ao mudar o histórico de uma branch remota, também use
pull --rebase --force-with-leasepode, em alguns casos, evitar sobrescrever commits de outros desenvolvedores, mas se você só fizer fetch e não pull, essa proteção não funciona
-
Problema ao reverter merge
- reverter um merge tem efeito incompleto → ao fazer merge da mesma branch novamente, pode não haver mudança alguma
- solução: reverter o revert ou usar um método mais limpo (backup → reset → cherry-pick → force push)
-
Cuidados relacionados ao GitHub
- mesmo que você sobrescreva com force push após commitar um secret como chave de API, o histórico continua no GitHub
- se um repositório privado B for fork de um privado A, e A virar público, o conteúdo de B também fica público (e continua acessível mesmo após a exclusão)
-
git stash pop: se houver conflito, o stash não é removido -
.DS_Storeé criado automaticamente pelo macOS → recomenda-se adicionar**/.DS_Storeao.gitignore
Networking
- Alguns roteadores e firewalls encerram silenciosamente conexões TCP ociosas → isso pode invalidar pools de conexão de clientes HTTP e DB → solução: configurar TCP keepalive
- O resultado do
traceroutetem baixa confiabilidade → em alguns casos,tcptracerouteé mais útil - TCP slow start pode aumentar a latência → pode ser resolvido desativando
tcp_slow_start_after_idle - Problema de sticky packet no TCP: o algoritmo de Nagle atrasa o envio de pacotes → pode ser resolvido ativando
TCP_NODELAY - Ao colocar um backend atrás do Nginx, é necessário configurar a reutilização de conexões → sem isso, em ambientes de alta carga, conexões podem falhar por falta de portas internas
- O Nginx faz buffering de pacotes por padrão → isso pode causar atraso em SSE (EventSource)
- O padrão HTTP não proíbe body em requisições GET e DELETE → alguns usam body, mas muitas bibliotecas e servidores não oferecem suporte
- É possível hospedar vários sites em um único IP → a distinção é feita pelo header HTTP
Hoste pelo SNI do TLS → há sites que não funcionam com acesso direto por IP - CORS: ao fazer requisições para outra origin, o navegador bloqueia o acesso à resposta → o servidor precisa definir o header
Access-Control-Allow-Origin- configurações adicionais são necessárias ao incluir envio de cookies
- se frontend e backend estiverem no mesmo domínio e porta, não há problema de CORS
Other
-
Cuidados com YAML
- YAML é sensível a espaços →
key:valueé erro;key: valueé o correto - o código de país
NO, se usado sem aspas, pode ser interpretado comofalse - um hash de commit do Git sem aspas pode ser convertido em número
- YAML é sensível a espaços →
-
Problemas de CSV no Excel
- ao abrir um CSV, o Excel faz conversões automáticas
- conversão de data:
1/2,1-2→2-Jan - conversão imprecisa de números grandes:
12345678901234567890→12345678901234500000
- conversão de data:
- isso acontece porque o Excel trata números internamente como floating point
- há casos em que isso alterou incorretamente o nome de gene SEPT1
- ao abrir um CSV, o Excel faz conversões automáticas
1 comentários
Comentários no Hacker News
Alguns roteadores e firewalls podem encerrar silenciosamente conexões TCP ociosas sem dar qualquer sinal à aplicação; por isso, códigos que mantêm pools de conexões TCP, como bibliotecas cliente HTTP ou clientes de banco de dados, podem sofrer com conexões invalidadas sem aviso algum. Para resolver isso, é possível configurar o TCP keepalive do sistema ou, no caso de HTTP, usar os cabeçalhos
Connection: keep-alive,Keep-Alive: timeout=30, max=1000. Depois que uma conexão TCP é estabelecida, os roteadores intermediários não mantêm estado; o problema está no timeout de sessão do firewall ou do NAT. Nesses casos, também não chega pacote RST. Em ambiente K8s, já houve caso em que a configuração do módulo conntrack estava baixa demais. Mesmo usando HTTP Keep-Alive, isso só ajuda na reutilização da conexão e não mantém a conexão de rede ativa (link explicativo); HTTP Keep-Alive na prática não gera pacotes, apenas adia o encerramento, enquanto TCP Keep-Alive gera pacotes periodicamente para resetar o temporizadorMétodos que retornam
Optional<T>podem devolvernull, e essa prática é confusa demais. Se eu estivesse com paciência emocional, teria proposto um JEP introduzindo uma anotação como@java.lang.NonNullReference. A ideia seria declarar tipos com essa anotação para que o compilador tratasse atribuições denullcomo erro; por exemplo, em Alpha a atribuição denullseria permitida, mas em Beta geraria erro. Acho que também valeria olhar a especificação para entender como o dead code elimination realmente funciona nojavac; por exemplo, emif (true)a parteb = nullna prática é eliminada, e talvez legalmente esse código ainda seja permitidoEm Kotlin isso já vira erro de compilação, sem precisar de anotação
Fico na dúvida se faz sentido usar
Optional<T>em uma linguagem que já temnull. Se no Python o retorno de função é escrito simplesmente comoT | None, e ainda assim você precisa fazer checagem em vez de receber um objeto Optional, a diferenciação do framework fica meio nebulosa. A menos que se use um estilo monádico específico, no fim a checagem acaba sendo a mesmaFoi dito que Java, C# e JS codificam strings em memória como algo do tipo UTF-16, mas isso está errado no caso de Java; C# e JS talvez também. Em qualquer linguagem, se o tipo string for suficientemente opaco, a forma de representação em memória é detalhe de implementação. Em Java isso ficou claro a partir da versão 9 (JEP relacionado), e esse também é um dos motivos pelos quais, quando há FFI, fica difícil mudar detalhes de implementação. Também foi dito que o max accurate integer de JS é 2^53−1, mas na verdade inteiros bem maiores, como 2^100, também podem ser representados com exatidão. O ponto de 2^53−1 é que
n-1,nen+1são todos representáveis exatamente em IEEE double; portanto, tanton == n-1quanton == n+1resultam em falseEm C#, a representação em memória é bem fixa. Há muitos casos de acesso direto ao buffer usando
ReadOnlySpan<char>ouraw char*, entãocharé um tipo de code point UTF-16. Talvez em JS ainda dê para escapar disso de algum jeitoEu preferiria o termo max safe integer em vez de max accurate integer
(Sobre codificação base64) Quanto à ideia de que strings em memória de Java, C# e JS não são do tipo UTF-16, isso pode até ser tecnicamente correto, mas há casos em que, se uma string codificada em base64 em uma linguagem baseada em UTF-8 for decodificada em Java, surgem problemas por causa da representação UTF-16 do Java
Parece que dicas ou informações em formato de manual só aceleram o entendimento daquilo que a pessoa já sabe ou quase sabia. A maioria dos manuais funciona melhor para organização e revisão do que para o aprendizado em si, e é ineficiente para ensinar quem não sabe absolutamente nada
Li com muito interesse o texto “Traceroute Isn’t Real” e gostei de finalmente entender por que os dados de traceroute tantas vezes parecem imprecisos ou sem sentido (link original). Se alguém tiver informações mais atualizadas, seria ótimo saber
Este texto não é bem uma lista de armadilhas reais, mas sim uma coleção de pequenas dicas que o autor aprendeu na prática. Muita coisa só se aplica em contextos específicos e estreitos, mas o contexto não fica claro, e parte do conteúdo até parece incorreto. Então não é preciso levar o texto todo ao pé da letra; vale mais como fluxo de pensamento ou anotações
Essa história de que valores padrão de argumentos em Python não são recriados a cada chamada, mas sim valores armazenados, é algo essencial de saber ao usar variáveis
datetimeNa primeira “armadilha” da página, foi dito que
min-width: autodefine a largura mínima com base no conteúdo, mas isso não é verdade fora de flex/grid. Segundo o MDN, emblock,inline,tableetc.,autoé ajustado para 0 (documentação oficial)A verdadeira primeira armadilha é que “não dá para ler nenhuma propriedade CSS de forma isolada”. Como o próprio nome cascading sugere, os valores padrão e o resultado de várias regras acabam se combinando em algum ponto, então o contexto do documento inteiro importa
Até dá para entender a cascade dos atributos de texto em CSS, mas layout em CSS é difícil demais de entender, seja do ponto de vista do designer da página, de quem implementa ou de quem usa. É difícil ter empatia com um design assim e pensar para quem ele foi feito
No geral é uma boa lista, embora eu tenha algumas observações.
-0.0e+0.0(zero negativo e zero positivo) são tratados como iguais em comparações de ponto flutuante, mas há formas de distingui-los, por exemplo pelo padrão de bits ou pelos resultados1.0/-0.0 = -infinitoe1.0/0.0 = +infinito(low + high) / 2tem risco de overflow e por isso se deve usarlow + (high - low) / 2, mas selowouhighpuderem ser negativos isso pode apenas deslocar a faixa do overflow. É uma questão importante em buscas binárias em geralrebasepode mudar o histórico, masrebaseé, por definição, um comando que reescreve o históricoEmbora usuários das duas línguas reconheçam conceitualmente o mesmo caractere, não dá para tratar isso como mera “variação de fonte”. O fato de o code point Unicode ser o mesmo não significa que a substituição de caracteres seja segura; para usuários japoneses, esse tipo de troca pode até ser motivo para rejeitar o uso de um produto
De fato, não se distingue A em inglês de A em francês, mas há casos como А (cirílico) e A (latino), que parecem iguais, mas têm code points diferentes. A unificação Han também costuma agrupar em um único ponto caracteres com aparência bem diferente, o que pode confundir estudantes de japonês ou chinês na prática. Por exemplo, o caractere '喝' (drink) pode aparecer de formas bastante diferentes, como mostra este link, e às vezes até parece mudar de forma imediatamente ao copiar e colar, de tão complexo que é o tratamento. Han unification é, na prática, um tema bastante espinhoso
Foi mencionado que há diferenças sutis entre numpy e pytorch, mas sem exemplos concretos isso não é muito útil e fica informação insuficiente para parecer uma armadilha real