Algoritmos
Um algoritmo é a forma mais rápida e eficiente de se resolver um problema, é um conjunto finito de regras.
Os algoritmos são o alicerce do software (programas de computadores). Um algoritmo é baseado em lógica e é ou deve ser construído se abstendo completamente da linguagem de programação em que será codificado. Um algoritmo para computador tem que ser refinado até o último nível possível, não permitindo que situação nenhuma fique sem tratamento.
“A Lei de Murphy é um ditado popular da cultura ocidental que afirma que "se alguma coisa pode dar errado, com certeza dará". "Se há mais de uma maneira de se executar uma tarefa ou trabalho, e se uma dessas maneiras resultar em catástrofe ou em conseqüências indesejáveis, certamente será a maneira escolhida por alguém para executá-la". A Lei de Murphy é comumente citada (ou abreviada) como "Se algo pode dar errado, dará" ou ainda "se algo pode dar errado, dará errado da pior maneira possível, no pior momento possível". É oriunda do resultado de um teste de tolerância à força g por seres humanos, feito pelo engenheiro aeroespacial norte-americano Edward A. Murphy. Ele deveria apresentar os resultados do teste; contudo, os sensores que deveriam registrá-lo falharam exatamente na hora. Frustrado, Murphy disse "se este cara tem algum modo de cometer um erro, ele o fará" (em referência ao assistente que havia instalado os sensores). Daí, foi desenvolvida a assertiva: "Se existe mais de uma maneira de se executar uma tarefa, e alguma dessas maneiras resultar num desastre, certamente será a maneira escolhida por alguém para executá-la." O teste obteve sucesso, mais tarde. Durante uma conferência de imprensa, John Paul Stapp, que havia servido como cobaia para o teste, atribuiu ao fato de que ninguém saiu ferido dos testes por levarem em conta a Lei de Murphy, e explicou as variáveis que integravam a assertiva, ante ao risco de erro e conseqüente catástrofe.”A qualidade principal de um bom programador de computadores é ter capacidade de definir algoritmos de precisão.
Existem várias maneiras de expressar algoritimos, como veremos a seguir:
Um algoritmo é a forma mais rápida e eficiente de se resolver um problema, é um conjunto finito de regras.
Os algoritmos são o alicerce do software (programas de computadores). Um algoritmo é baseado em lógica e é ou deve ser construído se abstendo completamente da linguagem de programação em que será codificado. Um algoritmo para computador tem que ser refinado até o último nível possível, não permitindo que situação nenhuma fique sem tratamento.
“A Lei de Murphy é um ditado popular da cultura ocidental que afirma que "se alguma coisa pode dar errado, com certeza dará". "Se há mais de uma maneira de se executar uma tarefa ou trabalho, e se uma dessas maneiras resultar em catástrofe ou em conseqüências indesejáveis, certamente será a maneira escolhida por alguém para executá-la". A Lei de Murphy é comumente citada (ou abreviada) como "Se algo pode dar errado, dará" ou ainda "se algo pode dar errado, dará errado da pior maneira possível, no pior momento possível". É oriunda do resultado de um teste de tolerância à força g por seres humanos, feito pelo engenheiro aeroespacial norte-americano Edward A. Murphy. Ele deveria apresentar os resultados do teste; contudo, os sensores que deveriam registrá-lo falharam exatamente na hora. Frustrado, Murphy disse "se este cara tem algum modo de cometer um erro, ele o fará" (em referência ao assistente que havia instalado os sensores). Daí, foi desenvolvida a assertiva: "Se existe mais de uma maneira de se executar uma tarefa, e alguma dessas maneiras resultar num desastre, certamente será a maneira escolhida por alguém para executá-la." O teste obteve sucesso, mais tarde. Durante uma conferência de imprensa, John Paul Stapp, que havia servido como cobaia para o teste, atribuiu ao fato de que ninguém saiu ferido dos testes por levarem em conta a Lei de Murphy, e explicou as variáveis que integravam a assertiva, ante ao risco de erro e conseqüente catástrofe.”A qualidade principal de um bom programador de computadores é ter capacidade de definir algoritmos de precisão.
Existem várias maneiras de expressar algoritimos, como veremos a seguir:
Linguagem natural
Os algoritmos são expressos diretamente em linguagem natural, ex:
1 – inicio do programa
2 – Ler a,b
3 – se a <> 0 então faça
Clacula o valor de x(ax+b=0)
Imprimir valor de x
Senão
Imprimir “não há zero”
4 – fim de programa
1 – inicio do programa
2 – Ler a,b
3 – se a <> 0 então faça
Clacula o valor de x(ax+b=0)
Imprimir valor de x
Senão
Imprimir “não há zero”
4 – fim de programa
Fluxograma ou diagrama de fluxo
Usa formas geométricas padronizadas para indicar ações ou decisões que devem ser tomadas.
Pseudo-linguagem ou pseudo-código
Emprega uma linguagem intermediária entre a linguagem natural e a linguagem de programação.
Read a
Read b
If a = 0 then
A = a + 1200
Else
A = a -1200
endif
print a
close
Linguagem de programação
1. public int getMenorValor(int [] vetor ){
2. int menorIdade = vetor [0];
3. for(int idade : vetor ){
4. if(menorIdade > idade){
5. menorIdade = idade;
6. }
7. }
8. return menorIdade;
9.
10. }
1. public int getMenorValor(int [] vetor ){
2. int menorIdade = vetor [0];
3. for(int idade : vetor ){
4. if(menorIdade > idade){
5. menorIdade = idade;
6. }
7. }
8. return menorIdade;
9.
10. }
Como se constrói um software.
Quando se trata de construir software de média e grande complexidade, como por exemplo softwares coorporativos e científicos a primeira atividade da equipe de analistas de sistemas (responsáveis pelo levantamento de informações sobre uma empresa a fim de utilizá-las no desenvolvimento de um sistema para a mesma), é definir os requisitos do software.
Os requisitos são objetivos ou restrições estabelecidas por clientes e usuários do sistema que definem as diversas propriedades do sistema. Os requisitos de software são, obviamente, aqueles dentre os requisitos de sistema que dizem respeito a propriedades do software.
Um conjunto de requisitos pode ser definido como uma condição ou capacidade necessária que o software deve possuir (1) para que o usuário possa resolver um problema, ou atingir um objetivo ou (2) para atender as necessidades ou restrições da organização ou dos outros componentes do sistema.
Tradicionalmente, os requisitos de software são separados em requisitos funcionais e não-funcionais. Os requisitos funcionais são a descrição das diversas funções que clientes e usuários querem ou precisam que o software ofereça. Eles definem a funcionalidade desejada do software. O termo função é usado no sentido genérico de operação que pode ser realizada pelo sistema, seja através comandos dos usuários ou seja pela ocorrência de eventos internos ou externos ao sistema.
Um dos objetivos da Engenharia de Requisitos é ultrapassar barreiras de comunicação entre os clientes e usuários e os analistas para que os requisitos possam capturados e modelados corretamente
Dentre as técnicas mais importantes para a comunicação podemos citar três:
• Entrevistas
• Observação in loco
• Encontros
Estas três técnicas são complementares e podem todas ser usadas numa mesma análise de requisitos. A entrevista é normalmente a primeira técnica utilizada. Analistas entrevistam clientes para definir os objetivos gerais e restrições que o software deverá ter. A entrevista deve ser feita de forma objetiva visando obter o máximo de informações do cliente. Diversas seções de entrevistas podem ser marcadas.
Na observação in loco os analista devem estar inseridos na rotina de trabalho da organização tentando entender e descrever as principais atividades que são realizadas. Na observação devem ser identificadas quais as atividades podem ser automatizadas, quem são os potenciais usuários, quais tarefas eles querem realizar com a ajuda do novo sistema, etc. A observação deve ser complementada com entrevistas específicas com os futuros usuários.
Os encontros são reuniões envolvendo analistas, clientes e usuários destinadas exclusivamente ao levantamento de informações, descrição dos problemas atuais e de metas futuras. Os encontros devem ser realizados em um local neutro (fora da organização) e normalmente duram poucos alguns dias. Nos encontros as informações que vão sendo levantadas vão sendo afixadas em painéis na sala de encontro para que possam ser analisadas e validadas pelos clientes e usuários. Ao final do encontro os analistas devem elaborar um relatório descrevendo os requisitos analisados.
O resultado final da análise e especificação de requisitos e das outras atividades da fase de definição devem ser apresentados aos clientes para que eles possam validá-lo. Este documento oferece a concordância entre clientes, analistas e desenvolvedores sobre o que deve ser desenvolvido. É utilizando este documento que as atividades da fase de desenvolvimento (design e programação) serão validadas.
Cada desenvolvedor utiliza um modelo específico para elaborar este documento. A sua estrutura muitas vezes depende do método que está sendo utilizado. Em linhas gerais este modelo deve ser basicamente textual, utilizando o mínimo de termos técnicos, e ilustrados como modelos gráficos que demonstrem mais claramente a visão que os analistas tiveram dos problemas e dos requisitos para o futuro sistema.
Quando se trata de construir software de média e grande complexidade, como por exemplo softwares coorporativos e científicos a primeira atividade da equipe de analistas de sistemas (responsáveis pelo levantamento de informações sobre uma empresa a fim de utilizá-las no desenvolvimento de um sistema para a mesma), é definir os requisitos do software.
Os requisitos são objetivos ou restrições estabelecidas por clientes e usuários do sistema que definem as diversas propriedades do sistema. Os requisitos de software são, obviamente, aqueles dentre os requisitos de sistema que dizem respeito a propriedades do software.
Um conjunto de requisitos pode ser definido como uma condição ou capacidade necessária que o software deve possuir (1) para que o usuário possa resolver um problema, ou atingir um objetivo ou (2) para atender as necessidades ou restrições da organização ou dos outros componentes do sistema.
Tradicionalmente, os requisitos de software são separados em requisitos funcionais e não-funcionais. Os requisitos funcionais são a descrição das diversas funções que clientes e usuários querem ou precisam que o software ofereça. Eles definem a funcionalidade desejada do software. O termo função é usado no sentido genérico de operação que pode ser realizada pelo sistema, seja através comandos dos usuários ou seja pela ocorrência de eventos internos ou externos ao sistema.
Um dos objetivos da Engenharia de Requisitos é ultrapassar barreiras de comunicação entre os clientes e usuários e os analistas para que os requisitos possam capturados e modelados corretamente
Dentre as técnicas mais importantes para a comunicação podemos citar três:
• Entrevistas
• Observação in loco
• Encontros
Estas três técnicas são complementares e podem todas ser usadas numa mesma análise de requisitos. A entrevista é normalmente a primeira técnica utilizada. Analistas entrevistam clientes para definir os objetivos gerais e restrições que o software deverá ter. A entrevista deve ser feita de forma objetiva visando obter o máximo de informações do cliente. Diversas seções de entrevistas podem ser marcadas.
Na observação in loco os analista devem estar inseridos na rotina de trabalho da organização tentando entender e descrever as principais atividades que são realizadas. Na observação devem ser identificadas quais as atividades podem ser automatizadas, quem são os potenciais usuários, quais tarefas eles querem realizar com a ajuda do novo sistema, etc. A observação deve ser complementada com entrevistas específicas com os futuros usuários.
Os encontros são reuniões envolvendo analistas, clientes e usuários destinadas exclusivamente ao levantamento de informações, descrição dos problemas atuais e de metas futuras. Os encontros devem ser realizados em um local neutro (fora da organização) e normalmente duram poucos alguns dias. Nos encontros as informações que vão sendo levantadas vão sendo afixadas em painéis na sala de encontro para que possam ser analisadas e validadas pelos clientes e usuários. Ao final do encontro os analistas devem elaborar um relatório descrevendo os requisitos analisados.
O resultado final da análise e especificação de requisitos e das outras atividades da fase de definição devem ser apresentados aos clientes para que eles possam validá-lo. Este documento oferece a concordância entre clientes, analistas e desenvolvedores sobre o que deve ser desenvolvido. É utilizando este documento que as atividades da fase de desenvolvimento (design e programação) serão validadas.
Cada desenvolvedor utiliza um modelo específico para elaborar este documento. A sua estrutura muitas vezes depende do método que está sendo utilizado. Em linhas gerais este modelo deve ser basicamente textual, utilizando o mínimo de termos técnicos, e ilustrados como modelos gráficos que demonstrem mais claramente a visão que os analistas tiveram dos problemas e dos requisitos para o futuro sistema.
Metodologias de Desenvolvimento de Sistemas
Análise Estruturada
Análise Essencial
Análise Orientada a Objetos
Análise Estruturada
Enfatiza a perspectiva das funções, com ênfase nos processos.
Utiliza as seguintes ferramentas:
Diagrama de Fluxo de Dados.
Dicionário de Dados.
Especificação da Lógica de Processos.
A análise estruturada clássica não modela o comportamento temporal, nem complexos relacionamentos de dados.
Análise Essencial
É uma evolução da Análise Estruturada por adicionar a preocupação com o controle.
Usa uma lista de eventos externos como base para o particionamento do sistema.
O modelo essencial é construído sem considerar restrições de implementação (assume uma tecnologia perfeita) – essência do sistema
O modelo essencial é formado pelo:
Modelo Ambiental – define a fronteira entre o sistema e o ambiente.
Modelo Comportamental – descreve o comportamento interno do sistema.
Modelo de Informação – modela os dados necessários às atividades essenciais do sistema.
Modelo de Implementação – extensão do modelo essencial com restrições de implementação
Modelo Ambiental
Diagrama de Contexto - Define as interfaces entre o sistema e o ambiente. São identificadas informações externas e as produzidas como saída.
Lista de Eventos - Identifica os eventos que ocorrem no ambiente e como o sistema deve reagir.
Modelo Comportamental
Mostra o comportamento interno do sistema.
Usa como ferramenta DFD com abordagem diferente.
Constrói um DFD para cada evento (DFD de resposta a eventos). A partir dele é feito o agrupamento para formar os diagramas superiores e inferiores.
Dicionário de Dados e Especificação de processos
Modelo de Informação
Representa os dados necessários ao sistema.
Ferramentas utilizadas são:
Diagrama de entidade e relacionamento
Deriva da lista de eventos
Representa a estrutura estática dos dados
Dicionário de Dados
Modelo de implementação
Insere restrições de implementação aos modelos comportamental e de dados
Fronteiras de automação, tempo de execução, capacidade de armazenamento, comunicação, etc.
Análise Orientada a Objetos
Cenário
Mudança do enfoque das funções para os dados
Preocupação em modelar de forma mais detalhada o sistema
Análise mais próxima da realidade
Facilidade na comunicação com o usuário
Objetos como entidades do mundo real
Objetos com estrutura e comportamento e que se comunicam
Dificuldades em fazer alterações nas estruturas de dados nas abordagens tradicionais
“Se eu alterar a definição desse dado, quais programas serão afetados?”
Trabalha com conceitos já conhecidos - Modularidade, Abstração, Encapsulamento, Mascarar informações, etc
Orientação a objetos apesar de antiga não era utilizada por falta de pessoas treinadas, interesse em manter a cultura adquirida, ferramentas imaturas. Isso começa a se resolver.
O mundo real é composto por objetos. Cada objeto tem propriedades e comportamentos. Então porquê não desenvolver programas que simulem no computador os objetos do mundo real com suas propriedades e comportamentos?
Um sistema construído usando um método Orientado a Objetos é aquele cujos componentes são partes encapsuladas de dados e funções, que podem herdar atributos e comportamentos de outros componentes da mesma natureza, e cujos componentes comunicam-se entre si por meio de mensagens.
Objetivo: Encontrar os objetos, organizá-los, descrever como interagem através de mensagens, definir operações de seus comportamentos.
Nos métodos tradicionais de análise, o comportamento do sistema e seus dados eram considerados separadamente. Com orientação a objetos, comportamento e dados são integrados, assim encapsulando detalhes internos de um objeto dos demais.
Concentra-se nos aspectos essenciais do objeto sem detalhamento, focando em suas características e o que ele faz;
Impede que um sistema se torne tão interdependente que uma pequena alteração ou implementação resulte em grandes alterações em sua estrutura;
Combina estrutura (dados) e comportamento (funções) em um único objeto;
Compartilha elementos estruturais e de comportamento com objetos de níveis inferiores;
Enfatiza a estrutura de objetos ao invés da estrutura de procedimentos, ou seja, o que o objeto é e não como ele é utilizado.
Análise Estruturada
Análise Essencial
Análise Orientada a Objetos
Análise Estruturada
Enfatiza a perspectiva das funções, com ênfase nos processos.
Utiliza as seguintes ferramentas:
Diagrama de Fluxo de Dados.
Dicionário de Dados.
Especificação da Lógica de Processos.
A análise estruturada clássica não modela o comportamento temporal, nem complexos relacionamentos de dados.
Análise Essencial
É uma evolução da Análise Estruturada por adicionar a preocupação com o controle.
Usa uma lista de eventos externos como base para o particionamento do sistema.
O modelo essencial é construído sem considerar restrições de implementação (assume uma tecnologia perfeita) – essência do sistema
O modelo essencial é formado pelo:
Modelo Ambiental – define a fronteira entre o sistema e o ambiente.
Modelo Comportamental – descreve o comportamento interno do sistema.
Modelo de Informação – modela os dados necessários às atividades essenciais do sistema.
Modelo de Implementação – extensão do modelo essencial com restrições de implementação
Modelo Ambiental
Diagrama de Contexto - Define as interfaces entre o sistema e o ambiente. São identificadas informações externas e as produzidas como saída.
Lista de Eventos - Identifica os eventos que ocorrem no ambiente e como o sistema deve reagir.
Modelo Comportamental
Mostra o comportamento interno do sistema.
Usa como ferramenta DFD com abordagem diferente.
Constrói um DFD para cada evento (DFD de resposta a eventos). A partir dele é feito o agrupamento para formar os diagramas superiores e inferiores.
Dicionário de Dados e Especificação de processos
Modelo de Informação
Representa os dados necessários ao sistema.
Ferramentas utilizadas são:
Diagrama de entidade e relacionamento
Deriva da lista de eventos
Representa a estrutura estática dos dados
Dicionário de Dados
Modelo de implementação
Insere restrições de implementação aos modelos comportamental e de dados
Fronteiras de automação, tempo de execução, capacidade de armazenamento, comunicação, etc.
Análise Orientada a Objetos
Cenário
Mudança do enfoque das funções para os dados
Preocupação em modelar de forma mais detalhada o sistema
Análise mais próxima da realidade
Facilidade na comunicação com o usuário
Objetos como entidades do mundo real
Objetos com estrutura e comportamento e que se comunicam
Dificuldades em fazer alterações nas estruturas de dados nas abordagens tradicionais
“Se eu alterar a definição desse dado, quais programas serão afetados?”
Trabalha com conceitos já conhecidos - Modularidade, Abstração, Encapsulamento, Mascarar informações, etc
Orientação a objetos apesar de antiga não era utilizada por falta de pessoas treinadas, interesse em manter a cultura adquirida, ferramentas imaturas. Isso começa a se resolver.
O mundo real é composto por objetos. Cada objeto tem propriedades e comportamentos. Então porquê não desenvolver programas que simulem no computador os objetos do mundo real com suas propriedades e comportamentos?
Um sistema construído usando um método Orientado a Objetos é aquele cujos componentes são partes encapsuladas de dados e funções, que podem herdar atributos e comportamentos de outros componentes da mesma natureza, e cujos componentes comunicam-se entre si por meio de mensagens.
Objetivo: Encontrar os objetos, organizá-los, descrever como interagem através de mensagens, definir operações de seus comportamentos.
Nos métodos tradicionais de análise, o comportamento do sistema e seus dados eram considerados separadamente. Com orientação a objetos, comportamento e dados são integrados, assim encapsulando detalhes internos de um objeto dos demais.
Concentra-se nos aspectos essenciais do objeto sem detalhamento, focando em suas características e o que ele faz;
Impede que um sistema se torne tão interdependente que uma pequena alteração ou implementação resulte em grandes alterações em sua estrutura;
Combina estrutura (dados) e comportamento (funções) em um único objeto;
Compartilha elementos estruturais e de comportamento com objetos de níveis inferiores;
Enfatiza a estrutura de objetos ao invés da estrutura de procedimentos, ou seja, o que o objeto é e não como ele é utilizado.
Linguagens de programação
Para se implementar um algoritmo em um computador, é necessário descrevê-lo de uma forma que o computador esteja apto a executá-lo. Essa descrição é feita por intermédio de uma “linguagem de programação”. O próprio conjunto de instruções de um processador pode ser entendido como uma “linguagem de programação” . Entretanto, essa linguagem normalmente não é a mais adequada para a descrição de um programa, uma vez que os algoritmos necessários podem ser sofisticados, e essa linguagem primitiva, também chamada de “linguagem de máquina” não é nem um pouco amigável ao programador, demandando um esforço muito grande na elaboração de programas mais complexos. Sendo assim, foram desenvolvidas, ao longo da história da computação, diversas linguagens de programação”, cada qual, a seu tempo, introduzindo facilidades e recursos que foram tornando a tarefa de programar mais fácil e menos suceptível a erros.
Atualmente, com as linguagens visuais (também chamadas por alguns de linguagens de quarta geração), programar deixou de ser uma arte restrita a um grupo de indivíduos, para tornar-se uma ferramenta a mais dentro do escopo do usuário comum.
Neste texto, apresentamos um tutorial histórico sobre as linguagens de programação, ressaltando aquelas que foram mais proeminentes dentro de cada categoria. As linguagens de programação podem ser divididas dentro da seguinte taxonomia:
Linguagens de Baixo Nível
Linguagens Não-Estruturadas
Linguagens Procedurais Linguagens Funcionais Linguagens Orientadas a Objeto
Linguagens de Baixo Nível
Linguagens de baixo nível são linguagens cujas instruções correspondem quase que diretamente ao código de máquina que será enviado ao processador para execução. Na verdade, existem tantas linguagens de baixo nível quantos são os conjuntos de instruções dos diferentes processadores. Essas linguagens são conhecidas de uma maneira unificada como “Linguagem Assembly”, sendo que na verdade deve existir uma linguagem Assembly para cada processador. Sendo assim, deve haver um Assembly 8086, um Assembly 68000, um Assembly 80386, um Assembly Pentium e assim por diante.
Linguagens Não-Estruturadas
Linguagens não-estruturadas são linguagens mais sofisticadas que as linguagens de baixo nível. São linguagens mais flexíveis, pois seus comandos não estão tão vinculados ao processador e sistema utilizados, tornando seu uso possível em diferentes plataformas. Do mesmo modo, a semântica de seus termos torna-se mais genérica, estando desassociada do conjunto de instruções que irão efetivamente implementá-la durante a execução do programa. Isso permite que operações mais sofisticadas sejam emuladas por sequências de instruções mais simples em linguagem de máquina. As linguagens não estruturadas corresponderam a um grande salto qualitativo em termos de programação, quando comparadas com as linguagens de baixo nível. Entretanto, tornaram-se gradualmente obsoletas, com a introdução de linguagens estruturadas mais sofisticadas, tais como as linguagens procedurais, as linguagens funcionais e as linguagens orientadas a objetos.
Linguagens Procedurais
As linguagens procedurais são um dos sub-tipos das linguagens chamadas “estruturadas”. Essas linguagens se diferenciam das linguagens não estruturadas, pela existência de estruturas de controle, que entre outras coisas promovem o teste de condições (if-then-else), controlam a repetição de blocos de código (for, while, do), fazem a seleção de alternativas (switch, case), e dividem o código do programa em módulos chamados de funções ou procedimentos. As linguagens procedurais são caracterizadas pela existência de algoritmos, que determinam uma sequência de chamadas de procedimentos, que constituem o programa. Essa característica é colocada em contraposição às linguagens funcionais, onde se descrevem expressões que caracterizam um certo tipo de conhecimento. As linguagens procedurais mais comuns são o C, o Pascal e o Fortran. Algumas linguagens mais sofisticadas, tais como o Ada, Modula-2 e Modula-3 foram desenvolvidas para corrigir deficiências e explorar novos contextos onde o C, Pascal e Fortran não eram totalmente adequados.
Linguagens Funcionais
Linguagens funcionais são linguagens que evidenciam um estilo de programação diferente das linguagens procedurais, chamado de programação funcional. A programação funcional enfatiza a avaliação de expressões, ao invés da execução de comandos. As expressões nessas linguagens são formadas utilizando- se funções para combinar valores básicos. As linguagens funcionais mais conhecidas são o LISP e o Prolog. A linguagem Scheme também é frequentemente citada, por ser uma variante simplificada do LISP. Diversas outras linguagens funcionais são encontradas na literatura, por exemplo, ASpecT, Caml, Clean, Erlang, FP, Gofer, Haskell, Hope, Hugs, Id, IFP, J, Miranda, ML, NESL, OPAL,e Sisal.
Linguagens Orientadas a Objetos
As linguagens orientadas a objeto foram originadas a partir da necessidade de se organizar o processo de programação em uma linguagem. A programação orientada a objetos é por si, só uma técnica. Uma linguagem é dita uma linguagem orientada a objetos, se ela suporta o estilo de programação orientada a objetos.
Um dos objetivos da engenharia de software é particionar o projeto de um programa em diversos módulos, de tal forma que o desenvolvimento do software e sua manutenção possam ser implementados com baixo custo. No passado, os paradigmas da engenharia de software derivavam os módulos baseados na funcionalidade de um sistema. Esses módulos correspondiam basicamente a módulos procedimentais, que eram alimentados por dados, gerando novos dados. O paradigma de orientação a objeto mudou essa concepção, idealizando a idéia de objetos, como módulos que se comunicam por meio de mensagens, encapsulando ao mesmo tempo dados e funções, por meio de um mecanismo conhecido como tipo de dados abstratos.
A primeira linguagem orientada a objetos que se tem notícia foi o Simula, desenvolvido em 1967. Posteriormente veio o Smalltalk em 1970. Atualmente, existe uma enorme diversidade de linguagens orientadas a objeto, abrangendo desde linguagens de propósito geral, até linguagens para multimídia e programação em lógica.
O desenvolvimento das linguagens
Várias linguagens, muitas delas conceitualmente diferentes entre si, foram surgindo e sendo aprimoradas, incorporando-se umas em outras. Com algumas poucas exceções, o projeto de cada linguagem foi influenciado pela experiência em linguagens anteriores. Merecem especial atenção pelo seu pioneirismo e pelos novos paradigmas que introduziram as linguagens, chamadas de alto nível: FORTRAN e LISP.
Com relação ao FORTRAN, em 1954 ocorreu um simpósio sobre 'computação automática'§3, e seu maior evento foi a apresentação do compilador algébrico de Laning e Zierler (ver capítulo Os primeiros 'compiladores'). Foi o primeiro 'software' que permitiu como entrada de dados um código algébrico elegante, embora limitado. Nesse meio tempo John Backus já montara um grupo de pesquisa dentro da IBM para trabalhar em um projeto sobre programação automática, para responder a uma questão fundamental: "(...) pode uma máquina traduzir uma linguagem matemática abrangente em um conjunto razoável de instruções, a um baixo custo, e resolver totalmente uma questão?"77. Em novembro de 1954 a equipe de Backus tinha criado o IBM Mathematical FORmula TRANslation System, o FORTRAN. O primeiro parágrafo da apresentação desse trabalho enfatizava que os sistemas anteriores ofereciam duas escolhas: ou uma fácil codificação e uma execução lenta do programa ou uma laboriosa codificação com rápida execução, mas "o FORTRAN propiciava o melhor das duas opções"38. Com o FORTRAN apareceram as expressões simbólicas, subprogramas com parâmetros, mas principalmente ocorreu a primeira tentativa de se definir rigorosamente a sintaxe de uma linguagem de programação. Um pouco mais tarde surgiu a notação BNF para a descrição sintática de uma linguagem de programação.
A história do LISP remonta a Turing e Church. Pela análise de Turing nos anos de 1936 e 1937, após seu famoso artigo sobre o décimo problema de Hilbert, o cálculo-lambda de Church, apesar da sua sintaxe simples, era suficientemente poderoso para descrever todas as funções mecanicamente computáveis, ou seja, pode ser visto paradigmaticamente como uma linguagem de programação. No cálculo-lambda muitos problemas de programação, especificamente aqueles referentes às chamadas de procedimento, estão em sua forma mais pura, e isto influenciará diretamente linguagens como LISP e Algol3.
Em 1955 e 1956 E.K. Blum, no U.S. Naval Ordinance Laboratory desenvolveu uma linguagem completamente diferente das demais, ADES (Automatic Digital Encoding System), baseada na teoria das funções recursivas e no esquema desenvolvido para elas por Kleene. Foi a primeira linguagem "declarativa", no sentido de que o programador estabelece as relações entre as variáveis quantitativas sem explicitamente especificar a ordem de avaliação (mais à frente se falará sobre este paradigma de programação).
Aparece agora a figura de John McCarthy, matemático, um dos primeiros a trabalhar no tema de Inteligência Artificial. Juntamente com Marvin Minsky iniciou um grande projeto nessa área. Estava procurando desenvolver uma linguagem algébrica para processamento de listas, preocupado com o problema de como representar informações da realidade por meio de sentenças escritas em uma linguagem formal adequada, e de como criar um programa que executasse fazendo inferências lógicas. Surgiu então o LISP, uma linguagem que pode ser utilizada como um formalismo para descrição de algoritmos, para escrever programas e provar propriedades de algoritmos, sendo adequada à computação simbólica e à inteligência artificial. Sobretudo com LISP pode-se visualizar melhor um importante conceito na computação moderna que é o uso de estruturas de dados como objetos abstratos. É um dos aspectos centrais dessa linguagem, comparada a como a Matemática usa os números naturais como entidades abstratas.
Nos inícios da década de 1960, fruto do trabalho de americanos e europeus, surgiu uma linguagem projetada para representar algoritmos ao invés de se escrever programas simplesmente, o Algol-60. Ela implementava o conceito de estrutura de blocos, onde variáveis, procedimentos, etc., poderiam ser declarados onde quer que o programa os necessitasse. Algol-60 influenciou profundamente muitas linguagens que vieram depois e evoluiu para o Algol-68.
PL/I surgiu como uma tentativa de se projetar uma linguagem de uso geral reunindo características de linguagens para aplicações numéricas como FORTRAN e Algol e para processamento de dados comerciais. Ela inovou ao permitir a construção de código de 'baixo nível' para o controle de exceções e o conceito de processamento concorrente, entre outros. O resultado foi algo anômalo, complexo e incoerente, de difícil implementação.
Foi a linguagem Pascal entretanto que se tornou a mais popular das linguagens do estilo Algol, porque é simples, sistemática e facilmente implementável nos diferentes computadores. Junto com o Algol-68, está entre as primeiras linguagens com uma ampla gama de instruções para controle de fluxo, definição e construção de novos tipos de dados. Ada, que veio depois do Pascal, introduziu o conceito de pacotes e permite a construção de grandes programas com estrutura modular.
Podem-se discernir na história das linguagens certas tendências. A primeira foi perseguir altos níveis de abstração. Os rótulos simbólicos e mnemônicos das linguagens de montagem abstraem códigos de operação e endereços. Variáveis e atribuição abstraem acesso a um endereço de memória e atualização. Estruturas de dados abstraem formas de armazenamento. Estruturas de controle abstraem desvios. Procedimentos abstraem subrotinas. E assim por diante.
Outra tendência foi a proliferação dos paradigmas. A maioria das linguagens mencionadas até agora são imperativas, caracterizadas por comandos que atualizam variáveis. A estrutura das linguagens imperativas é induzida pelo hardware, com preocupação de que os dados trafeguem o mais rapidamente possível. Daí alguns de seus aspectos relevantes: sequência de comandos, atribuição, controles (loopings), etc. É ainda o paradigma dominante.
Já as linguagens que seguem o paradigma funcional (também conhecidas como declarativas), como o LISP, tem como características a clareza e a busca de um maior poder expressivo, procurando manter a maior independência possível do paradigma de von Neumann, que caracteriza as linguagens imperativas§4. Buscam uma transparência referencial e a não ocorrência de efeitos colaterais nas suas instruções. Em LISP não há o conceito de estado - dado por uma atribuição -, memória, sequência de instruções, etc., procurando-se tornar mais visível o uso das funções. Nas linguagens imperativas as funções dependem de estados internos, fora de seu contexto ( x := x + 'argumento'), com a produção de efeitos colaterais (alteração de valores, impressão, etc.). LISP foi a ancestral das linguagens funcionais que culminaram atualmente em linguagens como Miranda, ML e Haskell, que tratam funções como valores de primeira classe.
Smalltalk é uma linguagem baseada em classes de objetos. Um objeto é uma variável que pode ser acessada somente através de operações associadas a ele. Smalltalk é um exemplo de uma linguagem que segue o paradigma de orientação a objeto. Simula foi um ancestral de tais linguagens.
É importante reparar que a notação matemática em sua generalidade não é facilmente implementável. No entanto muitos projetistas de linguagens quiseram explorar subconjuntos da notação matemática em linguagens de programação. Surgiram então tentativas de se contruir uma 'linguagem lógica', isto é, baseada em um subconjunto da lógica matemática. O computador é programado para inferir relacionamentos entre valores, ao invés de computar valores de saída a partir de valores de entrada. Prolog popularizou a linguagem lógica. Em sua forma pura é fraca e ineficiente, tendo sido alterada para incluir características não lógicas e tonar-se mais amigável como linguagem de programação.
No início da década de 1990 ocorreu um difusão intensa do paradigma da orientação a objeto§5. Este paradigma esteve em gestação por cerca de 30 anos e as novas tecnologias como a Internet, as necessidades geradas pela novas arquiteturas, tais como a de cliente-servidor§6 e a do processamento distribuído, coincidiam com o paradigma da orientação a objeto: encapsulamento, mensagem, etc. O crescimento da Internet e o "comércio eletrônico" introduziram novas dimensões de complexidade no processo de desenvolvimento de programas. Começaram a surgir linguagens que buscam superar esses novos desafios de desenvolvimento de aplicações em um contexto heterogêneo ( arquiteturas de hardware incompatíveis, sistemas operacionais incompatíveis, plataformas operando com uma ou mais interfaces gráficas incompatíveis, etc). Apareceram C++ e linguagens como Eifell, Objective C, Cedar/Mesa (elaborada pela Xerox, para fazer pesquisa de dados), Delphi (uma evolução da lingaugem Pascal) entre outras. E, "o próximo passo ou um paradigma completamente novo"28, surge a linguagem JAVA.
A origem da Java está ligada a um grupo de pesquisa e desenvolvimento da Sun Microsystems formado em 1990, liderado por Patrick Naughton e James Gosling, que buscava uma nova ferramenta de comunicação e programação, independente da arquitetura de qualquer dispositivo eletrônico. Em 1994, após o surgimento do NCSA Mosaic e a popularização da Internet, a equipe refocalizou seus esforços para criar uma linguagem para aplicações multimídia on line.
Conforme Linden47, Java foi inspirada por várias linguagens: tem a concorrência da Mesa, tratamento de exceções como Modula-3, linking dinâmico de código novo e gerenciamento automático de memória como LISP, definição de interfaces como Objective C, e declarações ordinárias como C. Apesar destas qualidades, todas importantes, na verdade duas outras realmente fazem a diferença e tornam Java extremamente atrativa: sua portabilidade e o novo conceito de arquitetura neutra.
Portabilidade significa que Java foi projetada objeticando aplicações para vários sistemas heterogêneos que podem compor uma rede como a Internet, por exempo, e as diferentes características dessa rede. Java procura obter os mesmos resultados de processamento nas diferentes plataformas.
Por arquitetura neutra entende-se que programas em Java são compilados para se obter um código objeto (byte code na terminologia Java) que poderá ser executado em um Power PC que use o sistema operacional OS/2, ou em um sistema baseado no chip Pentium debaixo do Windows 95 ou em um Macintosh usando MacOs, ou em uma estação de trabalho Sparc rodando Unix. Ou seja, em qualquer computador, desde que tal computador implemente o ambiente necessário para isso, denominado conceitualemente de Máquina Virtual Java.
Com a linguagem Java começou superar-se a barreira para a Internet tornar-se um computador: a barreira que impede o uso de um software utilizado em um determinado lugar, executando-o em qualquer plataforma.