Lincoln S. Rocha (lincoln@great.ufc.br)
POO e suas Limitações
Introdução POA
AspectJ: Conceitos Básicos
Exemplo: Tracing
Padrões de Projeto e POA
Background
Artigo do Kiczales
Objetivo da Programação?
Introdução à OO
Introdução à POO
Limitações da POO
Requisitos Transversais: Exemplos
Rastreamento Usando POO
Problemas com a Abordagem
A Causa dos Problemas da POO
4 record Pessoa nome : string; idade : integer; nascimento : string; end procedure aniversario begin (...) end
Nome Idade Nascimento
Alan Turing 96 23/06/1912 Mapeamento
5
A Orientação a Objetos surgiu no início dos anos 80
Grande evolução desde os Métodos
Estruturados
É uma abordagem para modelagem de
sistemas e um paradigma maduro que continua sendo amplamente utilizado
O paradigma da Orientação a Objetos compreende várias disciplinas
Análise Orientada a Objetos
Projeto Orientado a Objetos
Programação Orientada a Objetos
(...)
7
O princípio da OO é mapear um modelo da realidade, visto como interação entre objetos, num modelo computacional de dados e programas
8
Foco nos dados(objetos) do sistema, não nas funções
Estruturação do programa é baseada nos dados, não nas funções
Princípios Fundamentais 10 Objetos Herança Classes Polimorfismo Abstração Modularidade Encapsulamento Hierarquia Objetos
Entidades que formalizam o modo pelo qual compreendemos algo no domínio de um problema
Em um objeto estão encapsulados os dados (atributos) e os procedimentos (métodos) exclusivos dele
▪Os procedimentos são aplicáveis aos dados residentes
no objeto
11
Objetos (cont.)
Um objeto possui estado, comportamento e identidade
▪Estado: valores dos atributos
▪Comportamento: definido pelos métodos (como o
objeto age e reage)
▪Identidade: aquilo que diferencia um objeto de outro
Classes
Descrevem um conjunto de objetos semelhantes
São templates utilizados para criar objetos
Classes de objetos podem herdar atributos e métodos de outras classes de objetos
13
Objetos versus Classes
Objeto é uma entidade concreta e a Classe é uma abstração
Do ponto de vista de programação
▪Definir uma classe significa formalizar um tipo de dados
e todas as operações associadas a este tipo
▪Declarar objetos significa criar variáveis do tipo definido
14
A POO falha em modularizar requisitos periféricos que atravessam múltiplos módulos (ex., segurança, rastreamento e distribuição)
Esses requisitos ou interesses são chamados de transversais (crosscutting concerns)
A implementação de requisitos transversais se dá através da adição de código em diversos objetos ao longo do sistema
Gera espalhamento
Em geral o código relacionado ao requisito transversal não está diretamente ligado à funcionalidade definida para estes objetos
Gera entrelaçamento 16 Segurança Persistência Auditoria e depuração Tratamento de exceções Otimização e desempenho Concorrência e sincronização
Regras e restrições do negócio
17 Aplicação POA
18
public class Tracing {
public static void entry(String text) { System.out.println("entry: " + text); }
public static void exit(String text) { System.out.println("exit: " + text); }
} public class Person {
private String name = ""; public void setName(String name) {
Tracing.entry("setName("+name+")"); this.name = name; Tracing.exit("setName()"); } ... }
Redundância Fraca coesão Forte acoplamento Dificuldade de compreensão Dificuldade de manutenção Dificuldade de reutilização 19 20 A decomposição primária na POO é feita no plano
O requisito transversal fica
espalhado pelas classes porque é tratado na dimensão errada! Tracing
O requisito transversal é ortogonal à decomposição primária!
Introdução Princípios Básicos Etapas do Desenvolvimento Ingredientes Essenciais Benefício Esperado 22
A POA foi concebida por Gregor Kiczales (1997) quando era o cientista chefe (software design) da Xerox PARC (1996 – 2002) 23
O principal objetivo da POA é facilitar a modularização de interesses transversais (crosscutting concerns)
A POA não veio substituir POO, mas sim complementá-la!
A POA, assim como a POO, é baseada no principio da separação de interesses (separation of concerns) o qual preconiza a identificação e o tratamento individualizado dos diferentes interesses envolvidos no desenvolvimento de um software
1974 - Edsger W. Dijkstra em "On the role of scientific thought“
25
A separação de interesses é um princípio que deve guiar todas as etapas de um processo de desenvolvimento de software
A modularização de interesses transversais deve ser feita através de uma nova unidade de encapsulamento, denominada aspecto
26
Visão geral do processo de desenvolvimento na POA
Classes: encapsulam requisitos funcionais Aspectos: encapsulam requisitos transversais Weaver: entrelaça classes e aspectos num programa
28
Aspectos
Classes Programa
Weaver
Boa modularidade, mesmo quando temos
requisitos transversais
Facilidade de desenvolvimento
Código fonte menos espalho e entrelaçado, mais compacto e mais natural
29
Facilidade de manutenção
Mais fácil para entender, depurar e modificar Facilidade de reutilização
Hierarquia de aspectos, biblioteca de aspectos e aspectos “plug and play”
31
O que é AspectJ ?
Aspectos versus Classes
Joinpoints e Pointcuts
Advices e Introductions
Reflexão e Reusabilidade
32
É uma extensão de Java, orientada a aspectos
É um weaver que implementa POA em Java
É um pré-processador
“Fácil” de aprender e utilizar
Disponível gratuitamente http://eclipse.org/aspectj
Aspectos são similares a classes
Têm um tipo
Podem ser estendidos
Podem ser abstratos ou concretos
Podem conter atributos, métodos e tipos como membros
34
Aspectos são diferentes de classes
Não têm construtor, nem destrutor
Não podem ser criados com o operador new
Podem conter pointcutse advicescomo membros
Podem acessar membros de outros tipos
35
São pontos, bem definidos, na execução de um programa, onde aspectos podem interceptar classes 36 Objeto Método Execução de método Chamada de método get set Acesso a atributo Atributo
São identificados por designadores call(Signature) execution(Signature) initialization(Signature) preinitialization(ConstructorPat) staticinitialization(TypePat) handler(TypePattern) get(Signature) set(Signature) 37 args(TypePattern, ...) within(TypePattern) cflow(PointCut) cflowbelow(Pointcut) if(Expression) adviceexecution() this(TypePattern) target(TypePattern) 38
Designadores podem ser genéricos call(* set*())
call(public Person.*(..))
call(void foo(..))
call(* *(..))
Predicados que definem conjuntos de joinpoints
40 pointcut traced() : call(public * set*(..));
Podem ser definidos como expressões booleanas, empregando-se !, && e ||
41 pointcut traced() : call(public * set*(..)) ||
call(public * get*(..));
Pointcuts também podem ter argumentos
42 pointcut traced(Person p) : target(p) &&
call(public * set*(..)) || call(public * get*(..));
São trechos de código associados a pointcuts, que injetam um novo comportamento em todos os joinpoints representados pelo pointcut
Tipos before after around 43 chamado chamador After advice Before advice Formas básicas before(param) : pointcut(param) {...} after(param) : pointcut(param) {...}
after(param) returning [formal] : pointcut(param) {...}
after(param) throwing [formal] : pointcut(param) {...}
type around(param) [throws typelist] : pointcut(param) {...}
44
pointcut get(intindex) : args(index) && call(* get*(..));
before(intindex) : get(index) { System.out.println(index); }
Designador
Pointcut
É uma variável especial predefinida
É similar à variável this em Java
Disponibiliza várias informações a respeito do joinpoint que disparou o advice
Exemplos:
thisJoinPoint.toString() thisJoinPoint.getArgs()
46
Um forma de introduzir novos membros a classes e interfaces já existentes
47
private int Person.id = 0; public void Person.setId(int id){
this.id = id; }
public int Person.getId(){ return this.id; }
declare parents: Person extends Animal;
48
public abstract aspect Tracing { protected abstract pointcut trace();
// advice code
}
public aspect MyTracing extends Tracing {
// just define which calls to trace
protected pointcut trace(): call(* set*(..)); }
49
50
public class Person { private String name = ""; public void setName(String name) {
this.name = name; }
... }
class Tracing {
public static void entry(String text) { System.out.println("entry: " + text); }
public static void exit(String text) { System.out.println("exit: " + text); }
}
aspect Tracing {
pointcut trace () : call(public * Person.set*(..)); before() : trace() { Tracing.entry(thisJoinPoint.toString()); } after() : trace() { Tracing.exit(thisJoinPoint.toString()); }
52
public class Application {
public static void main(String[] args) { Person person = new Person(); person.setName("Lincoln Souza Rocha"); }
}
entry: call(void Person.setName(String)) exit: call(void Person.setName(String))
53
Padrões de Projeto - GoF
Descrição do Experimento
Resultados
Análise dos Resultados
GoF(Gang Of Four) Design Patterns
E. Gamma, R. Helm, R Johnson, J. Vlissides
Catálogo com 23 padrões de projeto
Documenta a essência de soluções comprovadas para problemas recorrentes
Considerados como soluções úteis para certo tipo de problemas de projeto
55
Três maiores desafios na implementação de padrões de projeto
Problema de “desaparecimento no código”
▪Isso dificulta a distinção entre o padrão e o modelo de objeto envolvido
Problema de documentação
▪Por causa da natureza invasiva do código do padrão é difícil rastrear uma instância particular se muitos padrões são usados
Problema de composição
▪É difícil raciocinar sobre sistemas que envolvem múltiplos padrões nas mesmas classes
56
Desenvolver e comparar implementações dos
padrões GoF em Java e AspectJ observando
Estruturas transversais entre regras e classe participantes existentes
Melhorias de modularização das estruturas transversais na implementação dos padrões 17 dos 23 padrões implementados em AspectJ foram
Uma análise comparativa entre implementações em Java e AspectJ dos padrões de projeto GoF
As implementações Java correspondem aos exemplos de implementações em C++ do livro do GoF
As implementações em AspectJ foram selecionadas entre 57 implementações diferentes para investigar plenamente a concepção de projeto de cada padrão
58
59 O padrão Observer descreve como estabelecer estes relacionamentos
- O Subject pode ter algum número de Observers dependentes
- Todos Observers são notificados quando o Subject sofre uma alteração no seu estado - Cada Observer irá consultar o Subject para sincronizar seu estado com o estado do Subject
Implementação em Java
60 1 - O código está espalhado pelas várias classes 2 - Todos os participantes têm que saber sua função no padrão
Mudanças requerem alterações em todas as classes participantes - Adicionando ou removendo regra - Usando um mecanismo de notificação alternativo
Implementação em AspectJ
Aspecto Abstrato Subaspecto Concreto Partes comuns a todas implementações
1 - Existencia de regras para Subject e Observer 2 - Manutenção do mapeamento de Sbjects para Observer
3 - Lógica de atualização: Mudanças no Subject dispara atualização do Observer
Partes específicas de cada implementação
1 - Dar função a cada classe 2 - Conjunto de mudanças que intereção o Subject
3 - Meios de atualizar cada Observer
61
Partes comuns a todas implementações
1 - Existencia de regras para Subject e Observer 2 - Manutenção do mapeamento de Sbjects para Observer
3 - Lógica de atualização: Mudanças no Subject dispara atualização do Observer
Aspecto Abstrato
Subaspecto Concreto Partes específicas de cada implementação
1 - Dar função a cada classe 2 - Conjunto de mudanças que intereção o Subject
Melhorias de implementação com AspectJ
Localidade
▪Todo o código relacionado com a implementação do padrão está nos aspectos abstrato e concreto
▪Não existe acoplamento entre classe participantes existentes Reusabilidade
▪O código núcleo do padrão (ObserverProtocol) é abstraído e passível de reuso
▪Para cada instancia do padrão, define-se somente um aspecto concreto Transparência de composição
▪Mesmo que uma classe seja participante em vários relacionamentos de padrões, os códigos da classe e do padrão não serão confundidos (Un)pluggability
▪Os participantes não precisam estar cientes de seu papel ▪É fácil alternar entre usar e não usar o padrão
64
Composite, command, mediator, chain of
responsibility
Papéis usados somente dentro dos aspectos Singleton, prototype, memento, iterator,
flyweight
Aspectos como fábricas de objetos
Adapter, decorator, strategy, visitor, proxy
Construtores de linguagem (AspectJ já da suporte direto)
65
Abstract factory, factory method, template method, builder, bridge
Herança múltipla State, interpreter
Parte do código espalhado pode ser modularizado Façade
Não apresentou benefícios usando AspectJ na implementação
A análise foi dividida em três partes
Melhorias gerais observadas na re-implementação dos padrões
Melhorias específicas associadas à padrões particulares
Origem de estruturas transversais em padrões
▪Foi observado melhorias relacionada a presenças de
estruturas transversais em implementações AspectJ
67
Melhorias gerais
Localidade
▪17 dos 23 padrões do GoF
▪Todas as dependencias entre padrões e participantes
foram localizadas no código do padrão
Reusabilidade
▪ 12 dos 17 padrões que tiveram a localidade melhorada
▪Pela separação do código específico do padrão, o
participante e o padrão podem ser reusados em outros contextos
68
Melhorias gerais (cont.)
Transparencia de composição
▪14 dos 17 padrões que tiveram a localidade melhorada
▪Classes ou objetos podem ter diferentes papéis em
diferentes instancias do padrão sem confusão
Melhorias específicas
Singleton
▪Implementação do Singleton como propriedade através
de herança ou simplesmente através de uma implementação do Factory Method
Herança múltipla e Java
▪AspectJ provê uma alternativa para implementação de
padrões tendo herança múltipla com composição transparente
70
Melhorias específicas (cont.)
Quebra de dependências cíclicas
71
Estruturas transversais de padrões de projeto
A transversalidade em estruturas de padrões é causada pelos diferentes tipos de papéis e suas interações entre os participantes
Papéis
▪Definindo papéis - define os participantes
completamente
▪Papéis sobrepostos - atribuídos às classes
▪Papéis transversais as classes participantes
▪Operações conceituais de interesse de métodos transversais
▪Papéis de múltiplos padrões transversais entre si
Estruturas transversais de padrões de projeto (cont.)
73
Hannemann, J., Kiczales, G.. Design Pattern Implementation in Java and AspectJ, 2002.
Kendall, E. A. Aspect-Oriented Programming in AspectJ, 2001.
Kiczales, G. et all. Aspect-Oriented Programming, 1997. Kiczales, G. et all. An Overview of AspectJ, 2002. Voelter, M. Aspect-Oriented Programming in Java, 2000. The AspectJ Programming Guide, Xerox Corporation,
2002.
74
Lincoln S. Rocha (lincoln@great.ufc.br)