Pesquisar

quarta-feira, 28 de outubro de 2009

Ser programador: Paradigmas de Programação - parte 3

Continuando a série ser programador, falaremos sobre os paradigmas de programação, buscando mostrar características de cada um destes paradigmas. Acreditamos que é importante conhecer como cada paradigma trabalha para que possamos escolher a melhor opção para um dado problema. No caso de quem quer ser programador, é importante conhecer bem o tema para não se enganar pensando que existe alguma linguagem que é solução para qualquer problema.



Nos artigos anteriores procuramos conceituar algoritmos e mostrar a evolução da computação, passando pelas linguagens de programação. Estas linguagens permitem que escrevamos a algo que a máquina será capaz de entender. Mesmo que de forma não direta, é por meio das linguagens de programação que nos comunicamos com o computador. É importante lembrar que o que escrevemos em uma linguagem de programação (usaremos a partir daqui apenas o termo linguagem) não é entendido pela máquina. É preciso que o texto seja convertido na linguagem que ela entende: a linguagem de máquina (composta apenas de zeros e uns). Sem querer mostrar agora como isto funciona (deixemos para outro post), é interessante saber que existe uma conversão do texto da linguagem para um texto na linguagem do computador. Este processo é chamado de tradução (compilando o texto ou interpretando o texto).

Para entender as diferenças entre as linguagens, isto deve ficar claro: excetuando a linguagem de máquina - entendida diretamente pelo processador - ou a lingugagem de máquina que possui um processo simplificado para ser entendida pela máquina, todas as demais linguagens são traduzidas para a linguagem do computador para que possam ser executadas. Assim, é preciso que o texto seja convertido da linguagem de programação (que é mais próxima da nossa linguagem = alto nível) para instruções em linguagem da máquina (baixo nível).  Este processo pode ser, basicamente, de dois modos: interpretado ou compilado.

Pela própria semântica das palavras, já podemos entender como funciona cada um destes processos. O intérprete é aquele que intermedia a conversa entre falantes de línguas diferentes, ouvindo parte da mensagem, convertendo e transmitindo. O interpretador na programação funciona de forma semelhante. Ele converte uma instrução que está na linguagem de alto nível para a linguagem do computador. Faz isto comando por comando e, se for preciso passar pelo mesmo comando novamente, faz o processo de tradução novamente. O interpretador precisa "ler" o texto original do programa para converter passo a passo para a máquina.

Já o compilador - que sabemos ser o processo de reunir em coleção, juntar - converte todo o texto em um outro texto na linguagem da máquina. Ele, então, gera um novo texto (programa objeto) com todas as instruções que estão contidas no texto original (programa fonte) na linguagem do computador. Claro que alguns processos complementares são necessários para que este código de máquina realmente funcione, pois é preciso que tenhamos as instruções administrativas (como carregar o código, onde começa a executar e algumas bibliotecas, tudo fornecido pelo sistema operacional). Ao final de todo o processo teremos mais um arquivo ainda: o programa executável. Este sim, poderá ser executado por um computador, geralmente do mesmo tipo que o compilou.

Em princípio, um programa interpretado é mais lento do que um compilado. Isto porque o interpretador também é um programa que está em execução e tem a tarefa de traduzir passo a passo. Somente após a conclusão da execução de uma instrução o interpretador passará para a execução da próxima. Se precisar repetir uma parte do programa, fará a tradução novamente. Já o compilador converte todo o texto de uma só vez, gerando um outro arquivo. O computador, então, não precisa aguardar a tradução e, caso execute uma parte novamente, esta já está traduzida. Além disso, como o compilador escreve o código para ser entendido diretamente pelo processador, o código é otimizado e, consequentemente mais rápido. O iterpretador, uma vez que traduz na hora da execução, utiliza a idéia de ter um programa-interpretador para cada tipo de processador e, assim, possibilitar que um mesmo código fonte seja interpretado em diferentes computadores sem a necessidade de processos adicionais.

Temos, até aqui, que os compiladores geram - normalmente - programas mais rápidos, enquanto os interpretadores permitem maior portabilidade. Eu quase me esqueci de falar sobre as linguagens mistas neste processo. Elas são inicialmente compiladas para uma linguagem intermediária (não é lingugagem de máquina) e depois este código intermediário é interpretado. Buscam, desta forma, aliar a velocidade do compilador com a portabilidade do interpretador.

Além desta variável - Interpretada ou Compilada - existem diversas outras caracaterísticas das linguagens que são importantes para a análise do potencial de cada uma. Mas, antes, devemos estudar os paradigmas de programação, os modelos de programação. É importante conhecer os diferentes modelos e as vantagens e desvantagens de cada um.

Os principais paradigmas são:

1) programação imperativa

2) Programação orientada a objetos

3) programação funcional

4) programação declarativa ou lógica

O modelo Imperativo é baseado na perspectiva do computador: a execução sequencial de comandos e o uso de dados são conceitos baseados no modo como os computadores executam programas no nível de linguagem de máquina. A sequência de comandos define o processo (ou
procedimento) a seguir e permite a mudança de estado de variáveis de atribuição. Implementada com base na máquina de von Neumann. As variáveis do programa (e o número da instrução em execução) descrevem o estado da computação a qualquer instante.
Este modelo é o predominante. As LPs imperativas são de fácil tradução. Um programa imperativo é equivalente a uma seqüência de modificações de locações de memória. Exemplos de Linguagens Imperativas: FORTRAN, COBOL, ALGOL 60, APL, BASIC, PL/I, SIMULA 67, ALGOL 68, PASCAL, C, MODULA 2, ADA.

São linguagens eficientes, uma vez que embutem o modelo "Von Neumann" (modelo de máquina). Outra vantagem é que é o modelo dominante e bem estabelecido.

Principais problemas:

  • Não são adequadas à computação em paralelo (pois estão baseadas em execução sequencial).

  • Baixa produtividade na programação: Grande esforço do programador no controlo do estado do programa (valores das variáveis).

  • Difícil legibilidade.

  • Erros introduzidos durante manutenção.

  • descrições demasiadamente operacionais focalizam o como e não o que deve ser feito.


O modelo Orientado a Objetos focaliza mais o problema, em que pese é um subtipo do modelo imperativo. A grande diferença entre os dois modelos está na concepção e modelagem do sistema. Um programa OO é equivalente a objetos que mandam mensagens entre si. Os objetos do programa equivalem aos objetos da vida real (problema). Ppdemos dizer que a abordagem OO é importante para resolver muitos tipos de problemas através de simulação. A primeira linguagem OO foi Simula, desenvolvida em 1966 e depois refinada em Smalltalk. Existem algumas linguagens híbridas: Modelo Imperativo mais características de Orientação a Objetos (OO). Ex: C++.
No modelo OO a entidade fundamental é o objeto. Objetos trocam mensagens entre si e os problemas são resolvidos por objetos enviando mensagens uns para os outros.

Linguagens Orientadas a Objeto: SMALL TALK, SIMULA, RUBY.

Além das vantagens do modelo imperativo, podemos acrescentar a modularidade, reusabilidade e extensibilidade. Os problemas são os mesmos do paradigma imperativo, amenizados pelas facilidades de estruturação deste modelo.

O modelo Funcional focaliza o processo de resolução do problema. A visão funcional resulta num programa que descreve as operações que devem ser efetuadas para resolver o problema. Elas descrevem o conhecimento de um problema através da declaração de funções (instruções funcionais de alto nível). As funções são aplicadas recursivamente ou por composição e tem como resultado valores. A parte algorítmica e procedimental é (idealmente) suprimida: modela-se apenas as formulações matemáticas da computabilidade.

São exemplos clássicos o LISP e o APL. A linguagem Haskell é também uma linguagem funcional. Durante meu mestrado estudei uma linguagem funcional pura: o Gofer, que é uma linguagem muito interessante.

Vantagens do paradigma funcional:

  • Manipulação de programas mais simples: Prova de propriedades e Transformação (exemplo: otimização)

  • Concorrência explorada de forma natural


Problemas

  • “O mundo não é funcional!”

  • Implementações ineficientes

  • Mecanismos primitivos de Entrada/Saída e formatação


O modelo Declarativo ou Lógico está relacionado à perspectiva da pessoa: ele encara o problema de uma perspectiva lógica. Um programa lógico é equivalente à descrição do problema expressa de maneira formal, similar à maneira que o ser humano raciocinaria sobre ele. O problema é descrito em função de afirmações (asserções ou factos) e de regras sobre os objetos. Procurou-se possibilitar a total supressão da parte algorítmica e procedimental: cabe ao interpretador (ou compilador) encontrar os caminhos ou processos de resolução do problema. Alguns autores entendem que a programação em lógica estende o paradigma funcional, sendo que os programas e dados aparecem em conjunto.
Principal representante: PROLOG.

Por experiência, trata-se de uma linguagem extremamente poderosa. Muito utilizada em inteligência artificial tal é a facilidade de descrever processos complexos que, em outros paradigmas, seriam necessários milhares de linhas de código. Tem, obviamente, problemas com a velocidade, dado que a estrutura do computador não é adequado para as estruturas declarativas.

Vantagens

  • Em princípio, todas do paradigma funcional

  • Permite concepção da aplicação em um alto nível de abstração (através de associações entre E/S)


Problemas

  • Em princípio, todos do paradigma funcional

  • Linguagens usualmente não possuem tipos,  nem são de alta ordem


Tendência

Particularmente acredito que as linguagens tendem a integrar os paradigmas, combinando as facilidades de cada um, bem como as potencialidades. Para ser um bom programador é preciso entender o funcionamento de cada linguagem internamente (para que se possa visualizar as características a serem exploradas para a solução do problema). O melhor, neste caso, é conhecer o paradigma ao qual a linguagem pertence, o que facilita a identificação das potencialidades. Note, entretanto, que as linguagens de um mesmo paradigma possuem características distintas, mas a filosofia de implementação será a mesma.

Além disso, devemos considerar outros fatores importantes para a escolha, como: ambiente de implementação (internet, desjtop, celular); custo para implantação (será preciso comprar algo para que a solução seja implementada?); curva de aprendizado (se não conhecemos a linguagem, será que ela é fácil de aprender?); custo de manutenção (corrigir defeitos ou realizar evoluções); pessoal qualificado; suporte etc.

Imagine as linguagens como uma gama de livros dispostas em uma estante. Pense sempre que estes "livros" estão classificados por paradigma. Agora, para cada problema devemos escolher o livro mais adequado para a solução e isto só será definido após uma ampla análise do caso em questão. O bom programador é aquele que é capaz de reconhecer que uma determinada linguagem não se adapta bem ao problema estudado e consegue identificar quais seriam as opções disponíveis no mercado.

Minha dica, aqui, é: aprenda algoritmos, pois eles serão sempre a base do raciocínio aplicável à programação e estude as linguagem com uma visão de suas características, dos paradigmas de programação. Com o tempo, você saberá escolher a linguagem na qual pretende tornar-se um "expert", bem como perceber os movimentos do mercado. De pronto, sabemos que esta área requer dedicação, então, comece agora mesmo.

O modelo Imperativo é baseado na perspectiva do computador: a execução seqüencial de comandos e o uso de dados são conceitos baseados no modo como os computadores executam programas no nível de linguagem de máquina. Este modelo é o predominante. As LPs imperativas são de fácil tradução. Um programa imperativo é equivalente a uma seqüência de modificações de locações de memória.


Linguagens Imperativas: FORTRAN, COBOL, ALGOL 60, APL, BASIC, PL/I, SIMULA 67, ALGOL 68, PASCAL, C, MODULA 2, ADA.



Nenhum comentário:

Postar um comentário