• Nenhum resultado encontrado

Programação Orientada a Aspectos - Técnicas e paradigmas para a modularização de software

N/A
N/A
Protected

Academic year: 2021

Share "Programação Orientada a Aspectos - Técnicas e paradigmas para a modularização de software"

Copied!
161
0
0

Texto

(1)

e paradigmas para a modularização de

software.

Dissertação de Mestrado apresentada por

Luís Filipe Félix de Sá

Sob orientação do Prof. Doutor Ramiro Gonçalves e do

Prof. Doutor Carlos Rabadão

Universidade de Trás-os-Montes e Alto Douro

Departamento de Engenharias

(2)

"Controlling complexity is the essence of computer programming." (Brian Kernigan)

(3)

Dissertação apresentada por Luís Filipe Félix de Sá à Universidade de Trás-os-Montes e Alto Douro para cumprimento dos requisitos necessários à obtenção do grau de Mestre em Informática, sob a orientação do Prof. Doutor Ramiro Manuel Ramos Moreira Gonçalves, Professor Auxiliar do Departamento de Engenharias da Universidade de Trás-os-Montes e Alto Douro e co-orientada pelo Prof. Doutor Carlos Manuel da Silva Rabadão, Professor Adjunto do Departamento de Engenharia Informática da Escola Superior de Tecnologia e Gestão do Instituto Politécnico de Leiria.

(4)
(5)

AGRADECIMENTOS

A todos os meus amigos e colegas Francisco Silva, Marta Pimenta, Diana Santos, Isabel Marcelino, Andreia Penedo, Ana Oliveira, Rúben Pedro, Rodrigo Selada, Bruno Alves, Márcia, Tiago Conde pela amizade, dedicação e apoio constantes.

Aos meus orientadores Professor Doutor Ramiro Gonçalves e Professor Doutor Carlos Rabadão e Co-Orientador Professor Marco Monteiro, pela partilha de conhecimentos e experiência.

A todos o meu muito obrigado! Luís Filipe Félix de Sá

(6)

RESUMO

O desenvolvimento de software é uma tarefa complexa, onde se decompõe um problema localizando todas as suas preocupações. As tecnologias existentes para a implementação destas são limitadas devido à sua inadequação para as modularizar. Assim, deu-se o aparecimento de uma nova tecnologia, a Programação Orientada a Aspectos. Esta tecnologia não vem substituir mas sim estender as tecnologias existentes, melhorando-as, permitindo novas formas de modularidade, diminuindo o tempo de desenvolvimento e aumentando a reutilização de software.

(7)

ABSTRACT

Software development is a complex task, where a problem is decomposed identifying all its concerns. The current technologies for implementing them are unable to modularize all of them. Therefore, a new technology was developed, Aspect Oriented Programming. This technology doesn’t come to replace rather to improve current technologies, with new ways to achieve software modularity, resulting in a decrease of developing time and increased software reuse.

(8)

INDICE GERAL

AGRADECIMENTOS ... V RESUMO ... VI ABSTRACT ... VII INDICE GERAL ... VIII LISTA DE TABELAS ... XII LISTA DE FIGURAS ... XIII ACRÓNIMOS ... XV

1. INTRODUÇÃO ... 1

1.1 ENQUADRAMENTO TECNOLÓGICO ... 2

1.2 OBJECTIVOS E CONTRIBUTOS FUNDAMENTAIS ... 4

1.3 ESTRUTURAÇÃO DA DISSERTAÇÃO ... 5

2. TÉCNICAS E PARADIGMAS DA PROGRAMAÇÃO ... 7

2.1 PARADIGMA DE PROGRAMAÇÃO... 7

2.2 LINGUAGEM DE PROGRAMAÇÃO ... 8

2.3 FORMAS DE SEPARAÇÃO ... 8

2.3.1 Abstracção ... 9

(9)

2.3.3 Encapsulamento ... 10

2.4 PROGRAMAÇÃO ESTRUTURADA ... 10

2.5 PROGRAMAÇÃO ORIENTADA A OBJECTOS ... 13

2.5.1 Linguagens POO ... 14

2.6 PROGRAMAÇÃO ORIENTADA A COMPONENTES ... 15

2.7 PROGRAMAÇÃO PÓS-OBJECTOS ... 18

2.8 META-PROGRAMMING ... 21

2.9 SUBJECT-ORIENTED PROGRAMMING ... 22

2.10 PROGRAMAÇÃO ADAPTATIVA ... 24

2.11 FILTROS DE COMPOSIÇÃO ... 25

2.12 PROGRAMAÇÃO ORIENTADA A ASPECTOS. ... 26

2.12.1 AspectJ ... 28

2.13 SEPARAÇÃO MULTIDIMENSIONAL DE CONCERNS ... 33

2.14 DESENVOLVIMENTO DE SOFTWARE ORIENTADO A ASPECTOS .. 34

2.15 COMUNIDADES E SITUAÇÃO EM PORTUGAL ... 35

2.16 DESAFIOS, PROBLEMAS E OPORTUNIDADES ... 36

3. PROGRAMAÇÃO ORIENTADA A ASPECTOS ... 39

3.1 COMPORTAMENTOS GLOBAIS ... 39

3.2 ANÁLISE DO PROBLEMA ... 41

3.3 SISTEMA MODULAR ... 46

3.4 SISTEMA POA ... 47

3.5 METODOLOGIA DSOA ... 49

(10)

3.7 ESPECIFICAÇÃO DAS LINGUAGENS ... 51 3.7.1 Software concerns ... 51 3.7.2 Regras de combinação ... 51 3.8 COMPOSIÇÃO DE SISTEMAS... 52 3.8.1 Weaving ... 52 3.8.2 Weaver ... 53 3.9 BENEFÍCIOS DA POA ... 57

3.10 DESENVOLVIMENTO DE SOFTWARE ORIENTADO A ASPECTOS .. 59

3.10.1 Identificação de concerns ... 60

3.10.2 Implementação ... 60

3.11 DEVENVOLVIMENTO UTILIZANDO ASPECTJ... 61

3.11.1 Análise ... 62 3.11.2 @AspectJ ... 62 3.11.3 Ferramentas de Desenvolvimento ... 63 3.12 POSTSHARP ... 63 3.12.1 PostSharp LAOS ... 65 3.12.2 Análise da Tecnologia ... 67 3.12.3 PostSharp Core ... 69

3.12.4 AspectJ vs. Postsharp LAOS ... 69

3.12.5 Conclusões ... 73

3.13 MODULARIZAÇÃO DE PADRÕES DE DESENHO ... 74

3.13.1 Exemplo Observer Pattern. ... 76

(11)

3.14 MODULARIZAÇÃO DE EXCEPÇÕES ... 78 3.15 FRAMEWORKS ... 81 3.16 MÉTRICAS ... 81 4. CONSIDERAÇÕES FINAIS ... 86 5. BIBLIOGRAFIA ... 90 6. ANEXOS ... 95

(12)

LISTA DE TABELAS

Tabela 1 – Cronograma temporal da investigação sobre separação de concerns ... 20

Tabela 2 - comparação da nomenclatura do AspectJ e Postsharp Laos. ... 65

Tabela 3 – Comparação de pointcuts entre PostSharp Laos e AspectJ ... 71

Tabela 4 - Comparação de pointcuts entre PostSharp Laos e AspectJ ... 71

Tabela 5 – comparação de tipos ... 71

Tabela 6 – Resumo das comparações dos padrões de desenho. ... 77

Tabela 7 – Evolução da utilização de POO e POA, segundo as métricas de Sant’Anna... 83

Tabela 8 - Comparação de métricas entre Java e AspectJ primeira parte. ... 85

(13)

LISTA DE FIGURAS

Figura 1 - Módulos com acesso concorrente aos dados. ... 12

Figura 2 - Hierarquia de classes ... 13

Figura 3 – Espalhamento de Concerns. ... 19

Figura 4 - Meta-programming. ... 22

Figura 5 - Subject-oriented programming. ... 23

Figura 6 - Filtros de composição. ... 26

Figura 7 – Diagrama do exemplo. ... 30

Figura 8 - Interacção entre Módulos. ... 40

Figura 9 - Sobreposição de unidades elementares. ... 40

Figura 10 - Comportamentos Globais do Sistema ... 41

Figura 11 - Metodologia POA. ... 50

Figura 12 – Weaver de código fonte. ... 53

Figura 13 - Weaver de código intermédio... 54

Figura 14 - Comunicação normal entre objectos. ... 55

Figura 15 - Comunicação utilizando uma proxy. ... 56

(14)

Figura 17 - Sistema de Desenvolvimento de Software Orientado a Aspectos. ... 59

Figura 18 – Incisão do estudo de Early-Aspects. ... 60

Figura 19 – Processo de integração do Postsharp. ... 64

Figura 20 – Padrão de Desenho Observer implementado em POO ... 75

Figura 21 – Padrão de desenho Observer implementado em POA ... 76

(15)

ACRÓNIMOS

Ao longo desta dissertação vão ser utilizadas algumas abreviaturas e designações que apenas serão apresentadas quando forem utilizadas pela primeira vez:

POA Programação Orientada a Aspectos POO Programação Orientada a Objectos

DSOA Desenvolvimento de Software Orientado a Aspectos POC Programação Orientada a Componentes

GOF Padrões de Desenho Gang-of-Four JVM Java Virtual Machine

IDE Intregrated Development Envionment CME Concern Manipulation Envionment

(16)

1. INTRODUÇÃO

Em 1997 foi proposto um novo paradigma de programação, a Programação Orientada a Aspectos (POA), cujo principal objectivo era apresentar uma extensão aos paradigmas existentes até à data, retendo os pontos onde estes demonstraram a sua eficiência, o desenvolvimento das funcionalidades base de um sistema. Apresentando uma nova forma de modularidade onde os antigos paradigmas manifestavam reais fragilidades, esta nova extensão incide especialmente nos comportamentos transversais ao sistema (crosscutting concerns) [Kiczales, Lamping et al. 1997]. Este novo paradigma propõe a decomposição dos sistemas pelas suas variadas preocupações dividindo o software em concerns (preocupações) base (funcionalidades base do sistema) e transversais (funcionalidades globais ao sistema). É introduzido um novo conceito, o aspecto, que consiste numa unidade modular que possui uma visão global do sistema, o que lhe permite fazer a coordenação e comunicação entre concerns. Para estes, este processo é transparente. A transferência da coordenação e comunicação entre diferentes tipos de concerns para os aspectos, permite-os libertar de questões globais ao sistema tornando-os independentes.

A composição de concerns é efectuada através de um compilador, Weaver, cujo resultado é um sistema onde existe uma clara separação e abstracção entre todos os concerns que definem o comportamento do sistema. O sistema torna-se claro de ler, escrever e manter, as

(17)

funcionalidades adicionais são simples de acoplar ao sistema e o desenho inicial é mais consistente com a sua implementação concreta.

Outras tecnologias com objectivos semelhantes foram desenvolvidas: Programação Adaptativa [Lieberherr 1996], Filtros de Composição [Mehmet Aksit 1994], Subject Oriented Programming [Harrison and Ossher 1993], Separação Multidimensional de Concerns [Tarr, Ossher et al. 1999] e Programação Gerativa [Czarnecki, Eisenecker et al.].

A separação avançada de concerns12, a Programação Pós-Objectos [Elrad, Filman et al. 2001; Hayes 2003] e o Desenvolvimento de Software Orientado a Aspectos3 4 (DSOA) são as áreas de investigação em que a POA se enquadra.

1.1 ENQUADRAMENTO TECNOLÓGICO

A separação de concerns é um princípio fundamental que determina a resolução de um concern de cada vez [Dijkstra 1976]. Em engenharia de software, o princípio da sua separação está normalmente relacionado com a decomposição e modularização de sistemas [Parnas 1972]: os sistemas de software complexos devem ser decompostos em unidades modulares menores e claramente separadas, cada uma lidando com um único concern. Sendo de destacar como benefícios a sua melhor compreensibilidade e um maior potencial para a evolução e reutilização em outros sistemas de software complexos. Os mecanismos de composição e abstracção que sucessivas gerações de linguagens de programação oferecem, evoluíram para permitir a

1

http://www.cs.ubc.ca/~kdvolder/Workshops/OOPSLA2001/ASoC.html (Acedido, Julho 2008) 2

http://www.research.ibm.com/hyperspace/workshops/icse2001/index.htm (Acedido, Julho 2008) 3

http://www.aosd.net/ (Acedido, Julho 2008) 4

(18)

resolução de problemas do mundo real de forma mais natural, assim como, para possibilitar o alcance da separação de concerns ao nível do código-fonte. A Programação Orientada a Objectos (POO) tem sido a tecnologia de programação dominante sendo os seus benefícios amplamente reconhecidos. No entanto, a POO possui algumas limitações no tratamento de concerns, nomeadamente no que respeita aos requisitos que envolvam restrições globais e propriedades sistémicas, como é exemplo: a sincronização, a persistência, o tratamento de erros, entre outros. Estas limitações necessitam de uma tecnologia que permita uma rotura, ou seja, algo que esteja realmente para além dos objectos [Booch 2001].

Relativamente à POA, esta é uma tecnologia em evolução que oferece suporte a um novo tipo de separação de concerns no nível do código-fonte. É vista como sendo evolucionária porque considera as melhorias reconhecidas da sua separação, proporcionadas pelas tecnologias anteriores (principalmente, mas não apenas, a POO) enquanto oferece suporte a novos mecanismos para lidar com alguns concerns especiais que não são tratados adequadamente por essas tecnologias. A ideia central por trás da POA é que os mecanismos de abstracção e composição das tecnologias existentes não são suficientes para separar alguns concerns especiais encontrados em sistemas mais complexos. Denominados de crosscutting concerns, pois afectam a modularidade de vários elementos “penetrando" os seus limites, estes, sem os meios apropriados para a separação e a modularização, tendem a ficar espalhados e entrelaçados com outros concerns. Como consequências naturais reporte-se uma menor compreensibilidade, uma menor capacidade de evolução e uma menor reutilização dos artefactos do código. Esta tecnologia utiliza aspectos para alcançar a modularização de crosscutting concerns e fornece mecanismos para a sua combinação em pontos bem definidos.

(19)

A POA e a maioria dos trabalhos existentes sobre a separação avançada de concerns tratam do fenómeno de crosscutting no nível de implementação, tendo recentemente muitos grupos de pesquisa começado a discutir a função dos aspectos em outras actividades do processo de desenvolvimento de software. Deste modo, o Desenvolvimento de Software Orientado a Aspectos (DSOA) revela-se uma área emergente cujo objectivo, é promover a separação avançada de concerns ao longo de todo o ciclo de vida do desenvolvimento de software. O Design Orientado a Aspectos (DOA) é assim, uma parte crítica do DSOA que se concentra em notações, técnicas e ferramentas para a identificação, a estruturação, a representação e a gestão de crosscutting concerns no projecto e arquitectura de software, oferecendo um linhagem desde os requisitos até a implementação com POA.

1.2 OBJECTIVOS E CONTRIBUTOS FUNDAMENTAIS

O principal objectivo deste projecto de investigação é apresentar um documento, com vista a descrever paradigmas e técnicas que se propõem a melhorar a separação de concerns. São expostas as desvantagens da sua não separação, como é possível alcançar essa separação enumerando as suas vantagens e desvantagens. Este trabalho propõe-se ainda a detalhar princípios, metodologias e práticas de algumas linguagens e tecnologias POA, recorrendo à exemplificação prática, a exemplos de aplicações dessas tecnologias e à apresentação de estudos de investigação sobre análise de resultados empíricos, utilizando métricas bem conhecidas e documentando as principais ferramentas, linguagens e a sua forma de utilização.

(20)

1.3 ESTRUTURAÇÃO DA DISSERTAÇÃO

Inicia-se este trabalho com uma pequena apresentação deste estudo, seguindo-se o seu enquadramento, bem como, os objectivos definidos para o seu prosseguimento. Desta forma no Capitulo 2 apresenta-se uma breve evolução das várias técnicas e paradigmas que contribuíram para o aparecimento e desenvolvimento do Paradigma Orientado a Aspectos. Descrevendo-se as técnicas e tecnologias que com mais ou menos complexidade permitem alcançar uma melhor modularidade nos sistemas de software. No Capítulo 3 é desenvolvido de forma prática o Paradigma Orientado a Aspectos, linguagens de programação e aplicações práticas do paradigma. Apresenta-se o Paradigma Orientado a Aspectos, o que é, que problemas se pretendem resolver e como pode ser implementado. É apresentada a linguagem AspectJ e, de seguida, a tecnologia PostSharp. Algumas aplicações da Programação Orientada a Aspectos nomeadamente a modularização de padrões de desenho, a modularização de excepções e estudos que apresentam métricas para possibilitar a quantificação empírica de programas POA também são apresentadas e descritas. Finalmente no 4º e último Capítulo exibem-se as principais conclusões deste projecto de investigação.

(21)
(22)

2. TÉCNICAS E PARADIGMAS DA PROGRAMAÇÃO

No âmbito do objectivo deste trabalho de projecto, procurou-se aprofundar os conhecimentos relativos às diversas técnicas e paradigmas que possibilitam resolver o problema da separação de concerns. Para este fim tornou-se necessário a análise de uma variadíssima fonte bibliográfica alusiva a esta temática, possibilitando-nos assim, expor uma visão mais holística do estudo aqui em análise.

2.1 PARADIGMA DE PROGRAMAÇÃO

Um paradigma da programação pode ser definido como um “…conjunto de teorias e métodos que representam uma forma particular de se tentar organizar o conhecimento numa dada área” [Kuhn 1970], ou como, “modelos ou exemplos, e abordagens organizacionais, que permitem conceptualizar o que se deve entender por computações, bem como se devem estruturar e organizar as tarefas que se pretendem ver realizadas por um computador” [Floyd 1979]. Um paradigma da programação permite disponibilizar ao programador uma visão e uma forma de raciocinar de modo a que este consiga desenvolver e executar um programa de computador, podendo-se definir este último, como uma colecção de instruções na forma de

(23)

código e de variáveis que possibilitam a um computador manipular uma determinada informação. No âmbito deste projecto entende-se paradigma segundo a visão de Floyd.

2.2 LINGUAGEM DE PROGRAMAÇÃO

Uma linguagem de programação possibilita que um programador especifique precisamente sobre quais dados, um computador vai actuar, como estes deverão ser armazenados ou transmitidos e que acções devem ser tomadas sob as mais variadas circunstâncias. Assim, linguagem de programação é entendida como um método normalizado para expressar instruções para um computador, ou seja, é um conjunto de regras sintácticas e semânticas usadas para definir um programa de computador.

2.3 FORMAS DE SEPARAÇÃO

A evolução das linguagens de programação permitiu abstrair os programadores dos pormenores das plataformas e das máquinas em que os programas são executados, possibilitando mecanismos superiores de composição e abstracção, onde estes se ajustam aos problemas de uma forma mais natural, numa visão centrada no problema. Esta visão permite uma separação natural do problema por todos os seus concerns [Dijkstra 1976].

A separação de um sistema de software em módulos aumenta a flexibilidade, a compreensibilidade e diminui o tempo de desenvolvimento. Um módulo pode ser assim entendido como um pedaço de software independente, que faz parte de um programa de

(24)

computador, funcionando como uma caixa negra onde do exterior só é possível interagir com a sua interface (forma de ligação com o interior) [Parnas 1972].

Nesta continuidade, os módulos independentes podem ser desenvolvidos separadamente com informação mínima sobre outros módulos. As equipas de desenvolvimento que são atribuídas a cada módulo focam-se na sua especialidade (segurança, base de dados, etc.), o que provoca uma diminuição do tempo de desenvolvimento. Os módulos internamente podem ser redesenhados e implementados novamente para acomodar as alterações necessárias, sem que isto afecte o sistema, tornando-o flexível à evolução. A possibilidade de analisar e desenhar o sistema módulo a módulo torna-o mais compreensível. A sua separação pode ser alcançada através de vários conceitos tais como abstracção, ocultação de informação e encapsulamento como se poderá verificar nas secções seguintes.

2.3.1 Abstracção

Estabelecida como um processo que extrai detalhes importantes de um item e suprime os não importantes, a abstracção também pode ser vista como um modelo ou visão que representa um item - por exemplo, as pessoas podem dizer “diga-me só os pontos-chave”, este facto representa uma forma de abstracção. Podemos ver abstracção como uma técnica que dita que informação é mais importante que outra, mas não especifica como lidar com a menos importante [Berard 2002].

(25)

2.3.2 Ocultação de informação

O conceito de ocultação de informação para a construção de módulos é comum ser confundido com abstracção. Como anteriormente referido, a abstracção permite identificar a informação e posteriormente ocultar a menos importante, utilizando para este efeito técnicas de ocultação de informação disponibilizadas pelas linguagens de programação (funções, subrotinas, classes, etc.) [Berard 2002].

2.3.3 Encapsulamento

Designa-se por encapsulamento o agrupamento de um ou mais itens, não sendo definido a forma como ele é delimitado. Este processo não é o mesmo que o da ocultação de informação. Embora a informação esteja encapsulada, esta pode não estar escondida - por exemplo, uma estrutura encapsula uma determinada quantidade de informação mas esta pode ainda ser cedida, embora possam ser definidas regras para restringir esse acesso. Dito isto, o encapsulamento permite agrupar informação e definir qual ocultar ou qual tornar visível [Berard 2002].

2.4 PROGRAMAÇÃO ESTRUTURADA

Tendo-se iniciado para efectuar cálculos numéricos, os programas de computador começaram por ser desenvolvidos em código máquina através da introdução de novas linguagens de programação, entre elas o Fortran [Backus, Beeber et al. 1957], tornando possível elaborar sistemas de software mais complexos sem recorrer a este intrincado código.

(26)

Com o aumento da complexidade do processo de desenvolvimento de software levantaram-se problemas de fiabilidade e adaptabilidade, sugerindo-se assim, a eliminação das instruções goto das linguagens de programação de alto nível, substituindo-as por estruturas de sequência, de divisão e de iteração [Dijkstra 1968]. A utilização das instruções goto pode ter efeitos devastadores uma vez que podem surgir problemas devido ao facto de esta instrução alterar o fluxo do programa. Todavia, o seu comportamento não pode ser avaliado ao longo da fase de implementação utilizando um conjunto de manipulações matemáticas e lógicas que permitam demonstrar a existência de erros [Dijkstra 1976].

Enumeram-se assim, como principais Linguagens de Programação Estruturada: Fortran [Backus, Beeber et al. 1957], Pascal [Wirth 1971] e C [Kernighan and Ritchie 1988].

As principais características da Programação Estruturada consistem em:

• design descendente: decompõe-se o problema por etapas ou estruturas hierárquicas;

• recursos abstractos (simplicidade): consiste em decompor acções complexas noutras mais simples, capazes de serem resolvidas com maior facilidade, ou seja, as acções complexas são abstraídas em subrotinas ou em funções;

• estruturas básicas:

o estrutura sequencial: a cada acção segue-se outra acção sequencialmente, isto é, a saída de uma acção é a entrada em outra acção;

o estruturas de divisão: avaliam condições lógicas e, em função do resultado das mesmas, realizam uma acção ou outra;

o estruturas de iteração: são sequências de instruções que se repetem um determinado número de vezes.

(27)

Para melhor alcançar a separação de concerns foi sugerida a introdução de critérios para a decomposição do sistema em módulos de maneira a permitir uma melhor flexibilidade e compreensibilidade do sistema, definindo quais os métodos mais efectivos da decomposição em módulos utilizando técnicas de abstracção e ocultação de informação fornecidas pela Programação Estruturada [Parnas 1972].

Todavia é de referir a existência de problemas na Programação Estruturada, sendo de destacar: o código espalhado das invocações aos vários módulos independentes, bem como, o facto de os módulos abstraírem os procedimentos, as instruções, mas não conseguirem abstrair o acesso aos dados (figura 1) resultando tal situação em programas maiores, menos flexíveis e mais difíceis de desenvolver e de reutilizar ao longo do tempo.

Figura 1 - Módulos com acesso concorrente aos dados. (Adaptada de [Booch 1994])

(28)

2.5 PROGRAMAÇÃO ORIENTADA A OBJECTOS

Nesta visão, o programa descreve estruturas e comportamentos de objectos e classes de objectos. Um objecto encapsula dados passivos e disponibiliza operações activas sobre esses dados, a estrutura dos dados do objecto define o seu estado e os métodos definem o seu comportamento. A execução de um programa orientado a objectos é a troca de mensagens entre objectos que modificam o seu estado [Booch 1994].

Na POO o problema é decomposto em classes e em objectos pertencentes ao domínio do problema, onde os dados e os procedimentos já não estão separados e os detalhes da sua interacção são encapsulados em objectos [Booch 1994].

Alguns fundamentos da POO são a herança e o polimorfismo, onde a primeira possibilita aos objectos herdar propriedades, permitindo a reutilização de comportamentos, de outros objectos. A existência de hierarquia de objectos (figura 2) facilita a compreensão do problema e, através do polimorfismo, permite-se o tratamento desses objectos de forma igual. O encapsulamento faculta assim a modificação do conteúdo interno dos objectos sem que essas alterações afectem outros objectos.

(29)

Em suma, alguns princípios usados na POO são:

o Princípio open closed: especifica que o desenho e desenvolvimento do código deve permitir a extensão de novas funcionalidades (open) e minimizar alterações aos módulos existentes (closed). O sistema abre-se a novas funcionalidades mas deve estar encerrado a alterações que provocam incompatibilidades a módulos existentes;

o Princípio da substituição de Liskov [Liskov and Wing 2001]: possibilita substituir referências de classes base por uma outra classe que derive desta sem afectar o normal funcionamento do módulo;

o Princípios da inversão da dependência: módulos hierarquicamente superiores não devem depender de módulos hierarquicamente inferiores. Todos devem depender de abstracções e esta última não deve depender de detalhes. Enquanto que os detalhes devem depender de abstracções.

2.5.1 Linguagens POO

Remontando à história da Linguagens POO dá-se especial destaque aos inícios dos anos 60 com o aparecimento da linguagem de programação Simula 67, criada por Ole-Johan Dahl e Kristen Nygaard. Nos anos 70 inicia-se o desenvolvimento do Smalltalk na Xerox PARC, alguns anos depois Bjarne Stroustrup cria o C++ e finalmente na década de 90 foi criado na empresa Sun o Java por James Gosling.

(30)

2.6 PROGRAMAÇÃO ORIENTADA A COMPONENTES

A Programação Orientada a Componentes (POC) permite elaborar programas a partir de componentes de software pré-fabricados contidos em blocos de código executáveis. Os componentes têm de seguir padrões específicos predefinidos, incluindo a inclusão de uma interface e uma gestão de versões para garantir uma boa reutilização.

O objectivo da POC, passa assim por desenvolver software combinando componentes pré-fabricados. Enquanto a POO dá ênfase a classes e objectos, a POC enfatiza interfaces e composição. Os clientes dos componentes não necessitam de possuir conhecimentos de como é que um componente é implementado, enquanto as interfaces de ligação continuam inalteradas, os clientes não serão afectados por alterações na implementação do componente [Szyperski 1998].

Brown sumaria algumas definições do que é um componente [Brown and Wallnau 1998]: “A component is a nontrivial, nearly independent, and replaceable part of a system that fulfills a clear function in the context of a well-defined architecture. A component conforms to and provides the physical realization of a set of interfaces.” (Philippe Krutchen, Rational Software)

“A runtime software component is a dynamically bindable package of one or more programs managed as a unit and accessed through documented interfaces that can be discovered at runtime.” (Gartner Group)

“A software component is a unit of composition with contractually specified interfaces and explicit context dependencies only. A software component can be deployed independently and is subject to third-party composition.” (Clemens Szyperski)

(31)

“A business component represents the software implementation of an “autonomous” business concept or business process. It consists of the software artifacts necessary to express, implement, and deploy the concept as a reusable element of a larger business system.” (Wojtek Kozaczynski, SSA)

“A software component is a piece of self-contained, self-deployable computer code with well-defined functionality and can be assembled with other components through its interface.” [Brown and Wallnau 1998]

Um componente de software é um bloco de código executável, pronto a usar, com funcionalidades bem definidas, que pode ser combinado com outros componentes através de uma interface.

Deste modo, um componente não é um objecto, mas disponibiliza recursos para os instanciar. Muitas vezes, um único componente disponibiliza interfaces para várias classes inter-relacionadas, daí a POC focar-se na arquitectura e encapsulamento (packging) ao invés da intercooperação entre objectos[Szyperski, Bosch et al. 1999].

Alguns dos seus princípios são [Löwy 2003]:

o Separações da interface da implementação: alterações na implementação não devem ser reflectidas na interface de ligação com os clientes;

o Compatibilidade entre binários: na POC os binários, geralmente não estão compilados com o código da aplicação, mas sim separadamente e são invocados pela aplicação. É permitido que os componentes possam ser substituídos por novas versões, deste modo deverá existir compatibilidade dos binários entre as várias versões;

(32)

o Independência da linguagem: a escolha de uma linguagem de programação não deve impedir o uso de um componente;

o Transparência da localização: os componentes podem existir no mesmo processo do programa ou noutro local. Para os componentes, o lugar onde estes são executados deve ser transparente;

o Gestão de concorrência: como não é possível prever o uso que os componentes irão ter por parte dos clientes, dever-se-á implementá-los de forma a prever o pior caso possível. Para tal, os componentes devem implementar mecanismos de sincronização de acesso;

o Controlo de versões: novas versões de componentes não deverão afectar as aplicações dos clientes existentes. Deve existir uma tecnologia que permita a evolução dos componentes mas que ao mesmo tempo permita o acesso às suas versões mais antigas;

o Segurança com base em componentes: os componentes devem apresentar garantias aos clientes de que estes não são comprometidos por ataques;

Exemplos de algumas tecnologias que aplicam este paradigma: COM5 - Component Object Model

J2EE6 - Java 2 Platform, Enterprise Edition

CORBA7 - Common Object Request Bro-ker: Architecture and Specifications COM+8 - Component Object Model Plus

5

http://www.microsoft.com/com/default.mspx (Acedido em Junho 2008) 6

http://java.sun.com/j2ee/overview.html (Acedido em Junho 2008) 7

(33)

DCOM9 - Distributed Component Object Model ActiveX10

.NET Framework11

2.7 PROGRAMAÇÃO PÓS-OBJECTOS

A POO apesar dos seus benefícios, apresenta algumas lacunas principalmente no que concerne aos requisitos globais e às propriedades sistémicas. Não é possível neste tipo de concerns decompô-los e organizá-los num único local. Assim estes tendem a estar espalhados e entrelaçados com outros concerns[Elrad, Filman et al. 2001], tais como: a sincronização, as restrições em tempo real, a persistência e a recuperação de falhas [Hürsch and Lopes 1995].

Embora seja possível identificá-los na fase conceptual, poucas linguagens de programação, permitem mantê-los separados na fase de implementação. Por exemplo, é pretendido que num programa, quando existir uma actualização de uma linha ou de um ponto, essa alteração seja reflectida imediatamente no ecrã invocando um método (figura 3). Aponta-se a existência de diversas alternativas que permitem este comportamento, nomeadamente, a introdução de código no local onde são feitas as alterações dos valores. Para cada classe é introduzido o código necessário nos métodos para actualizar o ecrã. Este código adicional secundário tem como objectivo implementar um concern que é global ao sistema. É intrusivo nas classes, para além de se repetir de igual forma por várias classes.

8

http://www.microsoft.com/com/default.mspx (Acedido em Junho 2008) 9

http://www.microsoft.com/com/default.mspx (Acedido em Junho 2008) 10

http://www.microsoft.com/com/default.mspx (Acedido em Junho 2008) 11

(34)

Figura 3 – Espalhamento de Concerns. (Adaptada de [Kiczales, Hilsdale et al. 2001])

Programar vários concerns ao mesmo tempo e ao mesmo nível, implica que o programador tenha de saber necessariamente todos os detalhes das áreas a desenvolver. Não existe uma forma de tornar as áreas independentes e separar as tarefas. Neste âmbito, nos anos 90 surgiram várias tentativas de simplificar a crescente complexidade do software, essencialmente a adição de novas necessidades a um projecto existente [Lopes 2002].

Desta forma, a POA surgiu com o ideal de que um sistema de software é superiormente programado especificando separadamente concerns, propriedades ou áreas de interesse do sistema e a descrição dos relacionamentos entre eles [Elrad, Filman et al. 2001].

Todavia é com Gregor Kiczales liderando uma equipa no centro de pesquisa de Palo Alto (PARC, subsidiária da Xerox na Califórnia nos Estados Unidos da América) que se desenvolve o conceito de POA. Este grupo começou por efectuar pesquisas na área da reflexão [Smith 1982] e meta-object protocols [Kiczales, des Rivieres et al. 1991], desenvolvendo algumas ferramentas e

(35)

linguagens orientadas a aspectos tais como: AML, RG [Mendhekar, Kiczales et al. 1997] e DJ [Lopes 1997] que culminaram na linguagem AspectJ [Kiczales, Hilsdale et al. 2001; Kiczales, Hilsdale et al. 2001] que hoje em dia é considerada a linguagem padrão da POA.

Porém, outra tecnologia foi apresentada em 1999 no Centro de Pesquisa de T.J. Watson da empresa IBM, Hypersapces [Ossher and Tarr 1999; Tarr, Ossher et al. 1999; Ossher and Tarr 2001] como uma evolução de subject-oriented programming [Harrison and Ossher 1993].

Na tabela 1, aponta-se as principais datas que marcaram o aparecimento de tecnologias sobre separação de concerns.

Ano Evento

1972 Parnas, decomposição de sistemas em módulos. 1976 Dijkstra, Separação de concerns.

1970s Programação Estruturada

1980s Programação Orientada a Objectos

1992 Adaptive Programming (Lieberherr, Northeastern University) Composition Filters (Aksit, Twente University)

1993 Subject-Oriented Programming (Harrison e Ossher, IBM) 1995 Artigo - Separation of Concerns (HÄurch e Lopes)

1996 Programação Orientada a Aspectos (Kiczales, Xerox PARC)

1997 Primeira Workshop sobre Programação Orientada a Aspectos (ECOOP 97) Artigo - Programação orientada a Aspectos (Kiczales etal.)

Linguagem de Programação AspectJ

Tese - D: A Language Framework for Distributed Programming (Lopes) 1999 Artigo - Multi-dimensional Separation of Concerns (Tarr, Harrison e Ossher,

IBM)

Linguagem de Programação Hyper/J

2000 Primeira Workshop sobre Advanced Separation of Concerns (OOPSLA ) Artigo Aspect-Oriented Programming is Quantification and Obliviousness (Filman e Friedman)

2001 Edição Especial da ACM sobre Programação orientada a Aspectos.

2002 Primeira conferência Internacional sobre Desenvolvimento de Software Orientado a Aspectos (DSOA)

2002- … Evolução nas várias subáreas da DSOA

(36)

2.8 META-PROGRAMMING

Este paradigma tem como base a reflexão computacional [Smith 1985; Maes 1987] que permite que um sistema mantenha informação sobre si e use essa informação para alterar o seu comportamento [Maes 1987]. No paradigma meta-programing [Okamura and Ishikawa 1994 ], um sistema está dividido em dois níveis: base-level e meta-level (figura 4).

Os construtores básicos da linguagem de programação, classes ou invocação de objectos, são descritos no base-level e podem ser estendidos ou redefinidos pela meta-programming. Cada objecto é associado com um meta-object através de um meta-link. O meta-object é responsável pela semântica das operações no objecto base. A interface entre o programa, base-level, e as camadas de nível superior é efectuada por meta-object protocols.

Este último estabelece interfaces para a linguagem de programação que permitem ao programador modificar o comportamento da linguagem de programação e a implementação. Os objectos base-level são responsáveis pelos algoritmos básicos do programa e os seus comportamentos são melhorados e adaptados através de meta-level objects de acordo com requisitos específicos. Através da captura de mensagens enviadas e recebidas para os objectos, meta-level objects, estes conseguem efectuar o trabalho de concerns [Hürsch and Lopes 1995].

(37)

Figura 4 - Meta-programming.

(Adaptada de [Okamura and Ishikawa 1994 ])

2.9 SUBJECT-ORIENTED PROGRAMMING

Subject-Oriented programming é uma extensão para a POO possibilitar a composição de diferentes visões subjectivas do mesmo objecto, facultando o desenvolvimento de aplicações separadamente, bem como, efectuar posteriormente a sua composição.

Estes objectos contêm assim, propriedades e comportamentos específicos que ao longo do tempo e com a evolução necessitam de ser alterados. Estas propriedades e comportamentos são subjectivas ao tipo de objectivo a que se destinam, o mesmo objecto pode ter representações diferentes dependendo do tipo de objectivo com que é idealizado e da entidade que o idealiza (figura 5).

(38)

Deste modo, a Subject-oriented programimng pretende facilitar o desenvolvimento e evolução de aplicações que colaboram entre si. Esta colaboração é alcançada partilhando subjects (objectos) que contribuem para a execução de operações. O desenvolvimento das aplicações é efectuado em separado e sem dependência entre aplicações, permitindo estender sem modificar o original [Harrison and Ossher 1993].

A composição combina hierarquias de classes a fim de produzir novos subjects que incorporam funcionalidades de subjects existentes. A Subject-Oriented programming oferece ferramentas de composição a fim de integrar os sujeitos [Kaplan, Ossher et al. 1996]. Esta tecnologia evoluiu para se tornar a Separação Multidimensional de Concerns (secção 2.13).

Figura 5 - Subject-oriented programming. (adaptada de [Harrison and Ossher 1993])

(39)

2.10 PROGRAMAÇÃO ADAPTATIVA

A Programação Adaptativa [Lieberherr 1996; Lopes 1997] é um modelo de programação com base em padrões de código, onde estes podem ser classificados em diferentes categorias, cada um capturando um tipo diferente de concern. Posteriormente os padrões de código são implementados como componentes de software de alto nível que interagem com os outros componentes de forma muito solta através da resolução de nomes [Lopes 2002].

Perante problemas como a elaboração de uma nova operação ou regra de negócio num sistema, é necessário colocar todo o código num só método, numa só classe, ou adopta-se a divisão do código da operação por várias classes. Porém o problema deste último método relaciona-se com a dependência na estrutura das classes, o que vai adicionar complexidade nos métodos e dificultar a evolução. A Programação Adaptativa resolve esta questão utilizando padrões de propagação, abstraindo o comportamento do concern num local e a estrutura das classes noutro. O comportamento é expresso a um alto nível utilizando uma estratégia transversal [Lieberherr, Orleans et al. 2001].

Nesta continuidade, a Programação Adaptativa pode ser definida em dois blocos: um bloco de estrutura implementado por um grafo do dicionário de classes, que contém a relação entre classes e um segundo bloco comportamental, implementado por um padrão de propagação que é depois composto com o grafo e que assim possibilita a interacção de forma flexível entre ambos.

(40)

2.11 FILTROS DE COMPOSIÇÃO

Filtros de composição são uma extensão à POO através da adição de filtros ortogonais e modulares que permitem aumentar a adaptabilidade e a reutilização dos objectos [Aksit, Wakita et al. 1993; Bergmans and Aksit 2001]. Assim, são elaborados filtros que filtram as mensagens enviadas e recebidas pelos objectos e efectuam acções através da definição de condições para a aceitação ou rejeição de uma mensagem.

Esta tecnologia consiste principalmente no interface e na implementação. Na parte de interface faz-se o tratamento das mensagens de chegada e de saída, composto de um ou mais filtros de entrada e saída, e opcionalmente, de objectos internos e externos e de declarações de métodos (figura 6). Os filtros são controlados por condições, nomes de filtros, nome das declarações de métodos e nomes das condições que são visíveis para os objectos clientes apesar da sua implementação ser invisível. Na parte de implementação estão as definições de métodos, instâncias de variáveis, definições de condições e opcionalmente operações de inicialização. Esta parte é totalmente encapsulada no objecto, possibilitando através deste, a alteração de mensagens e o seu redireccionamento para objectos internos ou externos. Assim pode ser alcançada a separação de concerns definindo um filtro por cada concern.

(41)

Figura 6 - Filtros de composição. (adaptada de [Aksit, Wakita et al. 1993])

2.12 PROGRAMAÇÃO ORIENTADA A ASPECTOS.

A origem do termo POA é resumida por Cristina Lopes, “Não me consigo lembrar da data exacta quando decidimos chamar ao nosso trabalho ‘Programação Orientada a Aspectos’, mas lembro-me que o termo foi sugerido por Chris Maeda […]. No meu portátil a primeira referência a ‘POA’ ocorre nos fins de Novembro de 1995. Em Janeiro de 1996, o meu portátil indica que estávamos a usar ‘Open Implementation’ e ‘POA’ ao mesmo tempo, embora para partes diferentes do trabalho do grupo. Em Junho de 1996 enviámos a proposta para o DARPA intitulada ‘Programação Orientada a Aspectos’, no fim de 1996 desaparecem todas as referências a ‘Open Implementation’ do meu portátil.” [Lopes 2002].

(42)

Gregor Kiczales como já referido, liderava uma equipa de investigação em “Open implementaions” [Kiczales 1996] e “Metaobject Protocol” [Kiczales, des Rivieres et al. 1991], à qual no verão de 1995 se junta Cristina Lopes, acrescentando conhecimentos de programação adaptativa [Lopes 1996]. Em 1997, Gregor Kiczales apresenta o seu trabalho em “Programação Orientada a Aspectos” na conferência ECOOP’97, expondo os primeiros termos, conceitos e análise dos problemas que se tentavam solucionar [Kiczales, Lamping et al. 1997].

Gregor Kiczales afirma que “[…] O objectivo deste trabalho é tornar possível que os programas consigam claramente capturar todos os aspectos importantes do comportamento do sistema […]” [Kiczales, Lamping et al. 1997].

As linguagens de programação com base num só tipo de abstracção são inadequadas para sistemas complexos. Diferentes tipos de comportamentos do sistema tendem a ter a sua própria “forma”, enquanto um tipo de abstracção pode ser bom para capturar um tipo de comportamento do sistema, é insuficiente num outro tipo de comportamento [Kiczales, Lamping et al. 1997].

As Linguagens de POO conseguem capturar os comportamentos dos objectos mas falham em comportamentos secundários, comportamentos estruturais e comportamentos invariantes. Estes comportamentos não são possíveis de isolar num só local e dispersam-se pelos módulos do sistema, ou seja, são transversais aos módulos. Nesta mistura de comportamentos o resultado é código espalhado que leva à perda de modularidade e a uma possível perda de abstracção.

Para combater estas fragilidades a POA apresenta uma nova forma de modularização que permite a implementação de cada aspecto do sistema separadamente na sua forma natural, e a sua composição usando uma ferramenta “Aspect Weaver”. As componentes funcionais continuam a ser implementadas nos paradigmas existentes enquanto as componentes não funcionais são

(43)

implementadas numa linguagem de aspectos. Criando-se uma solução de abrangência geral e independente do tipo de comportamento do sistema, funcionando como uma extensão.

Assim, a POA define Crosscutting concern como um comportamento do sistema que atravessa vários módulos deste. Este é dividido em concerns base, comportamentos primários e crosscutting concern, comportamentos secundários e é adicionada uma nova unidade modular, o aspecto. A implementação de concerns é feita independentemente e a coordenação e comunicação entre eles é relegada para os aspectos.

O programador, detentor da compreensão do sistema, fica responsável por explicitamente definir os aspectos, utilizando uma linguagem que deva permitir um nível abstracto adequado e com a localidade apropriada [Kiczales, Lamping et al. 1997].

2.12.1 AspectJ

Uma implementação do paradigma é o AspectJ12 [Kiczales, Hilsdale et al. 2001; Kiczales, Hilsdale et al. 2001] que funciona com uma extensão à linguagem POO Java13, adicionando-lhe conceitos práticos de POA e permitindo a implementação modular de crosscutting concerns. Acrescentando um novo conceito, o join point e alguns construtores: pointcuts, advice, inter-type declarations e aspects.

AspectJ foi desenvolvido com a compatibilidade com a linguagem Java em mente, isto é, os programas em Java têm de ser válidos em AspectJ e os programas AspectJ deverão ser válidos na Java virtual machine (JVM) padrão [Lindholm and Yellin 1999]. As ferramentas de suporte

12

http://www.eclipse.org/aspectj/ (Acedido, Julho 2008) 13

(44)

do Java foram alteradas para suportar a linguagem, tais como os Ambientes Integrados de Desenvolvimento (IDEs), bem como, as ferramentas de documentação. Assim, os programadores podem utilizar a extensão AspectJ de forma tão natural como o Java.

Como já referido, o AspectJ adiciona: pointcuts e advices que permitem afectar dinamicamente o fluxo normal do programa, inter-type declarations que alteram estaticamente a hierarquia de classes do programa e aspectos que encapsulam todos os novos construtores.

Outra adição a enumerar é o conceito de Join Point que define um ponto no fluxo do programa. Estes são utilizados por pointcuts para expor os locais de intercepção onde é necessária a adição de comportamentos transversais. Por sua vez, advice é o bloco de código que vai ser executado quando o join point for alcançado.

Na sua conjuntura existem dois tipos de comportamentos possíveis: os comportamentos dinâmicos que avaliam condições definidas nos pointcuts em tempo de execução e os comportamentos estáticos onde as avaliações são feitas em tempo de compilação.

Todavia acrescenta-se que os aspectos são as unidades modulares para a declaração dos crosscutting concerns, são similares às classes do Java mas incluem os construtores pointcut, advice e inter-type declaration.

Nos próximos subcapítulos expõe-se uma breve introdução da linguagem, tendo como base a guia de programação14.

14

(45)

2.12.1.1 Join Point

Join Point é um ponto bem definido no fluxo do programa. Este modelo permite capturar: • Chamadas a métodos;

• Execução de métodos; • Criação de objectos;

• Execução do construtor do objecto;

• Inicialização de objectos; • Pré inicialização de objectos;

• Referências e atribuição a variáveis;

• Tratamento de excepções.

2.12.1.2 PointCuts

Tendo por base que os pointcuts permitem seleccionar e agrupar join points, e utilizando a figura 7 como exemplo de referência, pretende-se seleccionar todas as chamadas ao método setX com argumento int e retorno void da classe Point.

(46)

Para se criar um Pointcut, utiliza-se o operador pointcut e declara-se o seu nome, a sua interface e o join point a capturar. No exemplo 1, expõe-se a utilização da primitiva call (identifica um join point do tipo chamada a método) para a captura de chamadas ao método setX da classe Point.

pointcut move(): call(void Point.setX(int))

Exemplo 1 – declaração de um pointcut.

De modo a agregar vários join points num só pointcut, aplicam-se os operadores lógicos ‘ou’ definido na linguagem com os símbolos ‘||’, o operador ‘e’ definido na linguagem com os símbolos ‘&&’ e o operador de negação definido na linguagem com o símbolo ‘!’.

Para facilitar a atribuição de join points é possível definir o nome do fluxo (método, variável, excepção, etc.) a capturar, utilizando wildcards para os expressar. Denominando este tipo de pointcut, de Property-Based Primitive PointCut, este permite que numa só declaração se agrupem um conjunto de join points, pois estes seguem uma determinada sintaxe no seu nome.

No exemplo 2 captura-se todos os métodos da classe Figure cujo nome comece por make com qualquer tipo de parâmetros mas só os métodos declarados com retorno void.

call(void Figure.make*(..))

Exemplo 2 - Pointcut utilizando WildCards.

2.12.1.3 Advice

Pointcuts seleccionam join points mas não exercem qualquer acção. Porém com o auxílio dos advices possibilita-se implementar o comportamento transversal associando assim, um pointcut a um bloco de código.

(47)

O bloco de código de um advice que está associado a um ou mais pointcuts pode ser executado em três momentos diferentes: ‘antes’ (exemplo 3), ‘depois’ (exemplo 4) ou ‘ao invés de’ (exemplo 5).

before():Pointcut{ Bloco de Código }

Exemplo 3 – Advice do tipo ‘antes’.

after():Pointcut{ Bloco de Código }

Exemplo 4 - Advice do tipo ‘depois’.

around():Pointcut{ Bloco de Código }

Exemplo 5 - Advice do tipo ‘ao invés de’.

2.12.1.4 Inter-type declarations

Inter-Type declarations permitem adicionar comportamentos a classes e alterar as suas hierarquias, declarar membros de classes que se propagam por múltiplas classes ou alterar a relação de herança entre classes. Por exemplo, permite adicionar a uma classe atributos, métodos, ou implementar um padrão de desenho. No exemplo 6 é mostrado como adicionar métodos e variáveis necessárias à implementação do padrão de desenho Observer que posteriormente são compostos pelo Weaver com a classe Point.

aspect PointObserving {

private Vector Point.observers = new Vector(); public static void addObserver(Point p, Screen s) { p.observers.add(s);

}

public static void removeObserver(Point p, Screen s) { p.observers.remove(s);

} ... }

(48)

2.12.1.5 Aspectos

Como já mencionado, os aspectos encapsulam os pointcuts, advices e inter-type declarations, para além de poderem conter métodos e atributos. São as unidades modulares onde todo o comportamento relativo a um ou mais comportamentos transversais é implementado e fica localizado (exemplo 7).

aspect OmeuAspecto{

//Dentro deste bloco é possível declarar

//Métodos e declaração de atributos iguais ao java

//pointcuts e advices e inter-type declarations referentes ao AspectJ }

Exemplo 7 – declaração de aspectos.

2.13 SEPARAÇÃO MULTIDIMENSIONAL DE CONCERNS

Separação multidimensional de concerns é um paradigma para modelar e implementar software artifacts, suportando a separação simultânea de concerns através da decomposição e composição de software artifacts ao longo de múltiplas dimensões, quebrando a “tirania da decomposição dominante”, sendo uma evolução da subject oriented programming [Tarr, Ossher et al. 1999].

Durante o desenho de um sistema são identificados requisitos e funcionalidades que na fase de implementação só são possíveis de decompor de uma forma: por objectos. Funcionalidades que afectem vários objectos vão espalhar-se por diversos outros implicando a evolução e compreensão do sistema. Futuras alterações são intrusivas no sistema ao invés de aditivas. Para alcançar a decomposição por concerns este paradigma utiliza Hyperslices.

(49)

Relativamente ao hyperslice, tido como um conjunto de módulos convencionais escritos num qualquer formalismo, têm a finalidade de encapsular concerns numa dimensão fora da dimensão dominante. Os módulos desta dimensão contêm todas as unidades que pertencem ou tratam do concern em causa.

Sendo bem elaborada a separação de concerns, pode fornecer a muitos engenheiros de software diversos benefícios, entre eles: a complexidade reduzida, a reutilização e a evolução. A escolha dos limites da separação dos concerns depende dos requisitos do sistema e dos tipos de decomposição e composição que um dado formalismo suporta. As metodologias predominantes e formalismos disponíveis só suportam separação de concerns ortogonal, ao longo de uma única dimensão de decomposição e composição [Ossher and Tarr 2000].

Esta tecnologia evolucionou para Concern Manipulation Evironment (CME) [Harrison, Ossher et al. 2005; Harrison, Ossher et al. 2005] suportando a extracção e composição de concerns durante o ciclo de vida de um sistema de software, disponibilizando um conjunto de ferramentas para programadores. CME é assim, um projecto Eclipse15 Open Source, que já não está em desenvolvimento e encontra-se arquivado16.

2.14 DESENVOLVIMENTO DE SOFTWARE ORIENTADO A ASPECTOS

Para além de modularizar crosscutting concerns é necessário primeiramente, identificá-los numa fase anterior à implementação. A POA tornou-se assim parte de uma área maior, o

15

http://www.eclipse.org (Acedido, Julho 2008) 16

(50)

Desenvolvimento de Software Orientado a Aspectos (DSOA), existindo duas grandes áreas nela inserida, a Early-Aspects17 [Rashid, Sawyer et al. 2002] e a POA.

A investigação na área Early-Aspects tem como objectivo identificar aspectos crosscutting numa fase inicial da elaboração do sistema, e determinar o impacto dos aspectos identificados em fases posteriores. A Early-Aspects foca-se na engenharia de requisitos. Para atingir um consenso nesta área é introduzido um modelo para a engenharia de requisitos, primeiro são identificados e especificados os concerns seguindo-se, a partir destes, a identificação dos potenciais aspectos que são especificados e atribuídos de uma prioridade. Finalmente é definida a dimensão em que se enquadram os aspectos.

Os concerns que influenciem ou interajam com mais de um requisito são chamados aspectos candidatos, prosseguindo-se uma detalhada especificação dos aspectos candidatos, o que permite uma refinação de aspectos mais sucinta e que tipo de interacções e conflitos, entre aspectos existe. Para resolver conflitos entre aspectos é preciso atribuir-lhes prioridades.

2.15 COMUNIDADES E SITUAÇÃO EM PORTUGAL

Existe uma associação de DSOA, a nível Mundial18 e Europeu19, que organiza todos os anos uma conferência Internacional20 com Workshops21 sobre esta temática. Em Portugal existe

17

http://www.early-aspects.net/ (Acedido, Julho 2008) 18

http://www.aosd.net/aosa.php (Acedido, Julho 2008) 19

http://www.aosd-europe.net/ (Acedido, Julho 2008) 20

http://aosd.net/ (Acedido, Julho 2008) 21

http://portal.acm.org/browse_dl.cfm?linked=1&part=series&idx=SERIES10702&coll=portal&dl=ACM&CFID=948 5317&CFTOKEN=42857112 (Acedido, Julho 2008)

(51)

um grupo de pesquisa na área de early-aspects22, sediada na Universidade Nova de Lisboa sob a liderança da Professora Doutora Ana Moreira.

2.16 DESAFIOS, PROBLEMAS E OPORTUNIDADES

A POA teve uma fase de evolução e amadurecimento desde que foi apresentada em 1997 até 2002, ano em que foi incorporada como uma subárea da DSOA. O desenvolvimento da investigação académica está na sua maioria focado na subárea early-aspects, desenvolvendo-se ferramentas para a identificação de aspectos na fase de desenho e como estes se deverão relacionar com o resto do sistema. Deste modo, estão a ser elaboradas ferramentas, que permitem a criação visual de aspectos de uma forma similar com o que é feito com UML para a POO.

Na fase de implementação estão a ser elaboradas ferramentas que permitem visualizar a interacção dos aspectos com o resto do sistema e efectuar a depuração do código, aproveitando também o novo conceito de modularização através de bytcode weaving para criar sistemas mais modulares, onde existe adição ou remoção, em tempo de execução, de funcionalidades e requisitos consoante as necessidades.

Alguns paradigmas apresentados posteriormente evoluíram e agora fazem parte integrante da POA, tais como o Adpatative programing [Lieberherr, Orleans et al. 2001].

Como tecnologia emergente, a POA tem a potencialidade de facilitar e diminuir o tempo de desenvolvimento de um sistema de software. Para o sucesso da tecnologia é necessário uma

22

(52)

maior adaptação ao nível comercial. Para tal, é essencial uma melhor integração com as tecnologias existentes, para que assim exista uma transição natural sentida como uma evolução. Esta evolução não pode ser só das linguagens de programação existentes, tem de envolver todas as ferramentas que são utilizadas com essa linguagem, entre outros, editores, documentação e depuradores.

A constante transformação do mundo actual determina que o que é uma necessidade hoje, pode ser substituída por uma outra necessidade completamente diferente amanhã. O que influencia as empresas a estar em constante evolução e alterarem as suas regras de negócio. Toda esta conjuntura de factos em constante mudança, evidência a necessidade de uma nova forma de se conseguir desenvolver software que permita em tempo útil, acompanhar estas mudanças. A POA possibilita este facto através da adição de funcionalidades e regras de negócio, que não são intrusivas à evolução e/ou modificação dos sistemas.

Devido à nova forma de modularidade é fundamental a existência de alguma coordenação das alterações que se possam efectuar no sistema, para que o seu comportamento seja previsível, ou seja, as alterações não devem conduzir a aspectos que deixam de interceptar pontos no fluxo ou estes fluxos deixem de ser o ponto de intercepção pretendido, tornando o comportamento do sistema imprevisível.

(53)
(54)

3. PROGRAMAÇÃO ORIENTADA A ASPECTOS

Nos pontos que se seguem tentar-se-á abordar os problemas inerentes à POA, bem como, as suas primordiais vantagens e desvantagem que influenciaram a busca de soluções por parte da POA. Assim, incidir-se-á numa primeira análise do que se entende por um sistema POA, seguindo-se a exposição das tecnologias existentes, aplicações e estudos quantitativos inerentes a esta área de investigação.

3.1 COMPORTAMENTOS GLOBAIS

A motivação do paradigma da Programação Orientado a Aspectos, é ajudar a modularizar múltiplos aspectos de um sistema de software, aplicando-lhe o princípio da separação de concerns. O sistema é composto por módulos independentes, raciocinando modularmente e sem as dificuldades e complexidades apresentadas por outras tecnologias de separação de concerns semelhantes. A partir da figura 8 mostra-se dois módulos da mesma aplicação, cada um dos módulos implementa uma determinada funcionalidade necessária pela aplicação, contudo existe ainda uma dependência explícita de entre os dois módulos. O módulo A necessita de conter referências ao módulo B, nas várias unidades que o compõem, deste modo os dois módulos não são totalmente independentes.

(55)

Figura 8 - Interacção entre Módulos.

Na figura 9 pode verificar-se a existência de uma sobreposição de uma unidade elementar B1 pertencente ao módulo B a três unidades do módulo A. Esta dependência é em certo modo, criada pela forma como se estruturou o programa e por condicionantes introduzidas pelo paradigma que se está a utilizar na implementação, por exemplo, a hierarquia de classes no paradigma orientado a objectos. Esta dependência entre módulos vai condicionar a sua independência e reutilização para futuros projectos.

Figura 9 - Sobreposição de unidades elementares.

Existem comportamentos num sistema de software que se repetem sistematicamente em vários módulos do sistema, não sendo possíveis de se situarem num só local pois são uma

(56)

necessidade global do sistema, criada pela necessidade do sistema em ter um certo comportamento específico (figura 10).

Figura 10 - Comportamentos Globais do Sistema

3.2 ANÁLISE DO PROBLEMA

O primeiro problema que se pode identificar diz respeito ao desenho da arquitectura de um sistema de software. O engenheiro de software, quando lhe é atribuída a tarefa de criar um novo sistema de software, depara-se com uma série de dilemas que afectam a criação do sistema, nomeadamente o tempo de que se dispõe para criar o sistema e a evolução dos requisitos do sistema. Não existem certezas de que os requisitos não vão sendo alterados durante o desenvolvimento do sistema ou sua posteriori.

(57)

Dependendo dos factores anteriores criam-se sistemas que são mais rápidos de produzir, ou seja, têm um tempo reduzido para sair para o mercado, mas são difíceis de evoluir posteriormente e nem sempre apresentam garantias de qualidade. Por outro lado uma arquitectura do sistema mais cuidada permite uma melhor evolução do sistema, com maior qualidade, mas implicando maior tempo de desenvolvimento e gastos adicionais.

Definir um meio-termo não é fácil, mas focando-se apenas nos requisitos presentes e desenvolvendo um sistema com base em tecnologias que permitam a acomodação modular de novos requisitos, ou as suas alterações, obtém-se assim uma solução que permitirá a elaboração de um sistema de melhor qualidade, em menos tempo e com menor custos.

A tarefa de gerir projectos é contudo um factor crítico, devido à falta de modularidade implicando deste modo mais comunicação entre equipas, reuniões e debates o que encurta o tempo de desenvolvimento.

Não obstante, outro problema inerente é o facto de que a tecnologia utilizada para a implementação produz um impacto negativo na modularização, ou seja, muitas vezes aquando do desenho do sistema para a fase de implementação perde-se modularidade. A tecnologia usada na implementação não permite implementar modularmente todas as preocupações desenhadas e identificadas e algumas acabam por se sobrepor a outras (exemplo 8).

(58)

public class SomeBusinessClass extends OtherBusinessClass {

"Dados do módulo"

"Stream de Registo"

"Flag de consistência de dados" "Métodos redefinidos da super classe"

public void performSomeOperation(<informação da Operação>) {

"Garantir autenticidade"

"Garantir que a informação satisfaça contrato" "Bloquear o objecto para garantir consistência" "Garantir que a cache está actualizada" "Fazer o registo do início da operação"

"Realizar Operação"

"Fazer o registo do final da operação" "Desbloquear o objecto"

}

public void save(<persistência de dados>) {

"..." }

public void load(<persistência de dados>) {

"..." } }

Exemplo 8 – Intrusão em Classes.

(1)

(2)

(3)

Imagem

Figura 1 - Módulos com acesso concorrente aos dados.
Figura 3 – Espalhamento de Concerns.
Figura 4 - Meta-programming.
Figura 5 - Subject-oriented programming.
+7

Referências

Documentos relacionados

Estudar o efeito da plastificação do ATp com glicerol nas características físico-químicas da blenda PLA/ATp; Analisar a mudança na cristalinidade dos laminados submetidos a

Era de conhecimento de todos e as observações etnográficas dos viajantes, nas mais diversas regiões brasileiras, demonstraram largamente os cuidados e o apreço

O termo extrusão do núcleo pulposo aguda e não compressiva (Enpanc) é usado aqui, pois descreve as principais características da doença e ajuda a

Para esse fim, analisou, além do EVTEA, os Termos de Referência (TR) do EVTEA e do EIA da Ferrogrão, o manual para elaboração de EVTEA da empresa pública Valec –

Local de realização da avaliação: Centro de Aperfeiçoamento dos Profissionais da Educação - EAPE , endereço : SGAS 907 - Brasília/DF. Estamos à disposição

De seguida, vamos adaptar a nossa demonstrac¸ ˜ao da f ´ormula de M ¨untz, partindo de outras transformadas aritm ´eticas diferentes da transformada de M ¨obius, para dedu-

•   O  material  a  seguir  consiste  de  adaptações  e  extensões  dos  originais  gentilmente  cedidos  pelo 

Podem treinar tropas (fornecidas pelo cliente) ou levá-las para combate. Geralmente, organizam-se de forma ad-hoc, que respondem a solicitações de Estados; 2)