Ferramentas do usuário

Ferramentas do site


boas_praticas_de_programacao_shell_script

Diferenças

Aqui você vê as diferenças entre duas revisões dessa página.

Link para esta página de comparações

Próxima revisão
Revisão anterior
boas_praticas_de_programacao_shell_script [2018/08/17 09:55] – Criou página com 'Esse é um guia pessoal de referência. Anoto aqui dicas que considero úteis, de modo que possa acessá-las de qualquer lugar, aproveitando para compartilhar com quem possa t...' cartolaboas_praticas_de_programacao_shell_script [2022/03/25 09:09] (atual) – [Documentação] cartola
Linha 1: Linha 1:
-Esse é um guia pessoal de referência. Anoto aqui dicas que considero úteis, de modo que possa acessá-las de qualquer lugar, aproveitando para compartilhar com quem possa ter interesse.+====== Programação Shell Script: boas práticas ====== 
 +Antes veja [[ti_publica:desenvolvimento_de_sistemas:boas_praticas|Desenvolvimento de sistemas: boas práticas]] 
 + 
 +Esse é um guia pessoal de referência. Na maioria dos casos a dica se baseia no **Shell Bash**, mas muitas são genéricas. Anoto aqui dicas que considero úteis, de modo que possa acessá-las de qualquer lugar, aproveitando para compartilhar com quem possa ter interesse.
  
 Ao longo de alguns anos programando a gente vai adquirindo alguns hábitos e aprendendo algumas boas dicas quando trocamos experiências com colegas ou aprendemos mais novidades estudando. Ao longo de alguns anos programando a gente vai adquirindo alguns hábitos e aprendendo algumas boas dicas quando trocamos experiências com colegas ou aprendemos mais novidades estudando.
Linha 5: Linha 8:
 Naturalmente algumas dicas aqui provavelmente servirão pra outras linguagens de programação. A medida que eu perceber isso vou tentar marcá-las como "**DICA GERAL**" Naturalmente algumas dicas aqui provavelmente servirão pra outras linguagens de programação. A medida que eu perceber isso vou tentar marcá-las como "**DICA GERAL**"
  
 +===== Referências Externas =====
 +
 +==== Gerais ====
 +  * [[http://kvz.io/blog/2013/11/21/bash-best-practices/|Bash best practices]]
 +==== Frameworks ====
 +  * [[https://invent.life/project/bash-infinity-framework/|Infinity framework]]
 +  * [[http://bashinator.org/|Bashinator]] - lista outros frameworks também
 +  * [[https://github.com/sstephenson/bats]] - Testes unitários automatizados
 +
 +==== IDE ====
 +
 +IDE é a sigla de Integrated Development Environment, que simplesmente se refere ao programa que se usa para escrever o código. Eu costumo escrever usando o [[https://www.vim.org/|Vim (Vi IMproved)]]. Sendo ele um editor genérico, é interessante configurá-lo pra facilitar a programação em shell.
  
 +  * Costumo identar com 2 espaços: set tabspace=2
 +  * Costumo limitar as linhas a 80 colunas:\\ set columns=80\\ set textwidth=80\\ set wrapmargin=8
 +  * Gosto do [[https://www.shellcheck.net/|Sellcheck]] que já verifica erros ao salvar o arquivo, dando dicas de melhores práticas.
 ======= Documentação ======= ======= Documentação =======
  
 Uma etapa bem sedimentada nos conceitos de engenharia de software é a documentação. Já vi muita documentação de sistemas e muito trabalho sendo contratado que exigia a criação de uma. Há uma documentação, porém, pra qual muitas vezes não é dada a devida atenção, seja em contratos comerciais, seja na verificação do produto final, mesmo que gerado internamente numa empresa ou por uma pequena equipe: comentários e código bem escrito. Uma etapa bem sedimentada nos conceitos de engenharia de software é a documentação. Já vi muita documentação de sistemas e muito trabalho sendo contratado que exigia a criação de uma. Há uma documentação, porém, pra qual muitas vezes não é dada a devida atenção, seja em contratos comerciais, seja na verificação do produto final, mesmo que gerado internamente numa empresa ou por uma pequena equipe: comentários e código bem escrito.
  
-**Comentários - **DICA GERAL** +**Comentários - DICA GERAL** 
-**\\   **regras de negócio** - um código bem comentado pode conter até as regras de negócio que estão normalmente num documento de especificação. Isso facilita a manutenção atualizada. No momento que a regra for alterada na prática, o programador está ali e pode ver que é necessário alterar o comentário.+ 
 +   **regras de negócio** - um código bem comentado pode conter até as regras de negócio que estão normalmente num documento de especificação. Isso facilita a manutenção atualizada. No momento que a regra for alterada na prática, o programador está ali e pode ver que é necessário alterar o comentário.
   *  **lógica** - em outras situações o programador faz uma lógica mais complexa e não a explica em comentários. Isso é muito ruim, tanto para trabalho em equipe quanto para o próprio programador, quando tem que mexer nesse código meses depois.   *  **lógica** - em outras situações o programador faz uma lógica mais complexa e não a explica em comentários. Isso é muito ruim, tanto para trabalho em equipe quanto para o próprio programador, quando tem que mexer nesse código meses depois.
  
-**Código bem escrito**\\+**Código bem escrito** 
   *  **identação** - além de comentários, um código bem identado ajuda na compreensão da lógica. Shell não exige identação, o que pode ser uma armadilha - **DICA GERAL**   *  **identação** - além de comentários, um código bem identado ajuda na compreensão da lógica. Shell não exige identação, o que pode ser uma armadilha - **DICA GERAL**
   *  **nomes de variáveis** - dê nomes de variáveis que indiquem seu significado e uso - **DICA GERAL**   *  **nomes de variáveis** - dê nomes de variáveis que indiquem seu significado e uso - **DICA GERAL**
   *  **nomes de variáveis minúsculos** - é um hábito de muitos programadores Shell o uso de nomes maiúsculos para variáveis. Isso aumenta o risco de acertar o nome de uma variável ambiente, essas sim, tradicionalmente maiúsculas.   *  **nomes de variáveis minúsculos** - é um hábito de muitos programadores Shell o uso de nomes maiúsculos para variáveis. Isso aumenta o risco de acertar o nome de uma variável ambiente, essas sim, tradicionalmente maiúsculas.
  
-**Cabeçalho - **DICA GERAL** +**Cabeçalho - DICA GERAL** 
-**\\Use um cabeçalho padrão nos seus códigos. Um bom cabeçalho pode conter:+ 
 +Use um cabeçalho padrão nos seus códigos. Um bom cabeçalho pode conter: 
   *  Descrição geral do que aquele código faz   *  Descrição geral do que aquele código faz
   *  Nome do autor e data de criação   *  Nome do autor e data de criação
Linha 26: Linha 48:
   *  Resumo de parâmetros que recebe e que retorna   *  Resumo de parâmetros que recebe e que retorna
  
 +**Interrompendo o programa em caso de erros**
  
 +Alguns erros podem passar limpos pela execução de um shell e isso pode causar problemas difíceis de solucionar depois que o código cresce muito. Uma dica é colocar sempre no início do script a definição:\\
 +
 +''set -euo pipefail''
 +
 +(Fonte:[[https://pythonspeed.com/articles/shell-scripts/|Artigo externo]])
 ======= Estrutura do programa ======= ======= Estrutura do programa =======
  
Linha 41: Linha 69:
 ======= Testes automatizados ======= ======= Testes automatizados =======
  
 +Existem linguagens que tem ferramentas pra facilitar isso, existe alias o [[https://github.com/bats-core/bats-core|BATS]] ([[https://hk.saowen.com/a/76a0859c6dbd6a2ac11c80dada4234fac367fdf43db39cf7e32992e46e8e1ed9|veja também esse guia]]) pro shell Bash, mas trabalhando com o conceito é possível fazer pra qualquer linguagem. Como Bash trabalha com funções, o melhor é refatorar o código de modo que funções recebam e retornem valores ou que executem coisas verificáveis, viabilizando testes externos que não necessariamente precisem executar as tarefas reais ou no ambiente real.
  
-   Refatoração para viabilizar +Um script muitas vezes é pequeno e, nesses casos, a criação de testes talvez não se justifique. Se começar a crescer, se for complexo, se for ser alterado de tempos em tempos, então pode se considerar essa criação dos testes, que garantirá o funcionamento esperado de cada parte do código, evitando que uma eventual alteração faça com que se crie um bug. Essa é a moral da coisa. 
-  *  Script testador+ 
 +**Refatoração para viabilizar 
 +**\\  *  Dividir o código colocando as partes que se quer testar em funções que possam ser testadas separadamente. Sem divisão fica complicado testar todo o código e fica complicado se referir a partes de um código inteiro. 
 +  *  Funções que recebem e retornam facilitam muito os testes 
 +  *  Modularizar em outros scripts também pode facilitar, se eles também receberem e retornarem algo 
 + 
 +**script testador X modo teste 
 +**\\  *  Para criar um script externo que teste o principal, o ideal é que o programa principal só seja executado se não for um teste. Ao colocarmos o código separado em funções podemos testar se o principal deve rodar ou não. Para carregar as funções do script principal no script testador usamos a sintaxe: 
 +<code>source principal.sh</code> 
 +e as funções estarão disponíveis dentro do testador, não sendo executada nenhuma. Ao executar o principal diretamente, o programa principal dispara os processos. Como fazer essa diferenciação? Através da variável "$0". Ao chamar um script diretamente, o $0 assume o nome do script. Quando carregamos com o "source" ficamos com "$0 = -bash". A parte principal do script deve, portanto, ter sua execução condicionada: 
 +  ## PROGRAMA PRINCIPAL 
 +    if [ "$0" != "-bash" ]; then 
 +      echo "programa principal" 
 +    fi 
 +Os resultados da execução de cada uma das formas é o previsto: 
 +  $ source principal.sh 
 +    $ . principal.sh 
 +    $ ./principal.sh 
 +    programa principal 
 +    $ bash principal.sh 
 +    programa principal 
 +Notas: 
 +  *  O comando "." é equivalente ao "source" 
 +  *  Mesmo chamando outro shell com "bash" o "$0" se mantém como "principal.sh" 
 +De resto, portanto, é colocar em funções o que é necessário testar no código e chamar elas dentro da parte principal do programa (que não será testada) e dentro do script testador, que promoverá, idealmente, uma série de testes, verificando o comportamento de cada função para N situações diversas, de modo a garantir a estabilidade do código.
  
  
Linha 50: Linha 103:
  
   *  Controle de versão   *  Controle de versão
 +
 +
 +======= Dicas da linguagem =======
 +
 +
 +
 +===== Arquivos temporários ou em memória =====
 +
 +No Bash podemos usar a sintaxe:
 +<code>comando1 <( comando0 )</code>
 +onde o trecho "<( comando0 )" se comporta como um arquivo para o "comando1". Dessa forma, se precisamos lidar com um conteúdo gerado pelo comando0 mas o comando1 só trabalha com arquivo, podemos trabalhar apenas em memória, sem a necessidade de criar um arquivo temporário em disco, o que consome mais código, mais recursos e mais tempo de programação e execução.
 +
 +**Referência**: [[https://github.com/pkrumins/bash-redirections-cheat-sheet|Bash redirections cheat sheet]]
 +
 +Exemplo: definindo múltiplas variáveis
 +  read filesystem total used free perc name < <(df . | tail -1)
 +
 +
 +===== Lendo linha a linha e atribuindo colunas a variáveis =====
 +
 +  echo "Sistema"
 +  echo "  disponivel"
 +  df | grep -v "^Filesystem" | while read fs total used avail perc mount; do
 +    echo "$fs"
 +    echo "        $avail"
 +  done
 +Resultado da execução:
 +  $ ./exemplo.sh 
 +  Sistema
 +          disponivel
 +  /dev/mapper/system-root
 +          2014976
 +  devtmpfs
 +          8121660
 +  tmpfs
 +          8133648
 +
 +  *  opção de delimitador
 +  *  como jogar linha inteira numa variável
 +  *  readarray
  
boas_praticas_de_programacao_shell_script.txt · Última modificação: 2022/03/25 09:09 por cartola