Práticas de engenharia

Para scripts shell

  1. Use bash. Usar zsh, fish ou qualquer outro dificulta o entendimento e a colaboração para outras pessoas. Entre todos os shells, o bash tem um bom equilíbrio entre portabilidade e DX.
  2. Basta deixar a primeira linha como #!/usr/bin/env bash, mesmo que você não dê permissão de execução ao arquivo do script.
  3. Use a extensão .sh (ou .bash) no seu arquivo. Pode parecer elegante não ter extensão no script, mas, a menos que seu caso dependa explicitamente disso, provavelmente você só está tentando ser esperto demais. Coisas espertas demais são difíceis de entender.
  4. Use set -o errexit no início do script. Assim, quando um comando falhar, o bash encerra em vez de continuar com o restante do script.
  5. Prefira usar set -o nounset. Você pode ter uma boa razão para não fazer isso, mas, na minha opinião, é melhor sempre defini-lo.
    • Isso fará o script falhar ao acessar uma variável não definida. Evita consequências horríveis e não intencionais causadas por erros de digitação em nomes de variáveis.
    • Quando quiser acessar uma variável que pode ou não ter sido definida, use "${VARNAME-}" em vez de "$VARNAME", e está resolvido.
  6. Use set -o pipefail. Novamente, você pode ter boas razões para não fazer isso, mas eu recomendaria sempre defini-lo. Isso garante que um comando de pipeline seja tratado como falho, mesmo que apenas um dos comandos do pipeline falhe.
  7. Use set -o xtrace, com uma verificação da variável de ambiente $TRACE.
    • Para copiar e colar: if [[ "${TRACE-0}" == "1" ]]; then set -o xtrace; fi.
    • Isso ajuda muito na depuração dos seus scripts. Muito mesmo.
    • Agora as pessoas podem ativar o modo debug executando seu script como TRACE=1 ./script.sh em vez de ./script.sh.
  8. Use IFS=$'\n\t'. A variável IFS, que significa Internal Field Separator (separador de campo interno), controla o que o Bash chama de word splitting (divisão de palavras). Quando definida como uma string, cada caractere dela é considerado pelo Bash como um separador de palavras. Isso controla como o bash percorre uma sequência.
  9. Use [[ ]] para condições em instruções if / while, em vez de [ ] ou test.
    • [[ ]] é uma palavra-chave do bash e é mais poderosa que [ ] ou test.
  10. Sempre coloque os acessos a variáveis entre aspas duplas.
    • Um lugar onde não é obrigatório é no lado esquerdo de uma condição [[ ]]. Mas mesmo ali eu recomendaria usar aspas.
    • Quando você precisar do comportamento sem aspas, usar arrays do bash provavelmente atenderá muito melhor.
  11. Use variáveis local dentro de funções.
  12. Aceite várias formas de os usuários pedirem ajuda e responda de acordo.
    • Verifique se o primeiro argumento é -h, --help, help, apenas h ou até -help e, em todos esses casos, exiba o texto de ajuda e encerre.
    • Por favor. Pelo bem do seu eu do futuro.
  13. Ao exibir mensagens de erro, redirecione para o stderr. Use echo 'Something unexpected happened' >&2 para isso.
  14. Use opções longas sempre que possível (como --silent em vez de -s). Elas servem para documentar seus comandos de forma explícita. Note, porém, que comandos que vêm com alguns sistemas, como o macOS, nem sempre têm opções longas.
  15. Se fizer sentido, mude para o diretório do script logo no início dele.
    • E quase sempre faz sentido.
    • Use cd "$(dirname "$0")", que funciona na maioria dos casos.
  16. Use o shellcheck. Preste atenção aos avisos dele.
#!/usr/bin/env bash

set -euo pipefail
IFS=$'\n\t'

if [[ "${TRACE-0}" == "1" ]]; then
    set -o xtrace
fi

if [[ "${1-}" =~ ^-*h(elp)?$ ]]; then
    echo 'Usage: ./script.sh arg-one arg-two

This is an awesome bash script to make your life better.

'
    exit
fi

cd "$(dirname "$0")"

main() {
    echo do awesome stuff
}

main "$@"

referência: Shell Script Best Practices e Use Bash Strict Mode (Unless You Love Debugging)

Para conventional commits

Uma convenção para mensagens de commit, compatível com o semver.

Por que usar conventional commits?

  • Comunica e documenta as mudanças melhor (mais fácil de ler e rastrear).
  • Um histórico de commits mais estruturado, facilitando a contribuição de outras pessoas.
  • Direciona a fazer commits por escopo (um commit para um problema específico)
  • Ajuda a gerar changelog automático ao usar o standard-version.
<type>[optional scope]: <description>

# exemplo
feat(pages): add home page

type

feat

adds a new feature which brings changes

fix

bug fix

Se você usa o vscode, pode usar esta extensão para ajudar a compor mensagens de conventional commits.

Leia mais:

Para conventional comments

Code reviews podem ser melhores quando entendemos que o código que estamos revisando foi escrito por uma pessoa, e que nossa revisão também será lida por uma pessoa. Às vezes não percebemos quando nossos comentários não são úteis. Isso pode ser melhorado seguindo os conventional comments, uma convenção inspirada nos conventional commits e nas práticas de engenharia do Google.

exemplo de comentário pouco útil:

Isso não está redigido corretamente

usando um prefixo de rótulo:

suggestion: Isso não está redigido corretamente

que tal usar other_word em vez disso?

Soa melhor, não é? Reduz a subcomunicação e os mal-entendidos.

<label> [decorations]: <subject>

[discussion]

Leia mais: conventional comments