4 pontos por GN⁺ 2023-10-07 | 1 comentários | Compartilhar no WhatsApp
  • A keynote da Strange Loop de Julia Evans, Making Hard Things Easy, aborda por que tecnologias que parecem “básicas”, como DNS, Bash, HTTP e SQL, levam muito tempo para aprender, e como reduzir as barreiras de aprendizado
  • A dificuldade do Bash está no grande número de pequenas exceções e armadilhas, como set -e ser desativado em chamadas de função dentro de uma condição com ||, e no fato de muita gente usar Bash só ocasionalmente, o que torna difícil lembrar os detalhes com precisão
  • HTTP e SQL escondem, por trás de uma superfície simples, uma implementação de navegador com cerca de 20 milhões de linhas, muitos headers e flags, e a diferença entre a ordem em que SQL é escrito e a ordem em que é executado, aumentando a carga de aprendizado
  • Em DNS, bibliotecas, caches e a comunicação com nameservers autoritativos não ficam muito visíveis para o usuário, e a saída do dig também é complexa; por isso, ferramentas que revelam comportamentos ocultos e demonstrações são importantes
  • Um bom apoio ao aprendizado envolve compartilhar ferramentas e referências, reduzir listas grandes a listas pequenas usadas na prática, explicar em ordem cronológica o que o computador faz e compartilhar também histórias de falhas e registros de bugs

Por que tecnologias que parecem “básicas” levam tanto tempo

  • A keynote da Strange Loop Making Hard Things Easy trata de como tornar tecnologias difíceis de aprender mais fáceis
  • O ponto de partida foi DNS
    • Encontrar o endereço IP de um nome de domínio parece simples, mas a palestrante diz que, mesmo depois de 7 anos aprendendo DNS, ainda teve problemas ao configurar um site, e que no total levou cerca de 10 anos
    • Amigos dela também passavam repetidamente pelos mesmos problemas, e muitas pessoas continuavam encarando isso como uma falha pessoal, pensando “eu já deveria ter entendido isso”
  • A palestrante criou uma pequena editora chamada Wizard Zines para explicar temas desse tipo de forma simples, usando Bash, HTTP, SQL e DNS como exemplos

Bash: exceções difíceis de lembrar devem ficar a cargo das ferramentas

  • Bash é uma linguagem de programação, mas entre as linguagens que a palestrante usa é uma das que têm mais comportamentos estranhos
  • Em um script de exemplo, mesmo que mv ./*.txt /tmmpp falhe, por padrão o Bash não para e executa echo "success!"
    • Com set -e, é possível fazer o script parar em caso de falha
    • Mas, se a função for chamada dentro de uma condição com ||, como em f || echo "failed!", o set -e é desativado globalmente dentro da função, e success volta a ser impresso
    • Esse comportamento não é um bug do Bash, mas sim um comportamento documentado
  • Um dos motivos pelos quais Bash é difícil é que muita gente só escreve scripts Bash uma vez a cada 6 meses e depois não volta a olhar para eles
    • Quando um sistema usado raramente é cheio de conhecimentos avulsos e armadilhas, fica difícil usá-lo corretamente
  • A reação de que “ninguém consegue usar Bash” não corresponde aos fatos
    • Muita gente usa Bash e, embora não perfeitamente, frequentemente resolve problemas com ele
    • O objetivo é levar uma pessoa diante de uma pilha esmagadora de armadilhas para um estado em que consiga usá-lo “corretamente na maior parte do tempo”
  • ShellCheck é uma ferramenta que lembra, no lugar das pessoas, das armadilhas de Bash difíceis de memorizar e emite avisos
    • shellcheck -o all bad-again.sh informa, com o aviso SC2310, que o set -e de uma função chamada em uma condição com || é desativado
    • Essa verificação só aparece ao executar com -o all
    • Ferramentas assim reduzem a carga cognitiva ao deixar o conhecimento avulso por conta do computador

Histórias de falhas ajudam mais no julgamento do que “best practices”

  • Mesmo sem criar ferramentas diretamente, é importante contar a amigos e colegas sobre ferramentas úteis que você já usa
    • A própria palestrante só descobriu o ShellCheck tarde e disse que ficou irritada ao perceber que não precisava ter guardado tudo na cabeça esse tempo todo
  • Compartilhar armadilhas e histórias de falhas é quase um serviço à comunidade
    • O caso do set -e sendo desativado no Bash foi algo que ela aprendeu com uma experiência contada algumas semanas antes por seu amigo Jesse
    • Ao conhecer a história de falha de outra pessoa, é possível evitar o mesmo problema sem passar por ele diretamente
  • Histórias sobre que tipo de problema Bash causou na prática são mais úteis do que opiniões fortes como “ninguém deveria usar Bash”
    • Ao ouvir a mesma história, uma pessoa pode decidir usar ShellCheck e manter scripts Bash simples
    • Outra pode concluir que não quer usar Bash de jeito nenhum
    • Tudo bem que as reações ao mesmo caso sejam diferentes

HTTP: é preciso entender partindo do pressuposto de um navegador com 20 milhões de linhas

  • Uma resposta HTTP pode parecer ter uma estrutura simples: status code, headers e corpo
  • Mas a pergunta “por que preciso configurar headers?” logo leva ao comportamento do navegador
    • O Firefox é composto por cerca de 20 milhões de linhas de código
    • Navegadores vêm evoluindo desde os anos 1990, e seus modelos de segurança também mudaram continuamente para acompanhar ataques e mudanças na Web
  • Para entender por que um tema é difícil, vale verificar se há uma codebase muito grande por trás dele
    • Isso inclui não só o HTTP em si, mas também CSS, JS etc.; ainda assim, a complexidade dos navegadores modernos ajuda a explicar a barreira de aprendizado de HTTP
  • Listas grandes precisam ser reduzidas a listas pequenas para serem mais fáceis de entender
    • A lista de headers de requisição HTTP tem mais de 43 itens, além de headers não oficiais
    • Na tirinha sobre HTTP request headers, a palestrante aborda os 15 headers que conhece e usa
    • “Os headers mais importantes” não são uma lista objetiva, mas uma lista subjetiva do que a pessoa conhece e usa
    • Por exemplo, normalmente basta saber que definir Accept-Encoding como gzip permite receber respostas compactadas
  • Ferramentas de linha de comando podem ser abordadas da mesma forma
    • A man page do grep tem muitas flags, mas a palestrante diz que, mesmo usando grep há 20 anos, não conhece todas
    • Ajuda um iniciante quando uma pessoa experiente diz: “neste sistema, eu só conheço estas 7 coisas, e são estas aqui”
    • Outra pessoa experiente pode conhecer outras 7 coisas

Referências devem ser compartilhadas com honestidade, como realmente são usadas

  • Informações que não cabem na cabeça das pessoas precisam de boas referências
  • A palestrante conta que, embora tenha aprendido CSS de forma intermitente por 20 anos, só conheceu o CSS-Tricks nos últimos cerca de 2 anos, e que teria sido útil conhecê-lo antes
    • Depois da aquisição, o CSS-Tricks parece ter parado de publicar novos artigos desde abril, mas ela considera que os artigos existentes continuam úteis
  • Em HTTP, ela usa bastante a Mozilla Developer Network
  • Como referências oficiais de HTTP, existem os RFC 9110, 9111, 9112, 9113 e 9114, escritos em 2022
    • Neles é possível consultar detalhes como o funcionamento exato do header Connection
    • A principal referência da palestrante normalmente é a MDN, mas ela valoriza o fato de os RFCs oficiais estarem bem organizados
  • Ao compartilhar referências, é preciso distinguir o que é compartilhado por parecer impressionante daquilo que é usado no trabalho real
    • Mesmo que, na prática, você use uma referência “menos sofisticada” como w3schools, é importante ser honesto sobre seu uso real

SQL: dizer em ordem cronológica o que o computador faz

  • SQL pode confundir iniciantes porque a ordem em que a query é escrita é diferente da ordem conceitual em que ela é executada de fato
  • O modelo mental de SQL usado pela palestrante segue esta ordem
    • FROM
    • WHERE
    • GROUP BY
    • HAVING
    • SELECT
    • ORDER BY
    • LIMIT
  • Bancos de dados reais têm otimizações, então são mais complexos, mas esse modelo cronológico é útil na maioria das situações
    • Ele é quase igual à ordem em que a query aparece escrita, exceto pelo fato de SELECT ser o quinto passo
  • A abordagem de perguntar “o que o computador realmente faz primeiro?” também pode ser usada em outros temas
    • Em CORS, é possível entender listando em ordem cronológica toda a comunicação entre o navegador e o servidor
    • A palestrante cita a tirinha sobre CORS como exemplo desse método
  • Explicações em ordem cronológica parecem simples, mas na prática são difíceis, e por isso são úteis para colaboração
    • Behind Hello World on Linux trata do que acontece ao executar “hello world” no Linux
    • A palestrante também escreveu um texto parecido há 10 anos, mas o texto de 2023 ficou cerca de 6 vezes mais longo
    • Ela entende que não foi o Linux que ficou mais complexo; em 2013, ela simplesmente sabia menos sobre o que acontecia em ordem cronológica
  • Em equipes, criar em conjunto uma timeline em ordem cronológica do que acontece quando uma requisição chega a um endpoint de API ajuda a conectar o que cada pessoa sabe

DNS: é preciso revelar sistemas ocultos para criar intuição

  • DNS é uma estrutura em que navegador, funções de biblioteca que enviam requisições DNS, caches e nameservers autoritativos trabalham juntos
  • O problema é que grande parte disso fica oculta para o usuário
    • Não é fácil descobrir qual código de biblioteca envia uma requisição DNS
    • É difícil inspecionar os dados armazenados dentro dos caches, e o usuário não consegue controlá-los
    • A comunicação entre caches e nameservers autoritativos também não é visível
  • A palestrante criou, junto com sua amiga Marie, um pequeno servidor DNS chamado Mess With DNS
    • Usuários podem criar registros DNS em um domínio
    • Sempre que uma requisição chega de um resolver, ele mostra qual mensagem foi recebida
    • Na demo da Strange Loop, ela criou um registro CNAME com o nome strangeloop apontando para orange.jvns.ca, e confirmou que o resolver DNS canadense usado pelo navegador solicitava registros A e AAAA
  • Outro exemplo de revelar algo oculto é float.exposed
    • Ele permite alterar o significand e o exponent em um número de ponto flutuante de 32 bits e ver o próximo número de ponto flutuante e a mudança no intervalo
  • Outro motivo pelo qual DNS é difícil é que se trata de um enorme sistema distribuído
    • A palestrante diz algo como “mais de 5 milhões de computadores podem estar envolvidos”, sendo que a maior parte deles não está sob controle do usuário, e alguns podem se comportar de forma diferente do esperado

Quando ferramentas viram barreiras de aprendizado, como a saída do dig

  • A saída de ferramentas de DNS também pode aumentar a confusão
  • O dig tem a flag +norecurse
    • Ela permite pedir ao resolver que retorne apenas resultados que já estejam em cache
    • dig +norecurse jvns.ca pode ser usado, por exemplo, para verificar se aquele resolver colocou esse domínio em cache nos últimos 5 minutos
  • A saída do dig pode dar a iniciantes a impressão de que o próprio DNS é ainda mais complexo
    • A palestrante considera que isso é mais próximo do resultado de um formato de saída relativamente arbitrário definido nos anos 1990 e mantido por muito tempo
  • “Eraser eyes” é uma forma de, em uma saída complexa, manter apenas a parte que você realmente olha e ignorar o resto como se apagasse
    • No exemplo, o foco é apenas no código de resposta SERVFAIL
    • Pelo entendimento da palestrante, neste contexto SERVFAIL é algo próximo de “não está no cache”
  • Ao demonstrar uma ferramenta, ajuda no aprendizado explicar que saída ou UI você está olhando e quais partes está ignorando
    • A saída do dig é bruta, mas a ferramenta tem muitas funcionalidades, oferece suporte a +norecurse, está disponível em todo lugar e tem a estabilidade de ter mudado pouco ao longo do tempo

Papéis para tornar as coisas mais fáceis em conjunto

  • A prática de tornar tecnologias mais fáceis pode ser compartilhada com pessoas ao redor mesmo sem ter um blog
  • Os métodos organizados pela palestrante são estes
    • Compartilhar ferramentas úteis
    • Compartilhar referências usadas na prática
    • Dizer em ordem cronológica o que acontece no computador
    • Reduzir listas grandes a listas pequenas que você realmente usa
    • Mostrar comportamentos ocultos
    • Demonstrar ferramentas confusas e explicar quais partes observar
  • Há também vários tipos de pessoas que ajudam
    • O “usuário antigo reclamão” conta o que deu errado no passado e reduz sofrimento
    • O “iniciante barulhento” pergunta “como isso funciona?” e faz outras pessoas também se sentirem aliviadas
    • Quando uma pessoa desenvolvedora sênior faz publicamente uma pergunta sobre algo que não sabe, quem tem medo de ser julgado por não saber também consegue aprender junto
    • O “registrador de bugs” documenta o que aconteceu para que o mesmo bug não volte a ocorrer
    • O “criador de ferramentas” escreve código, em vez de repetir explicações, e torna o problema permanentemente mais fácil
    • O “compartilhador do que aprendeu hoje” divide uma nova ferramenta, um bug encontrado ou um recurso recém-descoberto de uma biblioteca
    • A “pessoa com 700 abas abertas” provavelmente já sabe onde encontrar informações
    • Também são necessárias a “pessoa que responde perguntas” e a “pessoa que anota para ser possível encontrar depois”
  • Ter dificuldade com algo que parece básico não é apenas um problema individual
    • Muitas pessoas têm dificuldade nos mesmos pontos, pelos mesmos motivos
    • Ao identificar a causa da dificuldade, é possível corrigi-la melhor, como se corrige um bug em um programa de computador
  • Fatores que criam dificuldade incluem uma enorme quantidade de conhecimentos avulsos e armadilhas, código na escala de 20 milhões de linhas, sistemas ocultos e saídas confusas de ferramentas que não foram melhoradas
  • A palestrante ainda não entende bem por que Git é difícil, mas deixa isso como um tema sobre o qual quer continuar pensando e tentando entender

1 comentários

 
GN⁺ 2023-10-07
Opiniões do Hacker News
  • A parte que mais me marcou foi mostre o que normalmente fica oculto.
    Ferramentas assim tornam a situação mais clara quase imediatamente. Pense nas ferramentas de desenvolvedor dos navegadores web: na “era das trevas”, antes delas, era horrível ter que adivinhar o que estava acontecendo sem conseguir ver
    Uma ferramenta como o Wireshark, que mostra os bytes de pacotes de rede acessíveis e até analisa sua estrutura, é muito útil não só para depuração de rede, mas também para ensinar conceitos de rede, porque não esconde nada
    Também é por isso que gosto de software open source. Como posso olhar o código-fonte para entender a causa de um bug, preencher lacunas de conhecimento deixadas pela documentação ou aprender mais conceitos de programação, nada fica escondido

    • No desenvolvimento de jogos, a ferramenta equivalente a isso é o renderDoc. Fiquei realmente impressionado quando descobri que ela existia
    • O Wireshark é excelente, mas não mostra todos os bytes transportados pela rede
      Por exemplo, ele nunca mostra o preâmbulo Ethernet, só às vezes mostra o checksum do quadro Ethernet, e nunca mostra o intervalo entre quadros, que é um elemento essencial do protocolo Ethernet
      Chega bem perto, mas mostra que sempre há mais detalhes escondidos em algum lugar
    • Meu sonho é tornar tudo visualizável em tempo de execução. Se conseguíssemos fazer isso, acho que toda a computação se tornaria muito simples e bem menos complexa
      Já visualizamos isso na cabeça, e qualquer explicação de computação acaba virando um diagrama. Mas, quando estamos programando, não há diagrama nenhum
      Bastaria instrumentar todo o código dinamicamente e enviar mensagens para uma GUI
    • Ao contrário de frases como “mostre o que normalmente fica oculto” e “ferramentas assim tornam a situação clara quase imediatamente”, as ferramentas de DevOps de hoje parecem estar escondendo cada vez mais coisas
      E os especialistas que tinham esse conhecimento e poderiam ensiná-lo agora estão concentrados nessas empresas de ferramentas, não dentro das organizações
    • É exatamente disso que eu gosto no Magit para Emacs. A UI é realmente inteligente e fluida, talvez a melhor interface Git que já usei, mas a forma de interagir com ela consiste em alternar flags e opções que são mapeadas para os argumentos reais da linha de comando do Git por baixo
      Então, quando você passa naturalmente para a linha de comando, já está familiarizado e consegue usá-la diretamente
  • Julia parece ser uma das pessoas mais simpáticas da indústria de tecnologia
    Toda vez que leio seus textos, volta aquela empolgação de quando, na infância, eu começava a desvendar os segredos da realidade com pequenos experimentos. É realmente encantador

    • É raro alguém ter, ao mesmo tempo, conhecimento técnico profundo e excelente capacidade de ensino e comunicação. Outra pessoa que me vem à cabeça é Andrej Karpathy
      Felizmente, recentemente tenho encontrado mais pessoas que se encaixam nesse perfil
    • Por um instante achei que fosse sobre a linguagem Julia :)
    • Concordo muito. Em geral não gosto muito de posts de blog ou tutoriais exageradamente empolgados no estilo “omg awesomesauce”, e prefiro muito mais textos secos, concisos, bonitos e com alta relação sinal-ruído, no estilo Landau&Lifschitz
      Mas todos os textos da Julia me fazem sentir aquela empolgação mencionada acima
    • Ela também foi realmente encantadora pessoalmente. Peguei um autógrafo no meu livro How DNS Works
  • Acho que a frase “quando um iniciante diz ‘isso é difícil’, alguém experiente responde ‘sim, bash é inutilizável; ninguém conhece direito’” não deve ser interpretada literalmente
    O sentido está mais próximo de “não temos uma compreensão forte do código bash que escrevemos, nem confiança de que ele vá se comportar como esperado em situações não testadas”
    Quer dizer que, se acontecer qualquer coisa minimamente fora do comum, você já espera, em certa medida, que algo falhe e que algum fato recém-aprendido sobre bash faça você se arrepiar ou bater com força suficiente em algum objeto próximo a ponto de machucá-lo
    Bash é uma linguagem complexa e, para a maioria dos programadores, é completamente diferente das outras linguagens que usam no dia a dia. A maioria das empresas tem algum bash em produção em algum lugar, mas muitas vezes não há uma única pessoa que o tenha usado o bastante para conhecê-lo bem
    Não acho coincidência que ferramentas de build, ferramentas de CI e ferramentas de orquestração em nuvem estejam evoluindo no sentido de reduzir a necessidade de scripting em shell

    • Acho que a complexidade de ferramentas como bash vem da falta de evolução
      Como experimento mental: não seria possível adicionar ao bash uma forma melhor de atribuição? Por exemplo, se em um modo como set --goodass fosse possível escrever a = string1 + '.' + string2, daria para eliminar boa parte do tratamento de aspas do shell
      Ferramentas como make também se beneficiariam. Passar 6 meses tornando o make capaz de ter variáveis utilizáveis, formas claras de manipular caminhos e nomes de arquivos e targets mais úteis poderia ser melhor do que passar 6 meses criando um Makefile complexo
    • O problema é se o iniciante vai entender esse significado implícito ou se vai interpretar de forma mais literal do que a intenção
      Em especial, a percepção de que “para a maioria dos programadores, bash é diferente de qualquer linguagem que usam no dia a dia” não é algo que um iniciante necessariamente consiga inferir. É preciso experiência suficiente para saber a diferença entre “incomum” e “extremamente obscuro”
  • Relacionado a isso, a maior parte do software é superprojetada
    Acho que isso também se deve à centralização da indústria. Todos são empurrados para um pequeno conjunto de ferramentas, em benefício dos poucos que as controlam, e como resultado muitas ferramentas acabam virando “ferramentas para tudo”, cobrindo muito mais do que os casos de uso que precisariam atender
    As empresas querem que todos os desenvolvedores conheçam as mesmas ferramentas. Assim, eles se tornam facilmente substituíveis entre projetos e empresas, e seu poder de negociação na indústria diminui
    Por isso, sobra apenas um tronco principal no software, enquanto abordagens alternativas são rejeitadas e ficam sem empregos. A indústria naturalmente tenderia a se descentralizar, mas não consegue
    Vendo pelo lado positivo, um dia abordagens não convencionais muito superiores vão surgir e corroer as abordagens dominantes. Tecnologia não é matemática, nem é igual à ciência, e consegue sustentar muitos ramos diferentes para resolver o mesmo problema de várias maneiras

    • Concordo. Em certo sentido, o desenvolvimento web parece até ter regredido em relação à época do ASP.NET inicial ou do Rails
      Naquele tempo, as guerras dos navegadores nos mantinham ocupados; hoje, embora os navegadores sejam em geral compatíveis, criamos um monte de complexidade de frontend para web apps que, na maioria das vezes, é desnecessária
      Coisas como DNS, IP e HTTPS são tecnologias fundamentais envolvidas com compatibilidade retroativa e fatores políticos, então não há muito como evitar
      Ainda assim, sinto que aprender bem essas coisas é um investimento melhor do que aprender frameworks. Se eu continuar, vou acabar entrando na história dos tokens de inovação
  • Para tornar algo difícil mais fácil, é preciso encontrar a abstração adequada. Você mantém na cabeça apenas uma parte do conteúdo difícil e os detalhes usados com frequência, e consulta o restante quando necessário.
    O problema é que as pessoas não se dão ao trabalho de criar uma compressão cognitiva sobre um grande tema até que realmente precisem dela. Como já carregam outra grande carga cognitiva, resistem a acrescentar uma nova.
    Se você pode depender de outra pessoa que conhece bem algum tema X, simplesmente faz isso e pode não se esforçar para saber o bastante sobre X. A melhor forma de alguém que conhece bem X reduzir pedidos de ajuda é ajudar outras pessoas a entender o mínimo de X.
    set -e é quebrado, a necessidade de colocar tudo entre aspas também é quebrada, e globbing deveria ser um recurso solicitado explicitamente. Na linha de comando isso seria incômodo, mas em scripts a história é outra; hoje, se você desativa globbing globalmente, fica difícil fazer globbing onde deseja.
    Esses padrões ruins não existem só no Bash, mas em shells em geral da linhagem do Ksh e do Bourne shell.
    Muita gente também quer mudar a ordem das cláusulas em SQL. Não há motivo para isso não poder ser feito, e parece ser uma mudança relativamente pequena permitir que parsers SQL existentes aceitem cláusulas em outra ordem.
    Pessoalmente, porém, não tenho esse problema cognitivo, talvez porque eu saiba que devo olhar primeiro para a origem das tabelas.

    • As três armadilhas — set -e ser quebrado, a necessidade de colocar tudo entre aspas e globbing precisar ser explícito — são corrigidas pelo OSH, mesmo executando scripts shell existentes.
      Se você adicionar shopt --set ysh:upgrade no topo do script, esses três problemas desaparecem.
      Se quiser ajudar o projeto, seria bom baixar o tarball, verificar essa afirmação e escrever um post no blog.
      Mais detalhes estão em https://www.oilshell.org/release/latest/doc/error-handling.h... e https://www.oilshell.org/release/latest/doc/simple-word-eval....
      A documentação é abrangente, mas a maioria das pessoas não quer esse nível de detalhe, então ajudaria se alguém testasse e escrevesse um resumo curto.
      O motivo de eu não ter promovido ativamente o Oils por um tempo foi sua dependência de Python, mas agora ele é C++ puro e, nesta semana, já está superando o bash em alguns benchmarks centrados em computação.
      Scripts centrados em entrada e saída sempre tiveram a mesma velocidade, como acontece com a maioria dos scripts shell. Ainda é preciso trocar Oil por YSH na documentação, então pode haver alguma confusão por um tempo: https://www.oilshell.org/blog/2023/03/rename.html
    • O problema é continuar usando esses shells antigos mesmo existindo shells melhores. Usuários não deveriam perder tempo decorando conhecimento arcano como set -e. Ainda assim, agora existem mecanismos de busca.
    • Uma forma um tanto radical de corrigir a ordem das cláusulas SQL poderia ser introduzir project, que se comportaria como select, mas poderia ser colocado na posição correta.
    • Quando uma explicação inclui detalhes desnecessários, ela fica muito confusa. Como a arma de Tchekhov, a gente continua tentando encaixá-los na trama, mas eles não se encaixam.
      Meu superpoder é ter uma memória péssima. Por isso, para memorizar algo, eu necessariamente preciso entendê-lo, ou seja, preciso de compressão cognitiva. Não consigo simplesmente aprender como uma pessoa normal.
    • É preciso conseguir descascar o SQL e acessar a camada inferior
  • Aprendizado de hoje: em uma lista com && ou ||, exceto pelo comando depois do último && ou || entre os comandos executados, o shell não encerra mesmo que algum comando falhe
    Referência: https://www.gnu.org/software/bash/manual/bash.html#index-set

    • “Falha” é um conceito de nível mais alto do que aquilo com que o shell se preocupa. As condições de falha e as reações ficam inteiramente a critério do programador, e não estão embutidas como pressupostos no shell
      Tudo o que /bin/false faz é retornar 1. Isso é uma falha? Não. Ele foi projetado para se comportar assim e é literalmente uma ferramenta com esse propósito
      Já escrevi centenas de scripts de shell, e muitos comandos neles retornam valores diferentes de 0 de forma perfeitamente normal para fazer seu trabalho, como verificar se uma string tem determinado padrão
      Um programa pode retornar qualquer código de saída que quiser em qualquer situação e, por convenção, sucesso é 0 e falha é um valor diferente de 0. Mas a única coisa com que a linguagem do shell se importa é que 0 é avaliado como “verdadeiro” e valores diferentes de 0 como “falso”
      Se o shell encerrasse toda vez que qualquer programa retornasse um valor diferente de 0, instruções if e loops se tornariam impossíveis, o que seria muito inconveniente
      Se um script considera importante o código de retorno de um programa específico, ele deve verificá-lo e tratá-lo explicitamente. Como no link, existem opções que fazem o shell encerrar quando um comando interno retorna valor diferente de 0, e muitos autores iniciantes/intermediários de scripts de shell defendem dogmaticamente que elas deveriam ser usadas em todos os scripts
      Mas, em scripts complexos, sinto que há muitos casos de borda meio hacky e difíceis de lidar. Se você precisa dessas opções o tempo todo, talvez seja melhor usar um Makefile
    • Isso acontece porque && e || são frequentemente usados como condicionais
      [ -e README ] && cat README evita um erro quando o arquivo README não existe, e [ -e README ] || echo "You should write a README!" faz o oposto
      Um problema mais sutil é que, mesmo assumindo set -e, em um pipeline o shell não encerra se o último comando não falhar
      grep foo README | sort não falha mesmo que o README não exista, a menos que você também use set -o pipefail
    • Vejo isso como uma das maiores falhas de design da linguagem de shell. Porque uma função pode levar a resultados diferentes dependendo do contexto em que é chamada, independentemente de seus argumentos
      Mesmo definir explicitamente set -e dentro da função é sobrescrito por isso
      Já dei um exemplo antes: https://news.ycombinator.com/item?id=22213830
    • Há muito conhecimento obscuro sobre shell a aprender. Em algum momento, é preciso dar de ombros e aceitar que ele é uma ferramenta aceitável para obter resultados rápidos, mas inadequada para escrever programas robustos
  • É um texto que descreve bem coisas que parecem não dever ser difíceis, mas que na prática têm muita complexidade
    Porém, a parte sobre SQL parece reforçar mais uma falha conceitual do que desmistificar o assunto
    A lógica de uma consulta é declarativa e define a saída. O que tem ordem de execução ou caráter procedural é o plano de consulta. É isso que deve ser aprendido primeiro
    Depois, dá para aprender áreas ambíguas como subconsultas dependentes. Se você consegue ver que not exists e anti join são equivalentes, consegue entender e raciocinar sobre isso
    A analogia de tentar entender uma consulta escrita de forma procedural só empurra o problema para depois, e quando você travar em algo mais complexo não terá como desfazer essa mentira bem-intencionada

    • A parte sobre SQL falava de um modelo mental para ajudar a entender consultas, e também mencionava que provavelmente o banco de dados real não as processa dessa forma
    • Um episódio recente relacionado a Postgres, mas que em muitos casos pode ser estendido a outros bancos de dados: https://www.se-radio.net/2023/09/se-radio-583-lukas-fittl-on...
  • Foi uma ótima apresentação. É verdade que o Bash está cheio de “armadilhas” e conhecimentos soltos, e que é difícil decorar tudo, mas acho que vale a pena memorizar algumas dessas informações
    Por exemplo, eu costumava esquecer com frequência a ordem dos argumentos do comando find e perdia tempo tentando lembrar a sintaxe diante de uma máquina sem conexão imediata com a internet
    Então decidi aprender e memorizar as ferramentas de linha de comando mais comuns e algumas de suas armadilhas, usando Anki e alguns mnemônicos. Acho que o retorno sobre o investimento valeu bastante a pena

    • O Anki é minha tábua de salvação para entender coisas difíceis como DNS
      De fato, depois de ver uma recomendação de livro em jvns.ca, li Networking for System Administrators, de Michael W. Lucas, e extraí conhecimento técnico e uma boa dose de sabedoria de administração de sistemas para cartões do Anki
      Hoje, ao depurar problemas na camada de transporte, lembro imediatamente como usar ferramentas como netcat e tcpdump, então talvez seja um dos livros com maior retorno sobre investimento entre os que já li
    • Mantenho um arquivo com comandos que não uso com frequência. Por exemplo, comandos para aumentar o volume com ffmpeg ou adicionar uma borda a uma imagem com convert
      Também criei um atalho para adicionar a esse arquivo o último comando executado e outro para pesquisar nesse arquivo
    • As páginas man estão prontamente disponíveis
      A página man do bash é enorme e complexa, mas abrangente. Se você estiver familiarizado com as principais seções e com a forma visual do texto, pode folheá-la rapidamente e encontrar a informação exata de que precisa, o que foi bastante útil
      Muitas vezes esse método é mais rápido do que usar um mecanismo de busca na internet
    • Para não depender da internet e, ao mesmo tempo, não precisar memorizar designs ruins, talvez seja melhor investir em documentação e cheat sheets mais gerais
      Por exemplo, converter páginas man antigas para um formato mais amigável a editores de texto, ou usar ferramentas melhores como tldr e Dash. Afinal, não é só o find que tem esse problema
    • Deveríamos parar de usar Bash e usar TypeScript em vez disso. Bash é horrível
  • Não sei por quê, mas eu queria não gostar deste texto. Talvez porque a jvns apareça com frequência demais no HN, ou talvez eu estivesse de mau humor
    Mas é um texto realmente bom e, como alguém com 20 anos de experiência em desenvolvimento, acho que ele chega bem perto da verdade entre as discussões em metanível sobre programação
    A parte sobre visão seletiva se aplica muito bem tanto ao dig quanto às páginas man. Já perdi a conta de quantas vezes abri o man e fiquei sobrecarregado com opções de configuração e flags de linha de comando intermináveis
    Uma dica que uso no man é usar o recurso de busca no estilo Vim, com /. Por exemplo, se quero descobrir como fazer o grep imprimir o número da linha de cada ocorrência e não lembro, abro man grep, digito /line e pressiono Enter para procurar ocorrências de “line” dentro da página man. A próxima ocorrência é só /
    Também fico um pouco triste com a notícia de que a Strange Loop acabou. Só fiquei sabendo dela por volta do ano passado, e muitas palestras pareciam ter uma qualidade excepcionalmente alta

  • Discordo fortemente da perspectiva sobre bash. A melhor solução não é colocar ferramentas por cima do bash nem decorar suas peculiaridades, mas não usar bash
    Esse é o único jeito de evitar as armadilhas

    • Ainda não encontrei um substituto adequado para bash, especialmente em scripts
      As alternativas mais comuns são 1) usar um shell novo, como o Oil shell [0], ou 2) usar uma linguagem de programação como Python, JavaScript ou PHP
      O problema dos shells novos é que você precisa instalá-los em todos os lugares onde quer usar scripts. Já o bash está em todo lugar. Se não for um script mantido só por você, isso também exige que outras pessoas aprendam esse shell para conseguir mantê-lo
      O problema de outras linguagens de programação é que o bash tem uma usabilidade rara para aquilo em que é bom: encadear comandos e lidar com entrada/saída de comandos e arquivos
      Quando você tenta fazer isso em outra linguagem, de repente fica muito mais complexo, ou pelo menos mais verboso
      Por isso ainda uso bash, mas reconheço que sua força está em executar outros comandos e lidar com I/O. Se for uma lógica complexa sem relação com isso, passo para outra linguagem. Às vezes não é evitar bash por completo, mas chamar um script Python a partir do bash
      Se outra abordagem funcionou melhor para você, seria bom compartilhar
      [0] https://www.oilshell.org
    • É um ponto válido. Bash é uma ferramenta complexa demais, então é estranho escrever outra ferramenta por cima dele para tornar o bash menos complexo
      Ainda mais porque essa nova ferramenta não terá passado por décadas de depuração como o próprio bash. O problema está no próprio bash
      Tendemos a subestimar a facilidade de uso e superestimar a “inteligência”
      O exemplo clássico é o Git. É uma ferramenta muito inteligente, mas sua facilidade de uso é péssima. Ainda assim, foi feita pelo Linus, e o Linus é inteligente, então parece que o problema somos nós
      Recebemos aquilo que valorizamos. Deveríamos valorizar mais a facilidade de uso
    • Sou grande fã do shellcheck e já usei bash a fundo de verdade, mas nenhum linter nem ferramenta por cima do bash consegue consertar isso
      A melhor solução é simplesmente ficar longe. Sério, precisamos parar. Não devemos tentar posar de durões
      O modelo inteiro da linguagem é fundamentalmente quebrado. Tipos centrados em strings, chaves globais de modo, flags de uma letra em operadores básicos de comparação, comportamento padrão de ignorar erros por toda parte, e especialmente funções
      Qualquer uma dessas peculiaridades sozinha já seria suficiente para excluir uma linguagem; no bash há todas elas e ainda mais
    • O bash é peculiar porque não é uma linguagem de propósito geral. As coisas mencionadas no texto também têm suas boas razões. Por exemplo, o fato de set -x poder quebrar o comportamento esperado de || e &&
      Para começo de conversa, que linguagem entra em conflito porque uma função retorna false? Existem linguagens que lançam exceções, mas “false” não é um valor válido que pode ser retornado?
      Vemos a mesma coisa em Makefiles. As pessoas não entendem o que estão fazendo e nunca pensaram a fundo em sistemas de build, então esperam que funcionem de determinada maneira
      Por exemplo, a atribuição recursiva do Make derruba quase todo mundo
      FLAGS=-b, COMPILE=compile $(FLAGS), $(info compile command=$(COMPILE)), FLAGS=-a, myfile:, echo $(COMPILE) $? -o $@ imprime compile -b na primeira mensagem de informação, mas a execução real vira compile -a -o myfile
      Mas, se você transformasse todas as atribuições em avaliação imediata para alinhá-las com outras linguagens de programação, tiraria uma ferramenta muito útil. Quanto mais você entende essas ferramentas, melhor sabe onde usá-las e quanto esforço dedicar
    • Não é tão fácil quanto parece, e eliminar completamente o bash talvez nem sempre valha o tempo e o esforço
      Ainda assim, concordo em geral. Tento passar qualquer coisa minimamente complexa para scripts escritos em uma linguagem menos peculiar
      Nesses casos, ferramentas que ajudam a evitar erros nos últimos 5% que ainda ficam em bash são muito úteis