de Finibus Bonorum et Malorum



Reclamações recentes

Introdução à Computação: ontem e hoje

Uma das situações malucas envolvendo voltar à faculdade depois de vinte anos é que é inevitável fazer comparações entre as disciplinas de antes com as suas equivalentes de agora.

No que se refere às disciplinas de Física e Cálculo, para ser honesto eu ainda não parei pra pensar a respeito, mas o mesmo não pode ser dito de Introdução à Computação.

Para ser honesto, não sei nem se o conjunto de diferenças entre o MAC115 de 99 e o de 2023 é sequer enumerável. Mesmo assim, eu posso tentar falar das que eu tenho percebido.

Ao longo dos anos eu sei que a abordagem dessa disciplina mudou bastante – e acho bom deixar bem claro que eu não sou nenhum especialista em ensino de computação. Sou só um sujeito aleatório com um tempo de experiência em programação (praticamente um diletante), mas eu tenho uma perspectiva bem particular: passei pela disciplina em dois momentos bastante distantes um do outro.

A Função da Introdução à Computação

Quando se fala em “Computação”, especialmente na área acadêmica, e ainda mais na Física, o paralelo com a instrução “tradicional” em informática – Word, Excel, Powerpoint, etc – não chega nem perto de cumprir qualquer requisito.

Embora existam aqueles que optem por usar um pacote office para escrever seus relatórios e outros trabalhos acadêmicos, a introdução à computação tem uma função bem diferente.

Hoje em dia é virtualmente impossível falar em atividade de pesquisa ou qualquer outra área de aplicação de ciência sem falar de computação. Qualquer tarefa que vá ser realizada – teórica ou experimental – implica no uso de um computador para cálculos, simulações, processamento e análise de dados. E isso, por sua vez, implica em programação e, por associação, implica em conhecer o modo de funcionamento de um computador.

O Fundamento da Computação

Entender como funciona um programa de computador e como escrever um programa de computador são dois aspectos da mesma entidade.

Embora, fundamentalmente, ambos sejam essencialmente a mesma coisa, para que isso seja verdade é necessário chegar ao nível mais básico da computação, isto é, a manipulação de bits pela eletrônica que constitui a base de qualquer computador: os arranjos básicos de elementos fundamentais da eletrônica que constituem a base da lógica.

Essencialmente formados a partir de transistores, esses elementos – as portas lógicas – podem ser usados para estabelecer uma base de operações que pode ser usada para construir combinações cada vez mais elaboradas, eventualmente se tornando instruções, a linguagem básica de um processador.

Mesmo esse resumo de dois parágrafos, que essencialmente resume cursos inteiros de graduação a umas poucas frases, já é capaz de transmitir uma noção do nível de complexidade que programar um computador só com isso – definir 1’s e 0’s diretamente no nível do hardware – pode ser uma tarefa essencialmente incomensurável.

Só de pensar que foi exatamente assim que os primeiros programadores trabalharam, nas versões primordiais dos computadores – ENIAC, EDSAC e outros – é absolutamente assombroso. Os níveis de dedicação e de atenção necessários, sem falar no tempo investido para concluir qualquer tarefa, só eram humanamente possíveis porque, naquela época, os limites do que um computador era capaz de fazer eram… modestos.

O surgimento das linguagens de programação

Felizmente, conforme os computadores avançaram e foram ficando cada vez mais complexos e mais capazes, começaram a surgir maneiras de abstrair a programação de computadores a partir do simples código de máquina, escrito no formato binário.

O primeiro passo para isso foram as linguagens “assembly” – ou, numa tradução livre, linguagens de montagem. Nesse nível, ainda estamos, basicamente, no mesmo nível da linguagem de máquina. Mas as linguagens de montagem oferecem uma interface menos hostil. Elas expressam comandos que serão fornecidos à máquina com base em letras e números. Isso as torna mais acessíveis a humanos que estão acostumados a falar em línguas humanas – inglês, português, etc.

Mas, mesmo sendo abstrações, as linguagens de montagem ainda não estão distantes do nível mais básico. E, por isso, elas são específicas para cada modelo de processador. Então, novas camadas de abstração começam a surgir e, com elas, novas dificuldades.

Quanto maior o nível de abstração, mais distante da máquina em si (o “bare metal”) estamos. Ao converter uma instrução de um nível de abstração mais alto para um mais baixo, algo acaba se perdendo. Caminhos mais “genéricos” são adotados, de forma que a mesma instrução possa ser traduzida de maneiras equivalentes, dependendo do alvo. E, de fato, até hoje alguns programadores ainda se aventuram a escrever em assembly quando existe a necessidade.

Níveis cada vez maiores de abstração

Mas, de forma geral, existem maneiras mais… linguísticas de escrever programas. A linguagem assembly ainda é bastante complexa e difícil de escrever e de ler. Por isso, existem as linguagens de alto nível, isto é, conjuntos “gramaticais” que podem ser utilizados para escrever a sequência de instruções que deve ser transmitida ao hardware.

Essas linguagens de alto nível são traduzidas em linguagem de máquina por programas especiais – os compiladores. Eles executam uma verificação no código escrito, para garantir que ele obedece às regras específicas de cada linguagem, e depois traduz o código para que ele possa ser executado pela máquina.

A partir desse ponto, as linguagens de programação começaram a se proliferar profusamente, ao ponto que, hoje em dia, estima-se que existem, pelo menos, 700 linguagens de programação diferentes.

Duas faces da mesma moeda

Com uma quantidade indefinida de linguagens de programação, e em um nível de abstração tão elevado, fica difícil saber realmente como funciona um computador só com base em uma linguagem. E, de fato, é meio desnecessário entender como funciona o nível mais fundamental da lógica do hardware. Nesse nível de abstração, torna-se importante saber duas coisas:

  • Quais os conceitos fundamentais são necessários para estruturar um programa de computador
  • Como codificar as instruções correspondentes a um programa, criadas com base nesses conceitos

A primeira é essencialmente a mesma para qualquer programa. Ela dependerá, claro, mais do hardware a ser utilizado, pois cada arquitetura tem suas próprias caracterísitcas.

A segunda, por sua vez, depende diretamente de qual será a linguagem escolhida para a tarefa. E, caso ainda não tenha ficado claro, existem tipos diferentes de programas, e para cada um existe uma linguagem de programação que é mais conveniente.

Aprendendo a programar

Então, qual o melhor jeito de ensinar alguém a programar?

Podemos mostrar quais os princípios mais importantes a considerar quando planejar um programa, de forma que o resultado final de fato execute a tarefa que precisa. Ou podemos só ensinar alguma linguagem de programação, e esperar que a prática de programar acabe induzindo o surgimento desses princípios de forma espontânea.

Ontem…

Da primeira vez, o programa do curso era bem claro: como dividir a tarefa em partes pequenas o suficiente para serem expressas como uma sequência de comandos simples. O que é um endereço, uma instrução, um algoritmo e um programa. Expressões, comandos, seleções e repetições, entrada e saída, variáveis, procedimentos.

Passamos um bom tempo antes mesmo de começar a escrever em qualquer linguagem de programação; escrevíamos pseudo-código, uma espécie de português limitado, que descrevia com palavras simples e inequívocas o que um algoritmo deveria fazer e como deveria fazê-lo.

…e hoje

Embora os fundamentos ainda estejam presentes no curso atual, eles não estão no centro da atenção. Logo de cara, uma linguagem de programação é introduzida e utilizada para expor e ilustrar esses fundamentos. Em vez de criar uma base para a compreensão de como se deve instruir o computador a executar uma tarefa, somos ensinados a usar a linguagem.

Sem dar atenção a qual deve ser a mensagem que será transmitida por ela, é como descrever um livro e esperar que a pessoa consiga deduzir o vocabulário e as regras gramaticais da língua portuguesa, sem dar atenção ao conteúdo. As nuances da linguagem são devidamente exploradas, casos problemáticos e equívocos comuns são devidamente demonstrados e as suas soluções, devidamente exploradas. Mas ninguém está aprendendo a programar.

Não é surpresa nenhuma, então, que no fim das contas tudo que as pessoas conseguem fazer é recriar aquilo que já viram.

Linguagem não é conteúdo

É importante deixar uma coisa clara: não se trata de um curso ruim. Mas não é o curso necessário a essa altura, porque ensina Python, sem preocupação com a lógica da programação de computadores.

Também não se trata de uma crítica à linguagem. Python é uma linguagem bastante bem-sucedida, amplamente utilizada e saber utilizá-la é uma habilidade importante no mundo científico – e fora dele.

Mas de que adianta ter o conjunto de ferramentas se não sabemos como utilizá-las?

A importância de escolher a linguagem certa

Depois de ter passado por dois cursos de introdução à computação, é importante ter alguns pontos em mente, para não perder a perspectiva.

Meu ponto de vista é bastante enviesado: por um lado, só realmente passei por esse processo de início do aprendizado uma vez. Testemunho esta nova “incarnação” do curso com um antecedente bem mais encorpado, não somente do ponto de vista do que eu já conheço a respeito de computadores e programação, mas também por anos de experiência na prática direta do uso da computação em tudo que eu fiz até hoje.

Por isso, não posso realmente relatar qual é a perspectiva de quem está passando pelo processo de aprender a programar agora.

Mas, ao mesmo tempo, justamente pelo mesmo motivo, posso entender que o formato atual não é bom. Não porque opta por ensinar uma linguagem específica (embora, na minha opinião, isso seja um problema), mas porque negligencia os fundamentos. A linguagem é apenas uma encarnação disso, e Python especificamente é uma linguagem consideravelmente abstrata nesse quesito.

Uma linguagem mais estrututrada, com declaração explícita de variáveis, acesso a ponteiros (e, portanto, a uma janela ampla para o entendimento de endereços de memória), compilada, necessidade de implementação explícita de estruturas de dados, tipagem estática e sintaxe bem definida, com todas essas regras impostas rigidamente pelo compilador, tem mais potencial para apresentar uma correspondência mais fiel aos fundamentos da programação.

O poder da frustração

Justamente por esses motivos, uma linguagem como C seria mais adequada.

Por um lado, a rigidez do C imediatamente leva a problemas. A flexibilidade de uma linguagem como Python a torna muito mais tolerante com os erros que fatalmente cometemos ao escrever um programa.

Pode parecer uma benesse a princípio: o programa roda sem reclamar! Mas, ao mesmo tempo, a falta de reclamação na hora de executar se torna uma dor de cabeça: se ele não reclama dos problemas, fica mais difícil entender porque o resultado não é o esperado. “Onde foi que eu errei?” a pessoa se pergunta.

Python reclama menos, mas também é mais mal comportado.

Em C, qualquer erro mínimo gera um escândalo na hora da compilação. Se houver erros no programa, ela falha e o executável não é gerado. Por um lado, isso torna o processo de programação muito mais desgastante, porque muitas vezes nem mesmo é possível testar se a implementação realmente executa o que se espera dela. Mas, ao mesmo tempo, se a compilação é concluída, a chance é muito maior de que eventuais problemas venham de problemas “legítimos”, em vez de idiossincrasias obscuras da linguagem.

Ao transpor a barreira imposta pelo compilador, garantimos que a “gramática” está correta; nos resta saber se a mensagem é a mesma que pretendemos transmitir. O programa faz o que queremos que ele faça? Implementamos o algoritmo corretamente? Quais são os casos que podem criar problemas com a lógica utilizada na solução do problema?

O drama do curso preguiçoso

A experiência de MAC115 em 2023 foi… desagradável, desde antes do começo. O critério idiossincrático que levou à recusa do meu pedido de aproveitamento já foi ruim o suficiente – ter feito o curso há mais de dez anos não significa nada.

A escolha da abordagem, por sua vez, foi infeliz. O curso foi transportado a partir de uma versão já existente em uma plataforma online (o Coursera), sem tirar nem por. Por si só, isso já derrota o propósito de uma disciplina dedicada a ensinar os princípios da computação. Para além disso, a escolha de ensinar uma linguagem (independente de qual seja), sem preocupação com os princípios básicos da programação, é desastrosa. Salvas as devidas proporções, não deixa de ser semelhante a quem quer cobrir Lagrangianas em Física 1.

A escolha por automatizar a correção dos Exercícios-Programa tem vantagens óbvias, mas a tentativa de transportar essa abordagem para as provas criou uma situação absurda. Critérios desproporcionais para aplicação e instruções confusas para preenchimento das respostas transformaram a experiência de prova em algo traumático, desgastante e contraproducente. As questões das provas – que, por si só, tinham seus méritos – se transformaram em armadilhas. Em vez de realmente avaliar alguma coisa, induziram o erro, com o “bônus” de que erros nas respostas poderiam subtrair ainda mais pontos da nota final.

A conclusão do curso, com uma mensagem confusa e ameaçadora sobre os EPs, encerrou esse curso num tom desagradável de assédio moral, com uma abordagem tosca, e – sejamos claros aqui – antiética para com a totalidade dos alunos, em vez de abordar discreta e individualmente aqueles que foram considerados suspeitos pela “ferramenta” utilizada para julgar a similaridade entre os códigos submetidos.

Em um mundo em que não é mais opcional saber lidar com computadores – muito para além do simples “pacote office” – essa disciplina prestou um enorme desserviço ao ensinar a coisa errada, da forma errada. E, pior ainda, amortizou qualquer possível interesse por parte de quem, em sua profissão, irremediavelmente dependerá do conhecimento que deveria ter adquirido durante este semestre.


Comentários

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *