MAC 413/5715 - Tópicos de Programação
Orientada a
Objetos
Aula 6 - 26/8/2005
POSA I - Reflection
Além de diagramas UML, o POSA também usa
cartões CRC para documentar as arquiteturas:
Cartões CRC (Class, Responsibility, Collaborator)
Exemplo, padrão Camadas:
Class
Camada J
Responsibility
Provê serviços usados pela
camada J+1
Delega subtarefas para a camada J-1
Collaborator
Camada J-1
Exemplo concreto de uso do padrão:
FTP em cima de TCP em cima de IP em
cima de Ethernet em cima de cabo de par trançado.
Padrão Arquitetural para Sistemas Adaptáveis: Reflection
Padrão baseado na idéia de Reflexão
Computacional proposta na tese de doutorado de Brian Smith em 82 no MIT.
O conceito foi posteriormente desenvolvido por Gregor Kiczales
introduzindo um modelo OO para reflexão com a linguagem CLOS
descrita no livro The Art of the Metaobject Protocol.
Exemplo:
Considere um sistema em C++ que necessita que seus objetos
sejam guardados
no disco de forma persistente.
Poderíamos iplementar um método para ler e
escrever objetos do disco para cada tipo de objeto: obviamente ruim.
Poderíamos oferecer uma superclasse básica para
objetos persistentes da qual todos os objetos persistentes deveriam
herdar. As subclasses deveriam sobrecarregar os métodos para
leitura e escrita do disco. Problema: mudanças nas classes nos
forçariam a atualizar estes métodos manualmente, ou seja,
persistência e a funcionalidade básica da
aplicação estão fortemente acopladas/misturadas.
Queremos desenvolver um mecanismo de persistência
desacoplado da funcionalidade das aplicações.
Este mecanismo deveria ser capaz de enxergar em tempo de
execução a estrutura interna dos objetos e decidir o que
deve ser armazenado em disco.
Contexto:
Construção de sistemas que permitem, a priori, a
sua
própria modificação.
Problema:
Os requisitos para uma dada aplicação evoluem ao
longo
do tempo.
Forças:
Mudar software convencional (que não está
preparado para mudanças) é muito difícil e sujeito
a erros.
Sistemas de software adaptáveis em geral tem uma
estrutura interna complexa
Quanto maior o número de mecanimos diferentes que
aplicamos em um sistema para torná-lo mais adaptável,
mais complexo ele fica.
As mudanças exigidas podem ser de muitos tipos; desde
adicionar
um pequeno atalho a uma seqüência de comandos até
mudar
completamente uma aplicação para adaptá-la a um
cliente
específico.
Solução:
Faça com que
o software seja ciente de si mesmo (self-aware), que
ele conheça a sua própria estrutura e
que seja possível inspecionar e modificar a sua
estrutura interna e comportamento.
Isso leva a uma arquitetura separada em dois níveis:
nível base e meta-nível.
O meta-nível oferece uma
auto-representação do software para que ele tenha
conhecimento da sua própria estrutura e comportamento. Ele
é composto de meta-objetos.
Os meta-objetos guardam informações
sobre os
tipos utilizados, os algoritmos utilizados, os mecanismos de
comunicação utilizados, os mecanismos de
persistência utilizados, etc.
O nível base define a lógica da
aplicação e é composto pelos objetos da
aplicação. Os objetos utilizam
os meta-objetos para os aspectos não-funcionais.
Por exemplo, para fazer uma chamada a um método de
outro objeto, um objeto usa o meta-objeto de comunicação.
Mudando-se o meta-objeto de comunicação pode-se mudar o
mecanismo de comunicação entre objetos.
Para manipular os meta-objetos usa-se uma interface chamada
de Protocolo dos Meta-Objetos, ou Metaobject Protocol (MOP).
Usando-se o MOP pode-se, por exemplo, criar um novo objeto
para ser o meta-objeto de comunicação e, assim, mudar o
mecanismo de comunicação utilizado.
Outro Exemplo: pode-se implementar um componente
responsável por persistência de objetos no nível
base. Este componente utilizaria um meta-objeto responsável por
informar os detalhes da estrutura de dados de um objeto do nível
básico que deve ser persistido. O componente de
persistência vê quais são os dados a persistir e os
guarda no disco.
Estrutura:
Classe
Objeto do Nível Base
Responsabilidade
Implementa a lógica da
aplicação
Pode usar informações oferecidas
pelo
meta-nível
Colaborador
Meta-Nível
Classe
Objeto do Meta-Nível
Responsabilidade
Encapsula um dos aspectos internos do sistema
que podem mudar
Provê uma interface que permite
modificações em um aspecto do sistema
Colaborador
Nível Base
Classe
MOP
Responsabilidade
Oferece uma interface para efetuar
mudanças no meta-nível
Efetua as modificações solicitadas
Colaborador
Meta-Nível
Nível Base
Usos Conhecidos:
CLOS: uma linguagem de programação reflexiva
(extensão de LISP) de 1989.
MIP: um sistema para inspeção de tipos C++ em
tempo de execução de 1992.
PGen: um sistema para persistência de objetos C++ baseado
em
MIP; de 1994.
NEDIS: um sistema para venda de carros que usa reflexão
para
permitir adaptações para diferentes tipos de
concessionárias e informações específicas
para cada país (p.ex., moeda, língua, cálculo de
impostos).
Apertos:
um sistema operacional reflexivo que usa meta-objetos para controlar as
políticas e mecanismos para gerenciamento de memória,
escalonamento, etc. (Sony Labs, 1992)
dynamicTAO: um ORB CORBA que usa reflexão para controlar
aspectos de segurança, monitoração e
configuração automática de
aplicações CORBA (1999).
Guaraná: uma extensão de Java para permitir
reflexão completa (1999). A "reflexão" de Java permite
apenas introspecção, i.e., pode-se olhar a estrutura do
sistema mas não é possível mexer em nada.
JBoss: um servidor de aplicações.
Smalltalk, Python e Lua (em geral, linguagens dinâmicas
costumam ser reflexivas).
Padrões interessantes no POSA II
No POSA II, Patterns for Networked and Concurrent Objects,
sugiro em
especial, os seguintes padrões que são bem interessantes
e úteis:
Wraper Façade (para esconder sujeira não OO em
baixo de um tapete OO)
Component Configurator (para carga e descarga dinâmica de
componentes)
Interceptor (para interceptar e modificar chamadas a
métodos)
Extension Interface (permite que uma componente exporte
múltiplas interfaces)
Reactor (para receber eventos e reagir a eles demultiplexando e
os repassando aos objetos correspondentes)
Acceptor-Connector (para estabelecer conexões entre dois
pontos da rede (desacopla a conexão do processamento))
Leader-Follower (padrão do ponto de taxi)
Scoped Locking (expressão C++ para bloquear objetos
baseados no escopo de execução)
Thread-Specific Storage
Referências
F. Buschmann, R. Meunier, H. Rohnert, P.Sommerlad, M. Stal Pattern-Oriented
Software Architecture - A System of Patterns. John Wiley and Sons
Ltd, Chichester, UK, 1996