Anotações do Curso Shell Prático (aula 1)
Estas são as anotações da aula 1 do curso Shell Prático, que estão sendo compartilhadas livre e gratuitamente graças aos inscritos no curso e apoiadores. Você pode me ajudar a continuar produzindo e compartilhando esse tipo de material de várias formas:
- Divulgando, inscrevendo-se ou doando inscrições para os meus cursos;
- Com seu apoio regular pelo Apoia.se;
- Com seu apoio eventual pelo PicPay ou pela chave PIX abaixo:
PIX: e26a05db-d200-4261-aa65-c6ac3dc2dd0f
Conheça também a campanha de pré-lançamento do meu próximo livro!
Aula 1 – Em busca de um método
Sim, os problemas podem ter um caminho "mais rápido" para a solução, mas este caminho, geralmente, só servirá para aquele problema. É a esse tipo de "caminho mais curto" que nós chamamos de "soluções mágicas", "balas de prata" ou apenas de "truques".
Um truque é uma boa ideia que resolve um problema; um método é uma boa ideia que resolve muitos problemas. (Prof. Augusto Morgado)
Quando se trata de aprender o shell, nós temos que dominar métodos, não truques.
Tentar aprender shell com base em truqes para soluções específicas equivale ao código desta calculadora (em Python):
# my_first_calculator.py by AceLewis
# TODO: Make it work for all floating point numbers too
if 3/2 == 1: # Because Python 2 does not know maths
input = raw_input # Python 2 compatibility
print('Welcome to this calculator!')
print('It can add, subtract, multiply and divide whole numbers from 0 to 50')
num1 = int(input('Please choose your first number: '))
sign = input('What do you want to do? +, -, /, or *: ')
num2 = int(input('Please choose your second number: '))
if num1 == 0 and sign == '+' and num2 == 0:
print("0+0 = 0")
if num1 == 0 and sign == '+' and num2 == 1:
print("0+1 = 1")
if num1 == 0 and sign == '+' and num2 == 2:
print("0+2 = 2")
if num1 == 0 and sign == '+' and num2 == 3:
print("0+3 = 3")
if num1 == 0 and sign == '+' and num2 == 4:
print("0+4 = 4")
if num1 == 0 and sign == '+' and num2 == 5:
print("0+5 = 5")
if num1 == 0 and sign == '+' and num2 == 6:
print("0+6 = 6")
if num1 == 0 and sign == '+' and num2 == 7:
print("0+7 = 7")
Mais de 20800 linhas depois…
if num1 == 50 and sign == '*' and num2 == 47:
print("50*47 = 2350")
if num1 == 50 and sign == '*' and num2 == 48:
print("50*48 = 2400")
if num1 == 50 and sign == '*' and num2 == 49:
print("50*49 = 2450")
if num1 == 50 and sign == '*' and num2 == 50:
print("50*50 = 2500")
print("Thanks for using this calculator, goodbye :)")
Esta seria uma caricatura perfeita para aquelas situações que vemos em fóruns e grupos de ajuda onde as pessoas já chegam perguntando "qual é o comando para isso, aquilo ou aquilo outro", como se uma das zilhões de combinações possíveis de comandos, parâmetros e estruturas, magicamente, pudessem resolver todos os outros tantos zilhões de problemas possíveis.
O que é um método?
- Ferramenta para solucionar problemas.
- Conjunto relativamente estruturado de ações que levam a possíveis soluções.
Nós queremos um método caracterizado pela…
- Clareza
- Simplicidade
- Reprodutibilidade
- Capacidade de gerar conhecimento
Alguns métodos importantes
Alguns métodos utilizados no domíno das ciências e da matemática podem ser muito úteis na solução de problemas em shell.
Método indutivo
- Do particular, chega-se ao geral.
- Observação e registro.
- Análise e classificação.
- Produção de inferências.
Exemplo
- Sempre que golepio o ferro, ele esquenta (observação).
- Golpeando outros metais eu observo aquecimento (análise).
- Provavelmente, todos os metais esquentam quando golpeados (inferência).
Método dedutivo
- Do geral, chega-se ao particular.
- As conclusões estão implícitas nas premissas.
- Se as proposições são verdadeiras as conclusões também serão.
Exemplo
- Chama-se de "brasileiro" quem nasce no Brasil.
- Eu nasci no Brasil.
- Logo, eu sou brasileiro.
Método hipotético-dedutivo
- A reflexão racional enfrenta a observação empírica.
- Observação (do problema).
- Produção de hipóteses provisórias.
- Dedução das consequências.
- Verificação dos enunciados (experimentos).
Exemplo
- Minha linha de comando resulta em um erro de excesso de argumentos (problema observado).
- As palavras expandidas estão excedendo o limite de argumentos do shell (hipótese).
- Expandir menos argumentos não resultará em erros (dedução).
- Meu novo comando com menos argumentos resultou em erro? (verificação)
Método Polya (método de 4 etapas)
- George Polya, matemático húngaro.
- Entender o problema;
- Elaborar um plano de ação;
- Executar o plano de ação;
- Examinar o resultado.
Etapa 1: entender o problema
- Quais são os dados do problema?
- Quais são as incógnitas?
- Quais são as condições e restrições?
- É possível satisfazer as condições?
- As condições e restrições bastam para determinar as incógnitas?
Etapa 2: elaborar um plano de ação
- É possível descrever o problema de outras formas?
- É possível transformar o problema em outro equivalente?
- É possível decompor o problema em casos mais simples?
- Existem soluções conhecidas para esses casos?
Etapa 3: executar o plano de ação
- Cada passo da possível solução está correto?
- É possível provar que cada passo está correto?
Etapa 4: examinar o resultado
- O resultado parece razoável?
- Os argumentos utilizados são convincentes?
- É possível resolver o problema de outra forma?
- A solução é aplicável a outros problemas?
O nosso método
Originalmente apresentado em três passos no Curso Shell GNU, o método que nós sugerimos para a solução de problemas passou a incorporar, de forma adaptada, a quarta etapa do método Polya: o exame do resultado, indispensável para que aconteça a consolidação das soluções como conhecimento:
- Identificação (mudou para "descrição")
- Abstração (mudou para "modelagem")
- Demonstração
- Consolidação
O que é um problema?
No contexto das nossas atividades, um problema é qualquer situação que requeira uma solução na forma de uma ou mais linhas de comandos. Ele também será o ponto de partida para a busca de uma solução e, consequentemente, da produção de um conhecimento.
Natureza
É preciso levar em conta a natureza dos problemas que enfrentaremos. Na quase totalidade dos casos, eles envolverão o processamento de dados, a manipulação de processos ou alguma combinação de ambos.
Como exemplo, digamos que o problema seja: encontrar uma forma de renomear todos os arquivos em uma pasta. Neste caso, nós teremos que obter os nomes originais de todos os arquivos (dados de entrada) e produzir "textos" (dados processados) correspondentes aos comandos que serão executados (processos) para, finalmente, renomear cada um dos arquivos.
No fim das contas, nosso método nos levará à produção de uma ou mais linhas de comandos que, tal como as expressões matemáticas, são apenas outra forma de descrever o problema. Portanto, "renomear todos os arquivos em uma pasta" também poderia ser expresso como, por exemplo:
for f in *; do mv $f novo-$f; done
Passo 1: descrição (era "identificação")
O principal desafio na resolução de problemas na vida real é que eles nunca vêm com um enunciado! Sendo assim, no primeiro momento, cabe a nós a elaboração do enunciado, analisando cuidadosamente a situação com o propósito de identificar o que está acontecendo e estabelecer o que se pretende obter ao final.
Nesta etapa, o objetivo é descrever o problema de forma clara e objetiva, buscando sempre diferenciá-lo dos sintomas e/ou de possíveis soluções. Eventualmente, pode ser útil decompor o problema em casos mais simples onde, possivilmente, sejam aplicáveis soluções já conhecidas.
Nosso primeiro passo combina as duas primeiras etapas do método Polya:
- Quais são os dados do problema?
- Quais são os resultados esperados?
- Quais são as condições e restrições?
- É possível satisfazer as condições e as restrições?
- É possível descrever o problema de outras formas?
- É possível transformar o problema em outro equivalente?
- É possível decompor o problema em casos mais simples?
- Existem soluções conhecidas para o problema ou para os casos relacionados?
Passo 2: modelagem (era "abstração")
Com o problema devidamente descrito em linguagem humana, nossa meta será utilizar os recursos do shell, não como comandos, programas ou ferramentas, mas como uma linguagem comum entre nós e o sistema operacional. Aqui, comandos, utilitários e demais elementos léxicos serão utilizados para descrever o problema na forma de modelos capazes de expressar o problema como um todo ou os casos derivados da sua decomposição.
Para que a construção de abstrações seja efetiva, é importante possuir alguma proficiência no uso do shell e/ou dos programas de uso específico em cada caso, mas isso é algo que se desenvolve com o tempo e com o hábito de trabalhar com método na transformação de problemas em conhecimento.
Passo 3: demonstração
Nesta etapa, nós executaremos os modelos construídos e avaliaremos os resultados obtidos, tal como na terceira etapa do método de Polya:
- Cada modelo produzido se comporta como esperado?
- É possível provar que os modelos se comportam como esperado?
Com base nos resultados…
- Se eles forem incorretos, será necessário rever os dois primeiros passos antes de tentar novamente.
- Se eles forem apenas "inesperados" (o que não significa que sejam "incorretos"), pode ser necessário rever a etapa da modelagem.
- Caso eles correspondam comprovadamente ao esperado, podemos ir ao passo seguinte.
Passo 4: consolidação
Quando chegamos a este último passo, é bem possível que o problema já esteja solucionado, mas o nosso trabalho ainda não terminou! Para que o problema se consolide como conhecimento, ainda será preciso verificar se:
- A solução encontrada parece razoável?
- Os modelos utilizados são coerentes com a complexidade do problema?
- É possível resolver o problema de outra forma?
- A solução é aplicável a outros problemas?
É aqui que cabe a citação atribuída a Buckminster Fuller:
Quando estou trabalhando em um problema nunca penso em beleza, penso apenas em como resolver o problema. Mas, quando termino, se a solução não está bonita, eu sei que está errada.