Programação imperativa

Na ciência da computação, programação imperativa é um paradigma de programação de software que descreve a computação como ações, enunciados ou comandos que mudam o estado (variáveis) de um programa.[1] Semelhante ao comportamento imperativo das linguagens naturais que expressam ordens, programas imperativos são uma sequência de comandos para o computador executar.

O termo é frequentemente usado em contraste com a programação declarativa, que se concentra no que o programa deve realizar sem especificar todos os detalhes de como o programa deve alcançar o resultado.[1]

Linguagens de programação que baseiam no modo imperativo são: Ada, ALGOL, Basic, C, PHP, Java,[2] Cobol, Fortran, Pascal, Python, Lua, Mathematica.

O nome do paradigma, Imperativo, está ligado ao tempo verbal imperativo, onde o programador diz ao computador: faça isso, depois isso, depois aquilo... Este paradigma de programação se destaca pela simplicidade, uma vez que todo ser humano, ao se programar, o faz imperativamente, baseado na ideia de ações e estados, quase como um programa de computador.

Máquina de Turing

O fundamento da programação imperativa é o conceito de Máquina de Turing, que nada mais é que uma abstração matemática que corresponde ao conjunto de funções computáveis.

A Máquina de Turing foi aprimorada por John Von Neumann a uma arquitetura de computadores que fundamenta os computadores construídos até hoje. Isso explica, em parte, o sucesso das linguagens que seguem esse paradigma em relação às demais. Nesta arquitetura( usada hoje nos microcomputadores comercializados), tanto os dados como os programas são armazenados na mesma memória, e a CPU que processa as instruções, é separada da memória. Dessa forma, os dados e instruções devem ser transportados da memória para a CPU e os resultados das operações realizadas na CPU devem ser devolvidos para a memória.

Origens editar

Linguagens imperativas têm uma história rica e variada. As primeiras linguagens de programação imperativas eram linguagens de máquina, com instruções simples mas de construção complexa. Instruções de máquina foram logo substituídos com linguagens de montagem que são essencialmente transliterações de código de máquina.

Fortran (FORmula TRANslation) foi a primeira linguagem de alto nível para ganhar ampla aceitação. Ele foi projetado para aplicações científicas e contou com uma notação algébrica, tipos, subprogramas, e entrada/saída formatada. Foi implementado em 1956 por John Backus na IBM especificamente para a máquina IBM 704. Execução eficiente foi uma grande preocupação, consequentemente, sua estrutura e comandos têm muito em comum com linguagens de montagem. FORTRAN ganhou ampla aceitação e continua a ser largamente utilizado na comunidade de computação científica.

COBOL (COmmon Business Oriented Language) foi projetada (por um comitê de representantes de fabricantes de computadores e do Departamento de Defesa), por iniciativa do Departamento de Defesa dos EUA em 1959 e implementado em 1960. COBOL caracteriza registros, arquivos e dados fixos decimais. Ele também forneceu uma linguagem natural como sintaxe para que os programas sejam capazes de ser lido e entendido por não programadores. COBOL ganhou ampla aceitação na comunidade de processamento de dados e continua a ser largamente utilizado.

 
Ken Thompson e Dennis Ritchie (da esquerda para direita), os criadores das linguagens B e C, respectivamente.

ALGOL 60 (ALGorithmic Oriented Language) foi concebido em 1960 por um comitê internacional para uso em resolução de problemas científicos. Ao contrário FORTRAN foi concebido de forma independente de uma aplicação, uma escolha que conduzem a uma linguagem elegante. A descrição do ALGOL 60 introduziu a notação BNF para a definição de sintaxe e é um modelo de clareza e completude. Embora ALGOL 60 não conseguiu ganhar grande aceitação, introduziu estrutura de bloco, instruções de controle estruturados e procedimentos recursivos no paradigma de programação imperativa.

  • FORTRAN (1956) → variáveis com nome, subprogramas, expressões complexas
  • ALGOL (1960) → maior facilidade de expressar algoritmos matemáticos
  • COBOL (1960)
  • BASIC (1964) → sintaxe mais próxima do inglês
  • PASCAL (1970)
  • C (1970)
  • ADA (1974-1983)

Características editar

As linguagens imperativas estruturadas sofrem no entanto de uma falta de flexibilidade dadas o caráter sequencial das instruções. Contrariamente à programação declarativa, a programação imperativa introduz um paradigma de programação que descreve a computação em termos de um estado de um programa e ações que modificam esse estado, tal como o modo imperativo nas linguagens naturais (faladas e escritas) expressa comandos para perfazer ações, as linguagens imperativas expressam uma sequencia de comandos para um computador efetuar.

 
Visão simplificada da arquitetura de Von Neumann.

As linguagens de programação imperativas contrastam com outros tipos de linguagem, tais como linguagens de programação declarativa, funcional e lógica. Linguagens de programação funcional, como por exemplo Haskell, não são uma sequência de afirmações e não possuem, por consequência, um estado global como as linguagens imperativas. Linguagens de programação lógica, como exemplo Prolog, frequentemente definem "o que" é para ser computado, mais do que "como" computar, como seria normal em uma linguagem imperativa.

Em linguagens puramente imperativas, como Assembly, é muito fácil o programador criar códigos de difícil leitura, pois esse tipo de linguagem possui o que se chama de saltos (jumps) em sua estrutura. Estes saltos funcionam da seguinte forma: o programador define uma marcação (label) no código e depois, a partir de qualquer parte do programa, ele pode executar um desvio de fluxo de execução (salto) para aquela marcação. Pode ser que à primeira vista isso não tenha problema, contudo, na depuração do código, o programador fica em apuros com tantas marcações e saltos, pois isso dificulta o entendimento do fluxo de execução do programa.

Neste contexto, surge a programação estruturada, como uma forma de possibilitar que o programador tenha maior controle sobre o fluxo de execução do programa. Para isso, qualquer programa pode ser reduzido a 3 estruturas:

  • Estruturas de sequência: onde uma tarefa é executada após a outra, linearmente.
  • Estruturas de decisão: onde, a partir de um teste lógico, determinado trecho de código é executado, ou não.
  • Estruturas de iteração: onde, a partir de um teste lógico, determinado trecho de código é repetido por um número finito de vezes.

Programação estruturada é uma forma de programação de computadores que preconiza que todos os programas possíveis podem ser reduzidos a apenas três estruturas: sequência, decisão e iteração, desenvolvida por Michael A. Jackson no seu livro "Principles of Program Design" de 1975.

Tendo, na prática, sido transformada na programação modular, a Programação estruturada orienta os programadores para a criação de estruturas simples em seus programas, usando as subrotinas e as funções. Foi a forma dominante na criação de software anterior à programação orientada por objetos.

Apesar de ter sido sucedida pela programação orientada por objetos, pode-se dizer que a programação estruturada ainda é muito influente, uma vez que grande parte das pessoas ainda aprendem programação através dela. Para a resolução de problemas relativamente mais simples e diretos a programação estruturada é muito eficiente. Além disso, por exigir formas de pensar relativamente complexas, a programação orientada a objetos até hoje ainda não é bem compreendida ou usada pela maioria.

Há de se acrescentar também que inúmeras linguagens ainda extremamente relevantes nos dias de hoje, como Cobol, PHP e Perl ainda utilizam o paradigma estruturado (muito embora possuam suporte para a orientação à objetos).

Principais características da linguagem imperativa editar

As linguagens imperativas também são chamadas de procedurais e se trata do modelo mais antigo de todos, a execução é baseada em comandos e armazenamento de dados. O paradigma imperativo foi predominante nas LP, pois são mais fáceis de traduzir para uma forma adequada para execução da máquina. Um programa imperativo é mantido em variáveis que são associadas com localizações de memória que correspondem a um endereço e um valor de armazenamento. O valor da variável pode ser acessado direta ou indiretamente, e pode ser alterado através de um comando de atribuição. O comando de atribuição introduz uma dependência de ordem no programa, ou seja, o valor da variável pode se modificar antes e depois do comando e isso garante a sequencia de instruções.

As funções de linguagem de programação imperativa são descritas como algoritmos que especificam como processar um intervalo de valores, a partir de um valor de domínio, com uma série de passos descritos. A repetição é usada para processar os valores e laços para varrer uma sequencia de localizações de memória (vetores, por exemplo), ou para acumular valor nas variáveis.

  • Variáveis: modelam as células de memória
  • Comandos de atribuição: são baseados nas operações de transferências de dados e instruções.
  • Execução sequencial de procedimentos
  • Forma interativa de repetição

Como funciona a programação imperativa editar

A essência da programação imperativa e também da Máquina de Turing se resume a três conceitos:

  • A descrição de estados de uma máquina abstrata por valores de um conjunto de variáveis
  • Reconhecedores desses estados - expressões compostas por relações entre esses valores ou os resultados de operações utilizando valores
  • Comandos de atribuição e controle

O código fonte dos programas e computador, seguindo o paradigma imperativo possui marcações especiais (implíticas ou explícitas) que direcionam a sua execução pelo sistema operacional e, em última análise, pelo hardware. Embora as linguagens de programação modernas pertencentes a outros paradigmas tendam a facilitar cada vez mais a escrita do código, camuflando operações mais próximas às linguagens de baixo nível, podemos encontrar ainda a presença de estruturas de controle da mesma forma que ocorria em linguagens de programação de vinte ou trinta anos atrás.

As marcações utilizadas para controlar a execução dos programas são chamadas de estruturas de controle. As estruturas de controle são divididas em três grupos: sequência, seleção e repetição. A estrutura de sequência é implícita nos programas e indica que as instruções são executadas uma após a outra, seguindo uma sequência.

Modelo computacional do paradigma imperativo editar

Programas centrados no conceito de um estado (modelado por variáveis) e ações (comandos) que manipulam o estado, são programas projetados em um paradigma imperativo, paradigma esse que também é denominado de procedural, por incluir sub-rotinas ou procedimentos como mecanismo de estruturação. Foi o primeiro paradigma a surgir e ainda é o dominante.

O paradigma imperativo está baseado na ideia de um estado que sofre modificações durante a computação. O estado é representado por um conjunto de associações de identificadores (variáveis globais e locais ativas do programa) em valores. A diferença fundamental com relação ao paradigma funcional é que esta associação é dinâmica, sendo constantemente modificada durante a execução de um programa. As linguagens imperativas oferecem uma variedade de comandos cuja execução envolve aspectos de controle, mas essencialmente modificação do estado do programa.

O elemento central de um programa imperativo é o comando, que pode ser primitivo (como atribuição, leitura e escrita) ou composto, como seqüência, condicional e iteração. Um importante mecanismo de estruturação das linguagens imperativas é o procedimento, que, como uma função, pode ser parametrizado, mas tem como corpo um comando, ao invés de uma expressão. Em geral, um programa em uma linguagem imperativa deixa de ser uma expressão e passa a ser um comando.

Elementos da programação imperativa editar

Os principais elementos da programação imperativa são:

  • Definição de tipos de dados
  • Expressões e atribuições
  • Estruturas de controle de fluxo (programação estruturada)
  • Definição de sub-rotinas (programação procedimental)

Técnicas em programação imperativa editar

  • Modularidade dos Algoritmos (Programação estruturada)
  • Modularidade das Estruturas de dados (Tipos abstratos de dados)
  • Recorrência

Vantagens editar

  • Eficiência (embute o modelo Von Neumann)
  • Paradigma dominante e bem estabelecido
  • Modelagem natural de aplicações do mundo real
  • Possui tipagem fraca e também muito flexível (alguns especialistas consideram isso uma desvantagem)
  • É fácil de se entender, sendo amplamente usada em cursos introdutórios de programação.

Desvantagens editar

  • Possui difícil legibilidade
  • Descrições demasiadamente profissional focaliza o "como" e não o "quê"
  • Relacionamento indireto com a E/S (indução a erros/estados)
  • Ainda se foca em como a tarefa deve ser feita e não em o que deve ser feito.
  • Tende a gerar códigos confusos, onde tratamento dos dados são misturados com o comportamento do programa

Ver também editar

Referências

  1. a b «Imperative programming: Overview of the oldest programming paradigm». IONOS Digital Guide (em inglês). Consultado em 23 de outubro de 2022 
  2. Canaltech (4 de abril de 2022). «Quais as diferenças entre programação Imperativa, Declarativa e Reativa». Canaltech. Consultado em 23 de outubro de 2022 

Bibliografia editar

  • Pratt, Terrence W. e Marvin V. Zelkowitz. Línguas De Programação: Projeto e execução. ó ed. Penhascos De Englewood, N.J.: Prentice Salão, 1996.
  • Sebesta, Robert W. Conceitos de línguas de programação. ó ed. Leitura, Massa.: Addison-Wesley Publishing Companhia, 1996.

Ligações externas editar