Recentemente um amigo próximo me perguntou o que era exatamente o trabalho de um programador. Curioso que em uma sociedade tão atravessada por softwares se saiba tão pouco sobre o que eles são. Os usuários conhecem dos softwares somente a interface, o que permite uma noção apenas parcial da realidade da coisa. Pensar sobre isso me fez perceber que a dificuldade em explicar o que é um software livre advém do fato de que as pessoas não sabem o que é um software. Como o software é pensado como um utilitário, um produto, falar em software livre soa o mesmo que grátis e perde-se totalmente o foco da questão.
Assim, o presente post se propõe a explicar o que é um software, bem como o que significa torná-lo
livre.
O que é programar?
Programar é a arte de resolver problemas (o que a aproxima da engenharia), resolução feita por meio da concatenação de instruções. Quando, por exemplo, a chefe diz para o secretário:
"Sr. Albuquerque, estarei ocupada agora à tarde, portanto, se alguém me ligar, diga que eu estou em uma reunião e pergunte se quer deixar recado. Ah, a não ser que seja a Cleide, aí você pede pra ela me ligar no celular que eu quero falar com ela."
Ela o está programando para reagir frente a uma ligação. Quando tratamos de computadores, contudo, a programação não se dá por meio de um idioma natural (como o português), mas por meio daquilo que chamamos de linguagem de programação, que nada mais é do que um idioma formal, com sintaxe rígida e semântica unívoca.
Se a Sra. Santos estivesse programando um computador em vez de um ser humano, suas instruções se assemelhariam com o que segue:
Se alguém ligar:
Perguntar quem é:
Se for Cleide:
Pedir para que ela ligue no celular da Sra. Santos.
Do contrário:
Dizer que Sra. Santos está em reunião.
Perguntar se querem deixar recado.
Se houver recado:
Anotar recado.
Agradecer a ligação e desligar.
Observe que a linguagem natural na verdade esconde um conjunto complexo de instruções. Com poucas orações direcionadas à reação frente a uma situação trivial da vida quotidiana, a Sra. Santos na verdade passou várias instruções condicionais aplicáveis a uma pluralidade de eventos. O código acima, todavia, é meramente exemplificativo da estrutura de um programa, tratássemos de um computador, seria necessário um maior rigor formal que somente é possível com uma linguagem artificial.
A questão mais imediata é: por que um computador não pode ser instruído em português? Por que a linguagem de programação não pode ser a língua portuguesa? Apesar de soar trivial, a resposta a esta pergunta é a chave para entender não somente a programação, mas também os computadores e, por via reflexa, os humanos.
Um computador não pode ser programado em linguagem natural porque ele não é capaz de entender, mas apenas de reagir. Um computador não passa de um pedaço de silício que reage aos estímulos elétricos que passam por ele de uma maneira determinística. Diz-se que os computadores entendem apenas a álgebra booleana dos números binários, mas mesmo isto é uma abstração. A álgebra booleana na verdade é a forma como nós humanos abstraímos e formalizamos os processos físicos que ocorrem quando aquele objeto é estimulado de diferentes formas.
Assim, no nível da máquina, programar significa fornecer à maquina instruções em dois diferentes estados - binárias (zeros e uns). Ao receber estas instruções, o computador as computa (do Houaiss: calcular, efetuar confronto, comparar, igualar, contar) e isso é tudo o que ele pode fazer, cálculos.
Porém, como ficar decorando instruções no formato "00101011 10011101 ..." é simplesmente um pesadelo para um ser humano, foram criadas as linguagens de programação, que nada mais são do que programas que agrupam estas instruções ininteligíveis em funções matemáticas (algoritmos) que são apelidadas com nomes próximos à linguagem natural humana, mais fáceis de memorizar. Essa tradução, contudo, não foi feita de imediato, mas é o resultado de uma lenta evolução ao longo dos muitos anos da história da computação.
O primeiro passo não exigiu um programa, mas foi apenas uma diferente forma de representar a mesma coisa. Em vez de pensar as instruções em números binários, que são muito fáceis de confundir, elas eram pensadas números
hexadecimais (em vez de dois algarismos - 0 e 1 -; dezesseis deles - 0-9 e A-F). Isso, contudo, ainda é muito longe do que um humano pode entender, de forma que diversas destas instruções foram agrupadas em mnemônicos para o que elas faziam. Assembly é a forma como esta linguagem mais básica foi denominada. Mas a Assembly ainda permanecia atrelada a instruções muito básicas e é preciso conhecer intimamente a CPU para saber como programar nesta linguagem.
Criaram-se então as linguagens chamadas de "alto nível". O exemplo clássico é a linguagem C. As linguagens de alto nível distanciam-se da matemática e do conhecimento do computador e possibilitam instruções muito mais próximas à linguagem humana, parecidas com o pseudo-código acima.
Creio que já estamos próximos aos hieróglifos egípcios, então um exemplo para ilustrar o que é programar. Um programa extremamente básico em linguagem de alto nível seria um que apenas dissesse uma frase, por exemplo, "já estou entediado".
Na linguagem python, de altíssimo nível, esse programa seria:
print "já estou entediado."
Em C, um pouco mais baixo nível:
#include <stdio.h>
int main()
{
printf("já estou entediado\n");
return 0;
}
Em Assembly, baixo nível:
lea 0x4(%esp),%ecx
and $0xfffffff0,%esp
pushl -0x4(%ecx)
push %ebp
mov %esp,%ebp
push %ecx
sub $0x4,%esp
movl $0x8048490,(%esp)
call 80482d4 <puts@plt>
mov $0x0,%eax
add $0x4,%esp
pop %ecx
pop %ebp
lea -0x4(%ecx),%esp
ret
Em hexadecimal isto seria traduzido por:
8d 4c 24 04
83 e4 f0
ff 71 fc
55
89 e5
51
83 ec 04
c7 04 24 90 84 04 08
e8 13 ff ff ff
b8 00 00 00 00
83 c4 04
59
5d
8d 61 fc
c3
90
E em binários, que são as instruções que o computador de fato processaria:
10001101 01001100 00100100 00000100
10000011 11100100 11110000
11111111 01110001 11111100
01010101
10001001 11100101
01010001
10000011 11101100 00000100
11000111 00000100 00100100 10010000 10000100 00000100 00001000
11101000 00010011 1111111111 1111111111 1111111111
10111000 00000000 00000000 00000000 00000000
10000011 11000100 00000100
01011001
01011101
10001101 01100001 11111100
11000011
10010000
Na realidade ninguém programa em binários ou em hexadecimal. A linguagem mais baixa que se usa ainda hoje é o código Assembly, mas nem todo programador entende esta linguagem. Cada linguagem tem uma vantagem. A vantagem daquelas de alto nível é delegar ao computador a preocupação com a lógica e os processos básicos, permitindo que o programador se preocupe apenas com os resultados e diminuindo muito o tempo de estudo e a possibilidade de erros. As de baixo nível permitem códigos mais enxutos, capazes de rodar em máquinas com menor potencial (relógios, semáforos, celulares, tocadores de mp3 etc), permitindo, ainda, um maior controle sobre o que será executado.
O programador de linguagens de alto nível, em vez de se preocupar com álgebra e registradores, pensa em instruções do tipo "se x, então y". Mas para que ele possa abstrair a lógica do computador é necessário que alguém antes dele tenha se preocupado com ela. Para que alguém possa escrever apenas print "já estou cansado." e fazer o computador exibir na tela a frase desejada, é preciso que alguém antes dele tenha criado um programa que entende caracteres, que alguém tenha criado um programa que exibe caracteres, que alguém tenha criado um programa que interpreta "print" e traduz em um longo conjunto de instruções binárias (que é a única coisa que o computador entende).