sexta-feira, 24 de abril de 2009

Orientação a Objetos




O conceito de programação orientada por objetos não é novo. No final da década de 60, a linguagem Simula67, desenvolvida na Noruega, introduzia conceitos hoje encontrados nas linguagens orientadas a objetos. Em meados de 1970, o Centro de Pesquisa da Xerox (PARC) desenvolveu a linguagem Smalltalk, a primeira totalmente orientada a objetos. No início da década de 80, a AT&T lançaria a Linguagem C++, uma evolução da linguagem C em direção à orientação a objetos.

Atualmente, a grande maioria das linguagens incorpora características de OO, como Java e Object Pascal. Além das linguagens de programação, é possível encontrar o conceito de OO em sistemas operacionais, como no caso do Windows 2000, e em banco de dados, como no Oracle8 e, principalmente, Jasmine da CA.

A programação orientada a objetos tem como principais objetivos reduzir a complexidade no desenvolvimento de software e aumentar sua produtividade. A análise, projeto e programação orientadas a objetos são as respostas para o aumento da complexidade dos ambientes computacionais que se caracterizam por sistemas heterogêneos, distribuídos em redes, em camadas e baseados em interfaces gráficas.

A programação orientada a objetos não tem a intenção de substituir a programação estruturada tradicional. Podemos considerar que a programação OO é uma evolução de práticas que são recomendadas na programação estruturada, mas não formalizadas, como o uso de variáveis locais, visibilidade e escope. O modelo de objetos permite a criação de bibliotecas que tornam efetivos o compartilhamento e a reutilização de código, reduzindo o tempo de desenvolvimento e, principalmente, simplificando o processo de manutenção das aplicações.

A grande dificuldade para compreender a programação OO é a diferença de abordagem do problema. Enquanto a programação estruturada tem como principal foco as ações (procedimentos e funções), a programação OO se preocupa com os objetos e seus relacionamentos. Além do conceito de objeto, a programação OO tem como alicerces os conceitos de encapsulamento, classe, herança e polimorfismo.

Conceitos Básicos

A abordagem de orientação a objetos favorece a aplicação de diversos conceitos considerados fundamentais para o desenvolvimento de bons programas, tais como abstração e encapsulação. Tais conceitos não são exclusivos desta abordagem, mas são suportados de forma melhor no desenvolvimento orientado a objetos do que em outras metodologias.


Abstração

Abstração consiste de focalizar nos aspectos essenciais inerentes a uma entidade e ignorar propriedades ``acidentais.'' Em termos de desenvolvimento de sistemas, isto significa concentrar-se no que um objeto é e faz antes de se decidir como ele será implementado. O uso de abstração preserva a liberdade para tomar decisões de desenvolvimento ou de implementação apenas quando há um melhor entendimento do problema a ser resolvido.
Muitas linguagens de programação modernas suportam o conceito de abstração de dados; porém, o uso de abstração juntamente com polimorfismo e herança, como suportado em orientação a objetos, é um mecanismo muito mais poderoso.
O uso apropriado de abstração permite que um mesmo modelo conceitual (orientação a objetos) seja utilizado para todas as fases de desenvolvimento de um sistema, desde sua análise até sua documentação.

Encapsulação

Encapsulação, também referido como esconder informação, consiste em separar os aspectos externos de um objeto, os quais são acessíveis a outros objetos, dos detalhes internos de implementação do objeto, os quais permanecem escondidos dos outros objetos. O uso de encapsulação evita que um programa torne-se tão interdependente que uma pequena mudança tenha grandes efeitos colaterais.
O uso de encapsulação permite que a implementação de um objeto possa ser modificada sem afetar as aplicações que usam este objeto. Motivos para modificar a implementação de um objeto podem ser por exemplo melhoria de desempenho, correção de erros e mudança de plataforma de execução.
Assim como abstração, o conceito de encapsulação não é exclusivo da abordagem de orientação a objetos. Entretanto, a habilidade de se combinar estrutura de dados e comportamento em uma única entidade torna a encapsulação mais elegante e mais poderosa do que em linguagens convencionais que separam estruturas de dados e comportamento.

Compartilhamento

Técnicas de orientação a objetos promovem compartilhamento em diversos níveis distintos. Herança de estrutura de dados e comportamento permite que estruturas comuns sejam compartilhadas entre diversas classes derivadas similares sem redundância. O compartilhamento de código usando herança é uma das grandes vantagens da orientação a objetos. Ainda mais importante que a economia de código é a clareza conceitual de reconhecer que operações diferentes são na verdade a mesma coisa, o que reduz o número de casos distintos que devem ser entendidos e analisados.
O desenvolvimento orientado a objetos não apenas permite que a informação dentro de um projeto seja compartilhada como também oferece a possibilidade de reaproveitar projetos e código em projetos futuros. As ferramentas para alcançar este compartilhamento, tais como abstração, encapsulação e herança, estão presentes na metodologia; uma estratégia de reuso entre projetos é a definição de bibliotecas de elementos reusáveis. Entretanto, orientação a objetos não é uma fórmula mágica para alcançar reusabilidade; para tanto, é preciso planejamento e disciplina para pensar em termos genéricos, não voltados simplesmente para a aplicação corrente.

O Modelo de Objetos


Um modelo de objetos busca capturar a estrutura estática de um sistema mostrando os objetos existentes, seus relacionamentos, e atributos e operações que caracterizam cada classe de objetos. É através do uso deste modelo que se enfatiza o desenvolvimento em termos de objetos ao invés de mecanismos tradicionais de desenvolvimento baseado em funcionalidades, permitindo uma representação mais próxima do mundo real.
Uma vez que as principais definições e conceitos da abordagem de orientação a objetos estão definidos, é possível introduzir o modelo de objetos que será adotado ao longo deste texto. O modelo apresentado é um subconjunto do modelo OMT (Object Modeling Technique), proposto por Rumbaugh e outros1.1. OMT também introduz uma representação diagramática para este modelo, a qual será também apresentada aqui.

Objetos e Classes

Objeto é definido neste modelo como um conceito, abstração ou coisa com limites e significados bem definidos para a aplicação em questão. Objetos têm dois propósitos: promover o entendimento do mundo real e suportar uma base prática para uma implementação computacional. Não existe uma maneira ``correta'' de decompor um problema em objetos; esta decomposição depende do julgamento do projetista e da natureza do problema. Todos objetos têm identidade própria e são distinguíveis.
Uma classe de objetos descreve um grupo de objetos com propriedades (atributos) similares, comportamento (operações) similares, relacionamentos comuns com outros objetos e uma semântica comum. Por exemplo, Pessoa e Companhia são classes de objetos. Cada pessoa tem um nome e uma idade; estes seriam os atributos comuns da classe. Companhias também podem ter os mesmos atributos nome e idade definidos. Entretanto, devido à distinção semântica elas provavelmente estariam agrupados em outra classe que não Pessoa. Como se pode observar, o agrupamento em classes não leva em conta apenas o compartilhamento de propriedades.
Todo objeto sabe a que classe ele pertence, ou seja, a classe de um objeto é um atributo implícito do objeto. Este conceito é suportado na maior parte das linguagens de programação orientada a objetos, tais como C ++.
OMT define dois tipos de diagramas de objetos, diagramas de classes e diagramas de instâncias. Um diagrama de classe é um esquema, ou seja, um padrão ou gabarito que descreve as muitas possíveis instâncias de dados. Um diagrama de instâncias descreve como um conjunto particular de objetos está relacionado. Diagramas de instâncias são úteis para apresentar exemplos e documentar casos de testes; diagramas de classes têm uso mais amplo. Conforme figura abaixo


Programação Orientada a Objetos
Figura: Representação diagramática de OMT para classes e objetos. Um diagrama de classe é apresentado à esquerda. Um possível diagrama de instâncias é apresentado à direita.

O agrupamento de objetos em classes é um poderoso mecanismo de abstração. Desta forma, é possível generalizar definições comuns para uma classe de objetos, ao invés de repetí-las para cada objeto em particular. Esta é uma das formas de reutilização e economia que a abordagem de orientação a objetos suporta.

Operações e Métodos

Uma operação é uma função ou transformação que pode ser aplicada a ou por objetos em uma classe. Por exemplo, abrir, salvar e imprimir são operações que podem ser aplicadas a objetos da classe Arquivo. Todos objetos em uma classe compartilham as mesmas operações.
Toda operação tem um objeto-alvo como um argumento implícito. O comportamento de uma operação depende da classe de seu alvo. Como um objeto ``sabe'' qual sua classe, é possível escolher a implementação correta da operação. Além disto, outros argumentos (parâmetros) podem ser necessários para uma operação.
Uma mesma operação pode se aplicar a diversas classes diferentes. Uma operação como esta é dita ser polimórfica, ou seja, ela pode assumir distintas formas em classes diferentes.
Um método é a implementação de uma operação para uma classe. Por exemplo, a operação imprimir pode ser implementada de forma distinta, dependendo se o arquivo a ser impresso contém apenas texto ASCII, é um arquivo de um processador de texto ou binário. Todos estes métodos executam a mesma operação -- imprimir o arquivo; porém, cada método será implementado por um diferente código.
A assinatura de um método é dada pelo número e tipos de argumentos do método, assim como por seu valor de retorno. Uma estratégia de desenvolvimento recomendável é manter assinaturas coerentes para métodos implementando uma dada operação, assim como um comportamento consistente entre as implementações.
Em termos de diagramas OMT, operações são listadas na terceira parte da caixa de uma classe. Cada nome de operação pode ser seguida por detalhes opcionais, tais como lista de argumentos e tipo de retorno. A lista de argumentos é apresentada entre parênteses após o nome da operação. Uma lista de argumentos vazia indica que a operação não tem argumentos; da ausência da lista de argumentos não se pode concluir nada. O tipo de resultado vem após a lista de argumentos, sendo precedido por dois pontos (:). Caso a operação retorne resultado, este não deve ser omitido -- esta é a forma de distinguí-la de operações que não retornam resultado. Exemplos de representação de operações em OMT são apresentados na Figura

Figura: Representação diagramática de OMT para classes com atributos e operações

Programação Orientada a Objetos Programação Estruturada
Métodos Procedimentos e funções
Instâncias de variáveis Variáveis
Mensagens Chamadas a procedimentos e funções
Classes Tipos de dados definidos pelo usuário
Herança -
Polimorfismo -

Um objeto é uma abstração de software que pode representar algo real ou virtual. Um objeto é formado por um conjunto de propriedades (variáveis) e procedimentos (métodos). As variáveis possuem um tipo, que define os possíveis valores que a variável pode representar, como um número inteiro, número real ou string. Os métodos são rotinas que, quando executadas, realizam alguma tarefa, como alterar o conteúdo de uma variável do objeto.

Um exemplo de objeto poderia ser um automóvel. O objeto automóvel possui propriedades, como velocidade, número de portas e limite de passageiros. O objeto automóvel também possui procedimentos, como ligar, desligar, acelerar e parar. Um exemplo menos real de um objeto poderia ser um processo em um sistema operacional. Um processo tem propriedades, como identificação, prioridade, privilégios e quotas. Um processo possui procedimentos associados, como criar, eliminar, alterar a prioridade e visualizar suas caracteríticas.

Os objetos se comunicam apenas através de mensagens. Quando um objeto deseja alguma tarefa de um outro objeto, ele envia uma mensagem contendo o nome do objeto-origem, nome do objeto-destino, nome do método a ser ativado no objeto-destino e, se necessário, parâmetros que permitem especificar alguma função especial a ser executada pelo método. Este conceito se assemelha a chamada de uma rotina em uma linguagem tradicional. O conjunto de mensagens que um objeto pode responder é definido como protocolo de comunicação.

As variáveis de um objeto só podem ser alteradas por métodos definidos na própria classe. A única maneira de um objeto alterar as variáveis de um outro objeto é a através da ativação de um de seus métodos por uma mensagem. Este conceito, onde variáveis e métodos são visíveis apenas através de mensagens, é conhecido como encapsulamento. O encapsulamento funciona como uma proteção para as variáveis e métodos, além de tornar explícito qualquer tipo de comunicação com o objeto.

Geralmente, objetos são criados e eliminados em função da execução do programa. Um objeto pode ser instanciado (criado) por um certo período de tempo e depois eliminado, liberando o espaço de memória ocupado, em um processo automático conhecido como "garbage collection" (coleta de lixo). É possível, porém, criar-se objetos persistentes, que continuam existindo mesmo depois do término do programa que os criou. Um exemplo de objetos persistentes seriam os armazenados em Banco de Dados Orientados a Objetos (OODBMS).

Uma classe consiste de variáveis e métodos que representam características de um conjunto de objetos semelhantes. O conceito de classe é dos pilares da programação orientada a objetos, por permitir a reutilização efetiva de código.

A declaração de uma classe é similar ao dos tipos definidos pelo usuário nas linguagens de programação de alto nível. Nestas linguagens é possível definir um novo tipo de dado e declarar uma variável deste tipo. No caso de objetos, primeiro definimos uma classe com suas variáveis e métodos e, depois, declaramos um objeto desta nova classe. Um objeto é definido como sendo uma instância de uma determinada classe. A classe é estática, enquanto o objeto é dinâmico. No exemplo a seguir, escrito em C++, estamos definindo uma classe T_Ponto, onde as variáveis x e y representam a posição de um ponto na tela. Posteriormente declaramos um objeto p da classe T_Ponto.

class T_Ponto /* Define a classe Ponto */
{
int x;
int y;
public
void altera_xy (int a, int b)
{
x=a;
y=b;
}
int obtem_x () { return x; }
int obtem_y () { return y; }
};

T_Ponto p; /* Declara o objeto p da classe Ponto */

No mesmo exemplo, para alterarmos o valor das variáveis x e y é necessário o envio de uma mensagem para o objeto p, especificando o método altera_xy e passando os novos valores como parâmetros. Da mesma forma, para se consultar os valores de x e y é preciso acionar os métodos obtem_x e obtem_y, respectivamente. Os métodos que permitem a comunicação do objeto com o mundo exterior são conhecidos como interfaces públicas (public).

O conceito de herança permite definir uma nova classe, com base em uma já existente. A classe criada (subclasse ou classe derivada) automaticamente herda todas as variáveis e métodos da classe já existente (superclasse). O mecanismo de herança permite ainda que a subclasse inclua ou sobreponha novas variáveis e métodos da superclasse.

O mecanismo de herança é recursivo, permitindo criar-se uma hierarquia de classes. Nos níveis mais altos da hierarquia estão características comuns a todos os objetos desta classe, enquanto nos níveis inferiores estão especializações das classes superiores. As subclasses herdam as características comuns, além de definirem suas propriedades específicas.

Existem dois tipos de mecanismos de implementação de herança: simples e múltipla. Na herança simples, a subclasse pode herdar variáveis e métodos apenas de uma classe, enquanto na herança múltipla, a subclasse pode herdar variáveis e métodos de mais de uma classe.

Uma das grandes vantagens da programação OO é a utilização de bibliotecas de classes. Estas bibliotecas lembram as bibliotecas de código (procedimentos e funções), utilizadas na programação modular. As bibliotecas de classes permitem uma capacidade muito maior de compartilhamento e reutilização de código, pois é possível criar-se subclasses para atender novas necessidades, em função das classes já existentes. Muitas bilbiotecas são oferecidas juntamente com as ferramentas de desenvolvimento para reduzir o tempo e a complexidade de projetos de software, como a Microsoft Foundation Class (MFC) e a Visual Component Library (VCL) do Delphi. Hoje existe uma crescente insdústria de componentes, isto é, empresas que dedicam a criar classes que servirão para que outros literalmente montem suas aplicações finais.

O termo polimorfismo é utilizado em biologia para definir variações em forma e função de membros de uma mesma espécie. Utilizando a mesma anologia, o mecanismo de polimorfismo permite tratar objetos semelhantes de uma maneira uniforme. Neste caso, é possível que se envie uma mesma mensagem para um conjunto de objetos e que cada objeto responda de maneira diferente em função da mensagem recebida.

O polimorfismo para ser implementado exige a utilização do conceito de herança e aplica-se apenas aos métodos da classe. O protocolo de comunicação é estabelecido na classe mais alta da hierarquia, que será herdada por todas as subclasses definidas posteriormente. Este mecanismo cria um protocolo padrão de comunicação com um conjunto de objetos, permitindo uma grande flexibilidade na agregação de objetos semelhantes, mas não idênticos.

Em programas que não utilizam orientação por objetos, sempre que uma nova funcionalidade deve ser acrescentada, a aplicação deve ser alterada e recompilada. Com o conceito de polimorfismo, é possível acrescentar novos métodos a classes já existentes sem a necessidade de recompilar a aplicação. Isto é possível através da técnica de "late binding" ou "dynamic binding", que permite que novos métodos sejam carregados e ligados (binding) à aplicação em tempo de execução.

Concluindo, baseado nos conceitos de objetos, classes, encapsulamento, herança e polimorfismoo, o paradigma da OO representa uma forma evolucionária de pensar e desenvolver software, trazendo inúmeros benefícios à criação de programas, dentre os quais o mais notável é a reutilização de código, que reduz drasticamente os tempos de desenvolvimento e manutenção de programas.

Referências:
http://www.dca.fee.unicamp.br/cursos/POOCPP/node3.html
http://www.oopucbetim.blogspot.com/

Object-Oriented Programming: An Introduction
Greg Voss, McGraw-Hill, 1991.


Object-Oriented Software
Ann L. Winblad, Samuel D. Edwards & David R. King
Addison-Wesley, 1990.


Postado por Daruich Darquian Campidelli e Rafael Cardoso de Araújo

4 comentários:

  1. Rafa e Daruich,

    o post de vocês ficou muito bom, conseguiram explicar de forma clara e concisa os fundamentos da Orientação a Objetos. Bacana é que este post além de ser relevante em LP também ajuda a entender melhor a aula de análise....rss
    Valeu!

    ResponderExcluir
  2. Em uma entrevista para uma vaga de estagio me perguntaram se eu conhecia orientação a objeto, respondi que não. Mesmo usando na época orientação a objeto na aula do João. Só depois de ler o post de vocês e da explicação do prof.Tiago, consigo distinguir programação orientada a objeto.

    Ficou muito bom.

    ResponderExcluir
  3. Legal a postagem de vcs, tudo o que o Tiago explicou em sala, e um pouco tb do que a Professor de Análise 2 flw tabém, de que tudo é um objeto.
    Vlw

    ResponderExcluir
  4. O.O é a atualidade, é a facilidade batendo a porta do programador, mas surge alguns obstaculos que requer um pouco mais de empenho do programador...atualizar-se eé acompanhar a tecnologia.

    ResponderExcluir