sábado, 30 de junho de 2012

O PROGRAMADOR HUMILDE


O PROGRAMADOR HUMILDE

Edsger Wybe Dijkstra

Tradução: Professor João Carlos de A. R. de Oliveira – DCC/UFJF


            Como resultado de uma longa seqüência de coincidências entrei na profissão de programação oficialmente na primeira manhã da primavera de 1952 e que me conste fui o primeiro holandês a fazê-lo em meu país. Em retrospecto, a coisa mais espantosa é a morosidade com a qual, ao menos naquela parte do mundo, a profissão de programação emergiu, morosidade essa que hoje é difícil acreditar. Mas sou grato por duas lembranças vivas daquele período que demonstram a morosidade sem deixar dúvida.
            Após haver programado por uns três anos, tive uma discussão com van Wijngaarden que era meu chefe no Centro de Matemática de Amsterdã – discussão pela qual serei agradecido a ele enquanto viver. O ponto era que eu me considerava estudante de física teórica na Universidade de Leiden e estava  achando cada vez mais difícil combinar as duas atividades; devia fazer minha cabeça: ou parava de programar e me tornava um físico teórico real e respeitável ou levaria o meu estudo de física a um término meramente formal, com um mínimo de esforço e me tornaria... Sim, o que? Um programador? Mas isso era uma profissão respeitável? Onde estaria aquela substância legítima do conhecimento que poderia suportá-la como uma disciplina intelectualmente respeitável? Lembro-me bem vivamente como invejava meus colegas da eletrônica que, quando questionados sobre sua competência profissional podiam ao menos assinalar que conheciam tudo sobre válvulas, amplificadores e o resto, enquanto eu sentia que, confrontado com essa questão, ficava com as mãos abanando.
            Cheio de receios, bati na porta do escritório de van Wijngaarden pedindo para falar com ele por um momento; quando saí, algumas horas mais tarde, eu era outra pessoa. Pois, após ouvir pacientemente os meus problemas ele concordou comigo que até então não havia disciplina de programação, e começou a explicar calmamente que os computadores vieram para ficar e quem sabe não seria eu uma das pessoas chamadas para fazer da programação uma disciplina respeitável nos anos vindouros? Esse foi um ponto decisivo em minha vida e completei meu estudo de física formalmente o mais rápido que pude. Uma moral da história acima, obviamente, é que nós devemos ser muito cuidadosos quando aconselhamos os jovens: algumas vezes eles seguem o conselho!
            Dois anos mais tarde, em 1957, eu me casei e o ritual de casamento na Holanda requer que você declare sua profissão; declarei que era programador. Mas as autoridades de Amsterdã não aceitaram baseadas em que não havia tal profissão. E, acredite ou não, no campo “profissão” de meu registro de casamento está o título ridículo “físico teórico”!
            Demais para a morosidade com a qual eu vi a profissão de programação emergir em meu país. Desde então eu tenho viajado pelo mundo e fico com a impressão de que nos outros países, a menos de um possível deslocamento de datas, as características do surgimento têm sido as mesmas.
            Deixe-me tentar capturar a situação naquele tempo em mais detalhe na esperança de obter um melhor entendimento da situação de hoje. Enquanto prosseguimos a nossa análise devemos ver como os equívocos comuns sobre a verdadeira natureza da tarefa de programação podem ser remontados àquele passado agora distante.
            Os primeiros computadores eletrônicos eram todos únicos, cópias de uma mesma máquina, eram encontrados em ambientes com excitante aroma de um laboratório experimental. Uma vez imaginados, sua realização era um tremendo desafio para a tecnologia de eletrônica então disponível e uma coisa é certa: não se pode negar a coragem dos grupos que decidiram tentar construir essas fantásticas peças de equipamento. Porque fantásticas peças de equipamento eles eram; em retrospecto, é de se pasmar que essas primeiras máquinas tenham conseguido funcionar, pelo menos por alguns momentos. O problema aflitivo era conseguir e manter a máquina disposta ao trabalho. A preocupação com os aspectos físicos da computação reflete-se nos nomes das primeiras sociedades científicas da área, tais como “Association  for Computing Machinery” ou “ British Computer Society”, nomes esses nos quais existe referência explícita ao equipamento físico.
            E o programador? Bem, para dizer a verdade, ele era raramente noticiado. Em primeiro lugar, essas máquinas eram tão grandes que não se podia movê-las e além disso requeriam tal extensiva manutenção que era bastante natural que o lugar onde as pessoas treinavam a usá-las fosse o mesmo laboratório onde elas eram desenvolvidas. Em segundo lugar, o trabalho do programador, um tanto invisível, não possuía nenhum atrativo: você podia mostrar a máquina aos visitantes e isso era várias ordens de magnitude mais espetacular que algumas folhas de codificação. Porém o mais importante era que o próprio programador tinha uma visão modesta de seu trabalho: seu trabalho derivava toda sua significância da existência daquela maravilhosa máquina; como ela era singular, ele sabia perfeitamente que seus programas tinham significância apenas local, e também porque era patente e óbvio que essa máquina teria vida útil limitada, ele sabia que muito pouco de seu trabalho teria um valor duradouro.
            Finalmente há ainda outra circunstância que tinha uma profunda influência na atitude do programador para com o seu trabalho: por um lado, além de ser pouco confiável, sua máquina era usualmente muito lenta e dotada de memória muito pequena, isto é: ele encarava um sapato apertado, enquanto, por outro lado, seu código de ordens, usualmente um tanto excêntrico, deveria prover facilidade para as construções mais inesperadas. Naquele tempo era freqüente o programador hábil sentir uma imensa satisfação intelectual com os truques astutos através dos quais ele planejava obter o impossível, dadas as restrições de seu equipamento.
            Duas opiniões sobre programação datam dessa época. Vou mencioná-las agora e retornarei a elas mais tarde. A primeira era a de que um programador realmente competente deveria ter destreza enigmática e gostar muito de truques inteligentes; a outra sustentava que programar nada mais era que otimizar a eficiência do processo computacional em uma ou outra direção. Essa segunda opinião resultou da circunstância freqüente de que, efetivamente, o equipamento disponível era um incômodo sapato apertado e naquele tempo era comum a expectativa ingênua de que uma vez que se dispusesse de máquinas mais possantes, a programação deixaria de ser um problema porque então o esforço para empurrar a máquina aos seus limites não mais seria necessário e isso era o que se tratava na programação, não era? No entanto, nas décadas seguintes alguma coisa completamente diferente aconteceu: máquinas mais possantes tornaram-se disponíveis, não apenas uma ordem de magnitude mais poderosa, mas várias ordens de magnitude mais poderosas. Mas, ao invés de encontrarmo-nos em um estado de eterna felicidade, com todos os nossos problemas de programação resolvidos, encontramo-nos atolados até o pescoço na crise da programação. Como? Há uma causa menor: em alguns aspectos a maquinaria moderna é basicamente mais difícil de se manusear do que a antiga. Primeiramente, passamos a contar com as interrupções de entrada e saída, ocorrendo em momentos imprevisíveis e irreproduzíveis; comparando com a velha máquina seqüencial, que pretendia ser um autômato inteiramente determinista, essa foi uma mudança dramática e muitas vezes os cabelos brancos dos programadores de sistema testemunham o fato de que não devemos falar levianamente dos problemas lógicos causados por essa faceta. Em segundo lugar, passamos a ter máquinas equipadas com memórias de vários níveis, trazendo problemas estratégicos de gerência que, a despeito de extensa literatura sobre o assunto, continuam a ser um tanto ardilosos.
            Demais para as complicações adicionais devidas às mudanças estruturais das máquinas atuais. Mas eu chamei a essa uma causa menor; a causa maior é... que as máquinas se tornaram várias ordens de magnitude mais poderosas! Colocando de uma forma brusca: enquanto não haviam as máquinas a programação não era problema; quando passamos a ter poucos e pequenos computadores a programação tornou-se um problema moderado, e agora que temos computadores gigantescos a programação passou a ser um problema igualmente gigantesco. Nesse sentido a indústria eletrônica não resolveu um único problema; ela criou problemas – ela criou o problema de como usar seus produtos. Em outras palavras: tão logo a potência das máquinas disponíveis cresceu por um fator maior que mil, a ambição da sociedade em aplicar essas máquinas cresceu em proporção, e o pobre programador acabou se situando nesse campo explosivo de tensão entre fins e meios.
            O aumento da potência da máquina aliado ao aumento até mais dramático de sua confiabilidade fez viáveis as soluções que o programador não ousara sonhar poucos anos atrás, e agora, poucos anos depois, ele tem de sonhar com elas e pior, tem de transformar esses sonhos em realidade. É um espanto que nos encontremos na crise da programação? Não, certamente que não e como você pode deduzir, era mesmo bastante previsível, mas o problema dos profetas menores, é claro, é que só depois de cinco anos você saberá realmente que eles estavam certos.
            Então, nos anos sessenta algo terrível aconteceu: os computadores da então chamada terceira geração apareceram. A literatura oficial revela que a minimização da razão preço/desempenho foi um dos maiores objetivos do projeto. Mas, se você considera como “desempenho” o ciclo de obediência dos vários componentes da máquina, nada lhe impedirá de terminar o projeto com um produto no qual a maior parte da meta “desempenho” é alcançada em atividades de arrumação de casa, de necessidade duvidosa. E, se a sua definição de preço é o preço a ser pago pela maquinaria, nada lhe impedirá de terminar o projeto com um produto cuja programação é terrivelmente árdua: por exemplo, o código de ordens pode ser tal que force ao programador ou ao sistema operacional decisões de amarração precipitadas apresentando conflitos que realmente não podem ser resolvidos. E, em larga extensão, essas possibilidades desagradáveis parecem ter se tornado realidade.
            Quando essas máquinas foram anunciadas e suas especificações funcionais tornaram-se conhecidas, muitos dentre nós se sentiram miseráveis. Pelo menos eu. Era razoável esperar que essas máquinas fossem inundar a comunidade de informática, portanto era vital que seu projeto fosse completo e perfeito o quando possível. Mas o projeto incorporava defeitos tão sérios que eu senti como um simples golpe atrasou o progresso da ciência da computação em pelo menos dez anos. Foi quando vivi a semana mais sombria de toda minha vida profissional.
            Talvez o aspecto mais tristonho é que, mesmo depois de tantos anos de experiências frustrantes, muita gente ainda acredita honestamente que alguma lei da natureza corrobora a asserção que as máquinas devem ser como elas são. Essa gente não questiona, se cala observando quantas máquinas foram vendidas e deduz dessa observação o falso senso de segurança de que, afinal de contas, o projeto não pode ter sido tão ruim. Mas, após inspecionar de perto, essa linha de defesa tem a mesma força de convicção do argumento que fumar faz bem à saúde, uma vez que tanta gente fuma.
            A propósito, lastimo não ser costume os jornais científicos da área de informática publicarem revisões de computadores recentemente anunciados da mesma maneira como nós revemos publicações científicas; rever as máquinas seria igualmente importante. E aqui eu faço uma confissão: em meados da década de sessenta eu escrevi tal revisão com intenção de submetê-la às comunicações da “Association for Computing Machinery”, mas, a despeito do fato dos colegas para quem enviei o texto terem estimulado sua divulgação, eu não ousei fazê-lo, temendo que as dificuldades para mim e para os editores fossem enormes. Essa supressão foi um ato de covardia de minha parte pelo qual me culpo sempre. As dificuldades que eu previa eram conseqüência da ausência de critérios que escolhera para aplicar, eu senti que minha revisão seria rejeitada ou descartada como “uma matéria de gosto pessoal”. Ainda penso que essas revisões seriam extremamente úteis e desejo vê-las aparecer, pois a aceitação de sua aparição seria um sinal concreto de maturidade da comunidade de informática.
            A razão que me chamou a atenção para a cena da maquinaria é que eu sinto que um dos aspectos mais importantes de qualquer ferramenta de computação é sua influência da maneira de pensar daqueles que treinam em seu uso; tenho ainda razões para acreditar que essa influência é muitas vezes mais forte do que é comumente assumida.
            Voltemos nossa atenção agora para o cenário da programação. Aqui a diversidade tem sido tão grande que tenho de restringir-me a umas poucas pedras angulares. Estou plenamente consciente das arbitrariedades da minha escolha e rogo-lhe não tirar nenhuma conclusão no que concerne à minha apreciação sobre os vários esforços que não serão aqui mencionados.
            No início havia apenas o “EDSAC” em Cambridge, Inglaterra, e eu acho impressionante que desde o começo a noção de biblioteca de sub-rotinas tenha desempenhado um papel central tanto no projeto daquela máquina como na maneira como ela deveria ser utilizada. Vinte e cinco anos são passados e o cenário da computação mudou dramaticamente, mas a noção de programação básica continua conosco e a noção da sub-rotina é ainda um conceito chave na programação. Devemos considerar a sub-rotina como uma das maiores invenções; ela sobreviveu a três gerações de computadores e deverá continuar assim, porque provê a implementação de um dos nossos modelos básicos de abstração. É lamentável que sua importância tenha sido subestimada no projeto dos computadores de terceira geração nos quais o grande número de registradores explicitamente identificados da unidade aritmética implica uma grande sobrecarga para o mecanismo da sub-rotina. Mas mesmo isso não matou o conceito da sub-rotina e devemos orar para que a mutação não demonstre ser hereditária.
            O segundo desenvolvimento na área da programação que eu gostaria de mencionar é o nascimento do FORTAN. Naquele tempo, foi um projeto de grande temeridade e o pessoal responsável por ele merece toda a nossa admiração. Seria absolutamente injusto culpá-lo pelas omissões que só se tornaram aparentes após uma década ou mais de utilização extensiva. Grupos com uma boa visão de futuro de dez anos são raros! Em retrospecto, devemos avaliar o FORTRAN como uma técnica de codificação bem sucedida, mas com muito pouca ajuda efetiva na conceituação, ajuda essa agora tão urgentemente necessária que é chegado o tempo de considerá-lo obsoleto. Quanto mais cedo pudermos esquecer que o FORTRAN existiu melhor, pois como veículo de pensamento ele não é mais adequado, gasta nossa massa cinzenta e é muito arriscado e portanto muito caro para se usar. O fado trágico do FORTRAN tem sido sua grande aceitação, encadeando mentalmente milhares e milhares de programadores em nossos erros do passado. Rezo diariamente para que meus companheiros programadores possam encontrar os meios de se libertar da praga da compatibilidade.
            O terceiro projeto que eu não gostaria de deixar passar despercebido é o LISP, um fascinante empreendimento de natureza completamente diferente. Com alguns princípios básicos em seu fundamento, tem mostrado notável estabilidade. Além disso, LISP tem sido portador de um número considerável de nossas mais sofisticadas aplicações de computador. LISP foi descrito com jocosidade como sendo “a maneira mais inteligente de se empregar mal o computador”. Considero essa descrição um grande elogio por transmitir o pleno sabor da liberação: auxiliou nossos mais talentosos companheiros a pensar em raciocínios previamente impossíveis.
            O quarto projeto a ser mencionado é o ALGOL 60. Enquanto até hoje os programadores FORTRAN procuram entender sua linguagem de programação em termos da implementação específica com a qual trabalham. − daí prevalecerem as descargas de memória em hexadecimal, enquanto a definição de LISP é ainda uma curiosa mistura do que a linguagem significa e como o mecanismo funciona, o famoso relatório sobre a Linguagem Algorítmica ALGOL 60 é o fruto de um esforço genuíno de levar a abstração um passo a frente a definir uma linguagem de programação de uma maneira independente da implementação. Pode-se argüir que nesse aspecto seus autores foram tão exitosos que criaram dúvidas sérias se afinal a linguagem pode ser implementada! O relatório demonstrou gloriosamente a força do método formal BNF, agora conhecido como “Backus – Naur Form” e do fraseado cuidadoso, pelo menos quando usado por alguém tão brilhante quanto Peter Naur. Creio que poucos documentos pequenos como esse tiveram tão profunda influência na comunidade de informática. A facilidade com a qual, nos anos seguintes, os nomes “ALGOL” e “tipo ALGOL” foram usados como marca registrada desprotegida, para denotar as características de alguns projetos experimentais, é um elogio um tanto chocante à postura do ALGOL. O vigor da BNF como dispositivo de definição é responsável pelo que considero uma fraqueza da linguagem: uma super elaborada e não muito sistemática sintaxe que agora poderia ser comprimida em poucas páginas. Com a BNF o relatório sobre a Linguagem Algorítmica ALGOL 60 seria muito menor. Além disso, tenho minhas dúvidas quanto ao mecanismo de parâmetros do ALGOL 60: ele permite ao programador tal liberdade de combinação que seu uso correto requer forte disciplina. Além de caro para implementar é perigoso de se usar.
            Finalmente, embora o assunto não seja agradável, devo mencionar o PL/I, uma linguagem de programação cuja documentação de definição é de um tamanho e de uma complexidade espantosos. Usar o PL/I é como pilotar um avião com 7000 botões, chaves e manivelas na cabine. Absolutamente não vejo como manter o domínio mental sobre nossos programas em crescente desenvolvimento, quando a linguagem de programação barroca − nossa ferramenta básica, veja você! − já escapa ao nosso controle intelectual. Se devo descrever a influência que o PL/I pode ter em seus usuários, a metáfora mais adequada que me vem à mente é de uma droga. Lembro-me bem de uma palestra em defesa do PL/I feita num simpósio sobre linguagens de programação de alto nível, por um sujeito que se considerava um de seus devotos usuários. Após uma hora de louvor ao PL/I, ele conseguiu pedir a adição de mais ou menos 50 novas facetas, sem imaginar que a principal fonte de seus problemas poderia muito bem ser o fato da linguagem já possuir tantas. O palestrante exibia todos os sintomas depressivos do vício, reduzido ao estado de estagnação mental, no qual ele podia apenas pedir mais, mais, mais...
            Se FORTAN tem sido chamado uma desordem infantil, PL/I completo, com suas características de um tumor perigoso, poderia vir a ser uma doença fatal.
            Demais para o passado. Mas não há lugar para os erros cometidos a não ser que possamos extrair lições. Na verdade, eu acho que já aprendemos tanto que dentro de alguns anos a programação pode vir a ser uma atividade completamente diferente do que ela tem sido até então; tão diferente que o melhor é nos prepararmos para o choque. Deixe-me esboçar um possível futuro; à primeira vista essa previsão da programação já em futuro próximo pode lhe impressionar como sendo fantástica. Deixe-me, portanto, colocar as considerações que podem levar à conclusão de ser essa visão uma possibilidade muito real.
            A visão é que, antes da virada da década de setenta nós conseguiremos projetar e implementar o tipo de sistema que agora força a nossa habilidade de programação com um custo igual a uma pequena porcentagem em pessoa-ano do custo atual e além disso, esses sistemas serão virtualmente livres de erro! Esses dois melhoramentos andam juntos. Nesse aspecto, um programa é bem diferente de muitos outros produtos onde, como regra geral, o aumento de qualidade implica um preço maior. Aqueles que realmente querem programas confiáveis descobrirão que eles têm de encontrar os meios de evitar a maioria dos erros desde o início e, como resultado, o processo da programação tornar-se-á mais barato; se você quer programadores mais efetivos, você descobrirá que eles não devem gastar o seu tempo depurando − eles devem é não introduzir erros desde o início. Em outras palavras, ambas as metas indicam a mesma mudança.
            Uma mudança tão drástica em tão curto período de tempo seria uma revolução e, para aqueles que baseiam suas expectativas de futuro em extrapolação suave do passado − apelando para alguma lei (que não foi escrita) sobre a inércia cultural e social − a chance dessa mudança drástica acontecer deve ser desprezível. Mas nós sabemos muito bem que algumas vezes as revoluções acontecem! E quais são as chances desta?
            Três grandes condições têm de ser satisfeitas: o mundo inteiro deve reconhecer a necessidade da mudança; em segundo lugar a necessidade econômica para ela deve ser suficiente forte e, em terceiro lugar, a mudança tem de ser viável tecnicamente. Deixe-me discutir essas três condições na ordem acima.
            No que concerne ao reconhecimento da necessidade de maior confiabilidade nos programas, eu espero que não haja mais discordância. Há alguns anos atrás era diferente: falar em crise de programação era blasfemar. A reviravolta foi a “Conference on Software Engineering” em Garmisch − outubro de 1968, quando foi admitida pela primeira vez a existência da crise. Hoje é amplamente reconhecido que o projeto de qualquer sistema grande e sofisticado tende a ser um trabalho muito difícil; as pessoas responsáveis por tais empreendimentos continuam preocupadas com o aspecto da confiabilidade e é natural que assim seja. Em suma, nossa primeira condição parece estar satisfeita.
            Vejamos agora o requisito econômico. Atualmente é freqüente a opinião de que na década de sessenta a programação foi uma profissão muito bem paga e que nos próximos anos o salário do programador deve cair. Usualmente essa opinião é expressa em conexão com a recessão, mas poderia ser um sintoma de algo diferente e saudável, isto é: que talvez os programadores da década passada não tenham realizado um trabalho tão bem feito quanto deviam. A sociedade ficou insatisfeita com o desempenho dos programadores e de seus produtos. Mas há um fator muito mais ponderável: na situação presente é bastante comum que o preço a ser pago para o desenvolvimento dos programas de um sistema específico seja da mesma ordem de magnitude do preço da maquinaria necessária e a sociedade tende a aceitar isso. Mas os fabricantes nos dizem que na próxima década os preços da maquinaria devem ser reduzidos por um fator de dez. Se o desenvolvimento de programas continuasse a ser o mesmo processo tosco e caro como é agora, as coisas ficariam completamente desbalanceadas. Você não pode esperar que a sociedade aceite isso, portanto nós temos de aprender a programar uma ordem de magnitude mais efetivamente. Colocando em outra forma: enquanto as máquinas eram o maior item no orçamento, a profissão de programação ia se virando com suas toscas técnicas, mas esse guarda-chuva está fechando rapidamente. Em síntese, também a nossa segunda condição parece estar satisfeita.
            E agora a terceira condição: é tecnicamente viável? Eu penso que pode ser e dou seis argumentos que suportam essa opinião.
            Um estudo da estrutura de programas revelou que os programas, aí incluídas as alternativas para a mesma tarefa e de mesmo conteúdo matemático, podem diferir tremendamente no que concerne a seu manejo intelectual. Foram descobertas regras cuja violação debilitará seriamente ou destruirá totalmente a maneabilidade dos programas. Essas regras são de dois tipos. As do primeiro tipo podem ser facilmente impostas mecanicamente, isto é, por uma escolha adequada da linguagem de programação. Como exemplos, estão a exclusão da instrução “GO TO” e dos procedimentos com mais de um parâmetro de saída. Para aquelas do segundo tipo, eu pelo menos − mas pode ser por falta de competência de minha parte − não vejo como impor mecanicamente, uma vez que seria necessário um demonstrador automático de teoremas, de cuja existência eu não tenho prova. Portanto, até o momento e quiçá para sempre, as regras do segundo tipo se apresentam como elementos de disciplina requeridos ao programador. Algumas que tenho em mente são tão claras que podem ser ensinadas e não há como argumentar sua violação por um dado programa. Um exemplo é a requisição de que nenhum laço deve ser escrito sem explicitar a prova se seu término ou sem estabelecer a relação cuja invariância não será destruída pela execução repetida das instruções.
            Sugiro que fiquemos restritos ao projeto e implementação de programas intelectualmente manejáveis. Se alguém teme que essa restrição seja por demais severa, que não possamos conviver com ela, posso tranqüilizar: a classe de programas intelectualmente manejáveis é ainda suficientemente rica de modo a conter muitos programas realistas para qualquer problema capaz de solução algorítmica. Nós não devemos esquecer que nossa atribuição não é fazer programas e sim criar classes de computações que exibirão um comportamento desejado. A sugestão de nos restringirmos aos programas intelectualmente manejáveis é a base dos dois primeiros argumentos.
            O primeiro é o de que como o programador necessita considerar apenas os programas intelectualmente manejáveis, sua escolha de alternativas fica muito fácil.
            O segundo argumento é o de que uma vez decididos a nos restringirmos aos sub-conjunto de programas intelectualmente manejáveis, alcançamos de uma vez por todas uma redução drástica no espaço de soluções a ser considerado. E esse argumento é distinto do primeiro.
            O terceiro argumento é baseado na abordagem construtiva ao problema da correção de programas. Hoje em dia, uma técnica usual é a de fazer o programa e então testá-lo. Entretanto o teste de programas pode ser uma maneira efetiva de mostrar a presença de erros, contudo é irremediavelmente inadequado para mostrar a sua ausência. A única maneira efetiva de se elevar significantemente o nível de confiabilidade de um programa é dar uma prova convincente de que ele está correto. Mas não se deve fazer o programa e depois provar a sua exatidão, porque então o requerimento de proporcionar a prova apenas aumentaria a aflição do pobre programador. Pelo contrário, o programador deve deixar a prova de exatidão e o crescimento do programa andarem juntos. O terceiro argumento é baseado essencialmente nessa observação: se, primeiramente, a pessoa se questiona quanto a estrutura de uma prova convincente e, uma vez encontrada, constrói um programa satisfazendo os requerimentos da prova, então essas asserções de correção passam a ser um guia heurístico muito efetivo. Por definição, essa abordagem é aplicável apenas quando nos restringimos aos programas intelectualmente manejáveis, mas ela nos proporciona os meios efetivos para encontrar uma solução satisfatória entre eles.
            O quarto argumento tem a ver com o modo pelo qual a quantidade de esforço intelectual necessária para escrever um programa depende de seu tamanho. Há quem sugira a existência de alguma lei da natureza que nos diz que a quantidade necessária de esforço intelectual cresce com o quadrado do tamanho do programa. Mas, felizmente, ninguém conseguiu provar essa lei. E isso porque ela não é necessariamente verdadeira. Nós sabemos que a única ferramenta mental com a qual uma porção finita de raciocínio pode cobrir uma miríade de casos é chamada “abstração”; como resultado, a exploração efetiva de seus poderes de abstração deve ser vista como a principal atividade de um programador competente. Em relação a isso, vale a pena assinalar que o propósito da abstração não é ser vago, mas criar um novo nível semântico no qual é possível a precisão absoluta. Evidentemente já tentei encontrar a causa fundamental que estaria impedindo nosso mecanismo de abstração de ser suficientemente eficaz. Mas, a despeito das tentativas não encontrei tal causa. Como resultado assumo − e a experiência até então corrobora − que pela aplicação adequada de nossos poderes de abstração, o esforço requerido para conceber ou entender um programa não cresce necessariamente mais do que proporcionalmente ao seu tamanho.       
            Um sub-produto dessas investigações pode ser de grande significação prática e é, de fato, a base de meu quarto argumento. O sub-produto foi a identificação dos modelos de abstração que exercem um papel vital em todo processo de composição de programas. Já se conhece o bastante a respeito desses modelos de abstração a ponto de se poder dedicar uma palestra a cada um deles. O que a familiaridade e o conhecimento consciente desses modelos de abstração implicam despontou em mim quando realizei que, fossem eles conhecidos a quinze anos atrás, a passagem da BNF para os compiladores regulados por sintaxe, por exemplo, levaria alguns minutos ao invés de alguns anos. Portanto considero nosso conhecimento recente dos modelos vitais de abstração como o quarto argumento.
            Agora, o quinto. Este se relaciona com a influência da ferramenta que estamos tentando usar nos nossos hábitos de pensar. Observo uma tradição cultural que provavelmente tem suas raízes na Renascença, de ignorar essa influência, de encarar a mente humana como suprema e autônoma mestra de seus artefatos. Mas se começo a analisar meus hábitos de pensar e de meus companheiros, seres humanos, eu chego, querendo ou não, a uma conclusão completamente diferente, a saber: as ferramentas que estamos tentando usar e a linguagem ou notação que usamos para expressar ou registrar nossos pensamentos são os principais fatores que determinam o que podemos pensar ou expressar! A análise da influência que as linguagens de programação têm nos hábitos de pensamentos de seus usuários, e o reconhecimento que agora a massa cinzenta é o nosso recurso mais escasso, juntos, dão-nos uma nova coleção de medidas para comparar os méritos relativos das várias linguagens de programação. O programador competente é plenamente consciente do tamanho estritamente limitado de sua própria cabeça; portanto ele aborda a tarefa programação com muita humildade e dentre outras coisas ele evita como a praga os truques astutos. No caso de uma conhecida linguagem conversacional, eu tenho dito que tão logo a comunidade é equipada com o terminal, um fenômeno específico ocorre, cujo nome é bem estabelecido; é chamado “uma linha”. Tal fenômeno assume duas formas: um programador coloca um programa de uma linha na mesa de outro e diz orgulhosamente o que o programa faz acrescentando “você consegue codificá-lo com menos símbolos?” ─ como se isso fosse de alguma relevância conceitual ─ ou diz apenas: “adivinhe o que ele faz!”. Dessa observação temos de concluir que essa linguagem, como ferramenta, é um convite aberto aos truques astutos; embora seja precisamente isso que explicaria seu atrativo, isto é, para aqueles que gostam de mostrar quão inteligentes são, considero uma das coisas mais condenáveis que podem ser ditas a respeito de uma linguagem de programação.
            Outra lição que devemos extrair do passado recente é que o desenvolvimento das linguagens de programação “mais ricas” ou “mais poderosas” foi um equívoco no sentido de que essas monstruosidades barrocas, esses conglomerados de idiossincrasias são realmente intratáveis, mecânica e mentalmente. Vejo um grande futuro para as linguagens de programação muito sistemáticas e muito modestas. Por “modesta” quero dizer que não apenas a cláusula “FOR” do ALGOL 60 mas mesmo o laço “DO” do FORTRAN devem ser rejeitados por serem demasiado barrocos. Fiz uma pequena experiência de programação com voluntários realmente experientes e alguma coisa não intencionada e um tanto inesperada aconteceu. Nenhum deles encontrou a solução óbvia e mais elegante. Após cuidadosa análise ficou claro que isso tinha uma causa comum: a noção de repetição estava tão intimamente ligada à idéia de uma variável de controle associada a ser incrementada que eles ficavam bloqueados mentalmente para enxergar o óbvio. Suas soluções eram ineficientes, desnecessariamente difíceis de se entender e tomaram um bom tempo para serem encontradas. Foi uma experiências reveladora e chocante para mim.
            Finalmente, em um aspecto, espera-se que as linguagens de programação de amanhã diferirão grandemente das que usamos agora: elas devem levar, numa extensão muito maior do que até então, a uma reflexão sobre a estrutura daquilo que descrevemos: as abstrações necessárias para traduzir a complexidade do que estamos projetando. Isso é suficiente no que tange à grande adequação das ferramentas futuras, que foi a base do quinto argumento.
            A propósito, gostaria de avisar àqueles que identificam a dificuldade da tarefa de programação com o esforço contra as insuficiências de nossas ferramentas correntes, porque eles podem concluir que uma vez nossas ferramentas se tornem muito mais adequadas a programação não mais será um problema. Programar continuará a ser muito difícil pois quando nos libertamos desses incômodos circunstanciais nos dedicaremos aos problemas que hoje estão muito além de nossa capacidade de programação.
            Você pode questionar o meu sexto argumento, pois não é fácil colher evidências experimental para seu suporte, fato que não me impede de acreditar em sua validade. Até agora eu não mencionei a palavra “hierarquia”, mas penso ser este um conceito chave para todos sistemas que incorporem solução passível de se fatorar com exatidão. Poderia mesmo ir um passo a frente e fazer uma cláusula de fé a respeito, isto é: que os únicos problemas que realmente podemos resolver de uma maneira satisfatória são aqueles que finalmente admitem solução passível de ser fatorada com exatidão. A princípio essa visão das limitações humanas pode chocar como um tanto depressiva de nossas dificuldades, mas eu não encaro assim. Pelo contrário, a melhor maneira de aprender a conviver com as nossas limitações é conhecê-las. Sendo suficientemente modestos para tentar apenas as soluções passíveis de fatoração, porque os outros esforços escapam à nossa compreensão intelectual, devemos fazer o possível para evitar aquelas interfaces que enfraquecem a nossa habilidade de fatorar o sistema de uma maneira proveitosa. É de se esperar que isso levará repetidamente à descoberta que um problema inicialmente intratável pode, afinal, ser fatorado. Qualquer um que tenha visto como a maioria das perturbações de compilação na fase chamada “geração de código” deriva de propriedades cômicas do código de ordens saberá um exemplo do que tenho em mente. A maior aplicabilidade das soluções bem fatoradas é meu sexto e último argumento da viabilidade técnica da revolução que pode acontecer nessa década.
            Em princípio eu deixo para você decidir que peso atribuir às minhas considerações, reconhecendo que não posso forçar ninguém a compartilhar minhas crenças. Como em toda revolução séria, esta provocará uma violenta oposição e é natural indagar onde estarão as forças conservadoras que tentarão neutralizar tal desenvolvimento. Não espero que estejam no mundo dos negócios nem mesmo nos negócios de computação, mas nas instituições educacionais que proporcionam o treinamento atual e naqueles grupos conservadores de usuários que consideram seus velhos programas tão importantes a ponto de não valer a pena melhorá-los ou mesmo reescrevê-los. Relacionado com isso, é triste observar que em muitos campus de universidade a escolha do local para o centro de processamento de dados tem sido determinada pelas demandas de algumas aplicações estabelecidas, porém caras, menosprezando a questão de quantos milhares de pequenos usuários sofrerão com essa escolha. É comum a física de alta energia chantagear a comunidade científica com o preço de seu equipamento experimental.
            A resposta mais fácil, é claro, é a negação categórica de viabilidade técnica, mas receio que os argumentos necessários para isso têm de ser muito fortes. Nada garante que o teto intelectual do programador médio de hoje impedirá a revolução de acontecer: com outros programando muito mais efetivamente, ele está sujeito a sair de cena de qualquer maneira.
            Podem haver também impedimentos políticos. Mesmo que nós saibamos como educar profissionalmente o programador de amanhã, ninguém nos garante que a sociedade em que vivemos permita fazê-lo. O primeiro efeito de ensinar uma metodologia − mais que disseminar conhecimento − é aumentar a capacidade do já capaz, assim ampliando a diferença em inteligência. Numa sociedade na qual o sistema educacional é usado como instrumento para o estabelecimento de uma cultura homogeneizada, na qual a nata é impedida de galgar o topo, a formação de programadores competentes poderia ser politicamente desagradável.
            Deixe-me concluir. Os computadores já estão conosco por um quarto de século. Eles causaram forte impacto em nossa sociedade por sua capacidade de ferramenta, mas por essa capacidade a sua influência não será mais do que uma encapeladura na superfície de nossa cultura, comparada com a influência muito mais profunda que eles terão por sua capacidade de desafio intelectual, sem precedente na história cultural da humanidade.
            Os sistemas hierárquicos parecem ter a propriedade de que alguma coisa vista como entidade indivisível em um nível é considerada objeto composto no próximo nível de maior detalhe; como resultado, a granulação natural de espaço ou tempo aplicável a cada nível diminui de uma ordem de magnitude quando deslocamos a atenção de um nível para o próximo. Entendemos a parede em termos de tijolos, tijolos em termos de cristais, cristais em termos de moléculas, etc. Assim, o número de níveis que podem ser distintos significativamente em um sistema hierárquico é algo proporcional ao logaritmo da razão entre a granulação maior e menor; por conseguinte, a menos que essa razão seja muito grande, não teremos muitos níveis. Na programação de computadores nosso bloco básico de construção tem uma granulação temporal associada da ordem de um microsegundo, entretanto nosso programa pode levar horas processando. Não conheço outra tecnologia que cubra uma razão de 1010  ou mais; o computador, em virtude de sua fantástica velocidade, parece ser o primeiro a nos proporcionar o ambiente onde os artefatos altamente hierarquizados são possíveis e necessários.
            Esse desafio, a confrontação com a tarefa de programação, é único e essa nova experiência pode nos ensinar muito a respeito de nós mesmos. Ele deve aprofundar nosso entendimento dos processos de projetar e criar, ele deve dar-nos um controle melhor no que concerne à tarefa de organizar nossos pensamentos. Se ele não faz isso, então, a meu ver, não merecemos o computador.
            Ele já nos ensinou algumas lições e a que eu escolhi para salientar nesse ponto é a seguinte: podemos fazer um trabalho muito melhor, desde que abordemos a tarefa com uma apreciação ampla de sua tremenda dificuldade, desde que adiramos às linguagens de programação modestas e elegantes, desde que respeitemos as limitações intrínsecas da mente humana e abordemos a tarefa como programadores muito humildes.

Nenhum comentário: