design rules for increasing modularity with caesarj · 2019. 10. 25. · universidade federal de...
TRANSCRIPT
Universidade Federal de Pernambuco - UFPE
Centro de Informatica - CIn
Pos-graduacao em Ciencia da Computacao
DESIGN RULES FOR INCREASING
MODULARITY WITH CAESARJ
Carlos Eduardo Pontual de Lemos Castro
DISSERTACAO DE MESTRADO
Recife - PE
17 de Junho de 2010
Universidade Federal de Pernambuco - UFPE
Centro de Informatica - CIn
Carlos Eduardo Pontual de Lemos Castro
DESIGN RULES FOR INCREASING MODULARITY WITH
CAESARJ
Trabalho apresentado ao Programa de Pos-graduacao em
Ciencia da Computacao do Centro de Informatica - CIn da
Universidade Federal de Pernambuco - UFPE como requi-
sito parcial para obtencao do grau de Mestre em Ciencia
da Computacao.
Orientador: Paulo Henrique Monteiro Borba
Recife - PE
17 de Junho de 2010
Castro, Carlos Eduardo Pontual de Lemos. Design rules for increasing modularity with CaesarJ. / Carlos Eduardo Pontual de Lemos Castro. - Recife: O autor, 2010. xv, 102 folhas: il., fig., tab. Dissertação (Mestrado) - Universidade Federal de Pernambuco. CIN. Ciência da Computação, 2010. Inclui bibliografia e apêndice. 1. Engenharia de software. 2. Modularidade. 3. Programação orientada a aspectos. 4. Programação orientada a objetos. I. Título. 005.1 CDD (22.ed.) MEI-2010-163
To my family, my girlfriend and everyone that believed in
me.
ACKNOWLEDGEMENTS
Inicialmente, agradeco a Deus, companheiro inseparavel em todos esses 785 dias aqui “no”
Recife, a quem eu recorria quase sempre nos momentos mais difıceis, de maior angustia.
Sem Ele, nada disso seria possıvel. Agradeco tambem a muitas outras pessoas que me
ajudaram e contribuıram, de forma direta ou indireta, para a conclusao desse trabalho:
A minha famılia, por todo carinho, apoio, por acreditar muito em mim e por toda
a ajuda. Um agradecimento especial aos meus pais, que fizeram o possıvel (e o im-
possıvel) para me manter sempre motivado, sempre me dando muita atencao, e nunca
tendo deixando que eu passasse qualquer necessidade. Um abraco bem apertado no meu
irmao Bruno, de quem eu sinto muita falta. Suas visitas foram excelentes (METAL \,,/)!
A Cınthia, que me apoiou incondicionalmente durante esse perıodo, me ajudando de
todas as maneiras possıveis e impossıveis, inclusive nos momentos que nem eu conseguia
me suportar. Muito obrigado pela atencao, amor e carinho. Eu nao teria conseguido sem
o seu apoio, suas visitas, e o tempo que voce passou aqui comigo. Te amo Dra. =*
Ao orientador/amigo/lord Paulo Borba, primeiramente, no ambito profissional, pela
excelente orientacao durante esse perıodo, sempre me apontando a direcao correta, com
muita, muita paciencia, dedicacao e... ja disse paciencia? Alem disso, pelo lado amigo,
nas brincadeiras, viagens, confraternizacoes, e ate mesmo enquanto eu comemorava a
vitoria do Sao Paulo em pleno estadio dos aflitos :) Muito obrigado por tudo!
Aos meus amigos do mestrado, em especial Rodrigao, Napoleao, Moral, ModPag e
Fernanda, por toda a ajuda nos inumeros obstaculos desse perıodo: artigos, projetos,
trabalhos, discussoes... Leopoldo, Marcio e Henrique: Perdoo voces por torcerem contra
o SP :) Obrigado tambem aos membros do SPG, pelas excelentes e proveitosas discussoes.
A todos os meus amigos de Fortaleza, que me animavam toda vez que eu ia a minha
terrinha. Obrigado Brunao, Marılia, Pazzo, Sabrina, Tarcia, e a todos aqueles que me
visitaram aqui, quebrando a minha rotina e alegrando meus dias. Agradeco tambem aos
amigos da Residencia das Palmeiras, por toda forca que me deram nessa reta final.
Finalmente, agradeco ao CNPq por financiar a minha pesquisa.
Oh, and a special thanks to the #stratego community members, specially to Rob
Vermaas, for all the help with Stratego/XT. I won’t forget your beer Rob :)
iv
So sei que nada sei.
—SOCRATES
RESUMO
Programacao Orientada a Aspectos (POA) e um mecanismo de programacao proposto
para modularizar os requisitos transversais, visando um aumento na modularidade de
software. Entretanto, recentemente alguns autores tem alegado que o uso de POA quebra
a modularidade das classes. Isso acontece pois, sem o uso de interfaces apropriadas entre
classes e aspectos, diversas propriedades de um design modular, como compreensibilidade,
manutenabilidade e desenvolvimento em paralelo, sao comprometidas na presenca de
aspectos.
Diversas interfaces especializadas (design rules) para desacoplar classes e aspectos
foram propostas visando atenuar esse problema, como XPIs e LSD. Entretanto, tais
interfaces sao especıficas para a linguagem AspectJ, que possui problemas de reuso e
modularidade de aspectos. CaesarJ, por outro lado, e uma linguagem de programacao
orientada a aspectos com forte suporte para reuso e modularidade de aspectos. Essa
linguagem combina as construcoes OA pointcut e advice com avancados mecanismos de
modularizacao OO.
Nesse trabalho nos exploramos algumas construcoes de CaesarJ com o intuito de veri-
ficar se elas podem ser utilizadas para definir Design Rules que permitam um desenvolvi-
mento modular de codigo OO e OA. Alem disso, nos propomos CaesarJ+, uma extensao
de CaesarJ que foca no aumento de modularidade. Essa extensao introduz construcoes
que permitem impor restricoes estruturais sobre os codigos OO e OA. Um compilador
para CaesarJ+, que verifica se as restricoes especificadas nas Design Rules estao sendo
seguidas, e transforma o codigo CaesarJ+ em codigo CaesarJ tambem foi desenvolvido
nesse trabalho.
Para avaliar CaesarJ+, nos comparamos as implementacoes de tres estudos de caso
em CaesarJ+ e CaesarJ. Nossos resultados revelam que o uso de CaesarJ+ proporciona
ganho de expressividade.
Palavras-chave: Modularidade de Software, Design Rules, Programacao Orientada a
Aspectos, Programacao Orientada a Objetos, CaesarJ
vi
ABSTRACT
Aspect-Oriented Programming (AOP) is a programming mechanism proposed to modu-
larize the crosscutting concerns, aiming to increase software modularity. However, more
recently, some authors have claimed that AOP, in fact, might break class modularity.
This problem arises because, without using proper interfaces, several properties of a
modular design, such as comprehensibility, changeability and parallel development, are
compromised in the presence of aspects.
In order to mitigate these problems, specialized interfaces (design rules) to decouple
classes and aspects have been proposed, such as XPIs and LSD. However, these interfaces
are specific for AspectJ, which has some issues of reusability and modularity of Aspects.
CaesarJ, for instance, is an aspect-oriented programming language with a strong support
for reusability and modularity of aspects. It combines the AO constructs, pointcuts and
advice, with advanced object-oriented modularization mechanisms.
In this work we explore some CaesarJ constructs in order to check if they can be used to
define Design Rules which enable a modular development of OO and AO code. Moreover,
we propose CaesarJ+, an extension to CaesarJ that aims to increase modularity. This
extension introduces constructs that enforce structural restrictions over both OO and AO
code. We also have developed a compiler for CaesarJ+, which checks if the restrictions
specified by the Design-Rules are being followed, and transforms CaesarJ+ into CaesarJ
valid code.
We evaluate this extension using three case studies, comparing the interfaces specified
for these examples in both CaesarJ+ and CaesarJ. Our results reveal that we have a gain
of expressiveness when using CaesarJ+.
Keywords: Software Modularity, Design Rules, Aspect-Oriented Programming, Object-
Oriented Programming, CaesarJ
vii
CONTENTS
Chapter 1—Introduction 1
1.1 Summary of Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Chapter 2—Background 5
2.1 Software Modularity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Aspect Oriented Programming . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 CaesarJ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3.1 Caesar Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.2 Aspects Collaboration Interfaces - ACIs . . . . . . . . . . . . . . . 11
2.3.3 Mixin composition . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3.4 Wrapper Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4 Development of Classes and Aspects: Modularity Issues . . . . . . . . . . 15
Chapter 3—Exploring CaesarJ 18
3.1 Tetris SPL Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2 Template Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.2.1 Template Method without ACIs . . . . . . . . . . . . . . . . . . . 20
3.2.2 Template Method with ACIs . . . . . . . . . . . . . . . . . . . . . 23
3.3 Mixin Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.3.1 Mixins without ACIs . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.3.2 Mixins with ACIs . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.4 Wrappers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.4.1 Wrappers without ACIs . . . . . . . . . . . . . . . . . . . . . . . 32
3.4.2 Wrappers with ACIs . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.5 Chapter Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
viii
CONTENTS ix
Chapter 4—CaesarJ+: An extension to Increase CaesarJ Modularity 37
4.1 Design Rules construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.2 Complements relationship . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.3 Design Rules implementation . . . . . . . . . . . . . . . . . . . . . . . . 41
4.4 Design Rules instantiation . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.5 Enhancing Expressiveness . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.5.1 Wildcards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.5.2 Advice restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.6 Chapter Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Chapter 5—Implementation details 51
5.1 Transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.1.1 Design Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.1.2 Complements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
5.1.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.1.4 Instantiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.2 Compiler Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.2.1 Stratego/XT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
5.2.2 CaesarJ+ Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.2.2.1 Manipulation of Design Rules . . . . . . . . . . . . . . . 63
5.2.2.2 Compilation of DR implementations . . . . . . . . . . . 63
5.2.2.3 Manipulation of DR instances . . . . . . . . . . . . . . . 64
5.2.3 Compiler Limitations . . . . . . . . . . . . . . . . . . . . . . . . . 66
Chapter 6—Evaluation 68
6.1 Tetris SPL - Di!culty Feature . . . . . . . . . . . . . . . . . . . . . . . . 68
6.2 Observer Design Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6.3 Health Watcher Transaction Concern . . . . . . . . . . . . . . . . . . . . 77
Chapter 7—Concluding Remarks 81
7.1 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
7.1.1 Open Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
7.1.2 Aspect Aware Interfaces . . . . . . . . . . . . . . . . . . . . . . . 84
7.1.3 Crosscutting Programming Interfaces (XPIs) . . . . . . . . . . . . 84
CONTENTS x
7.1.4 Language for Specifying Design Rules (LSD) . . . . . . . . . . . . 85
7.1.5 CrossMDA2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7.2 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Appendix A—CaesarJ+ SDF grammar 89
A.1 General CaesarJ+ Specification . . . . . . . . . . . . . . . . . . . . . . . 89
A.2 Design Rules construct SDF . . . . . . . . . . . . . . . . . . . . . . . . . 94
LIST OF FIGURES
2.1 Aspect weaving process . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Mixin linearization: Generated inheritance hierarchy . . . . . . . . . . . 13
2.3 ColoredWeightedGraph (a) refined by SpecialColoredWeightedGraph (b) 14
2.4 Modularity Issues between Classes and Aspects . . . . . . . . . . . . . . 16
3.1 Tetris game: normal di!cult (left) and easy di!cult (right). . . . . . . . 19
3.2 Tetris Game - Single product diagram . . . . . . . . . . . . . . . . . . . . 19
3.3 Classes TetrisCanvas and NextPiece . . . . . . . . . . . . . . . . . . . . . 20
3.4 Template Method without ACIs: variations depend on invariant code (in-
heritance). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.5 Diagram of Mixin implementation without use ACIs . . . . . . . . . . . . 27
3.6 Diagram of Wrapper implementation using ACIs . . . . . . . . . . . . . . 35
4.1 The order of classes in a DR instances is the same of the DR parameters 44
5.1 Overview of Design Rules compilation process . . . . . . . . . . . . . . . 52
5.2 Overview of Stratego/XT transformation process [9]. . . . . . . . . . . . 60
xi
LISTINGS
2.1 Pointcut example on AspectJ . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Advice example on AspectJ . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3 Inter-type declaration on AspectJ . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Caesar class example: classic Figure-Display problem . . . . . . . . . . . 10
2.5 Set of collaboration classes (ACI) for the graph example . . . . . . . . . 12
3.1 Template Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2 Interface for Template Method . . . . . . . . . . . . . . . . . . . . . . . . 22
3.3 NextPieceACI, Template Method . . . . . . . . . . . . . . . . . . . . . . 23
3.4 NextPieceACI enabling the bi-directional dependency, Template Method 24
3.5 Implementations of NextPieceACI, Template Method . . . . . . . . . . . 24
3.6 Instantiation of the variation . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.7 NextPieceConcrete class: Mixin of NextPieceBase and EasyVariation . . 27
3.8 Implementation of NextPieceACI using Mixin Composition . . . . . . . . 28
3.9 NextPieceACI with the Canvas role . . . . . . . . . . . . . . . . . . . . . 29
3.10 Mixin implementation of NextPieceACI with Canvas role . . . . . . . . . 30
3.11 Invalid mixin NextPieceMixin: No error given by CaesarJ compiler. . . . 31
3.12 First implementation using wrappers . . . . . . . . . . . . . . . . . . . . 32
3.13 Wrapper class EasyVariation with inversion of control . . . . . . . . . . . 33
3.14 NextPieceACI interface for Wrapper classes implementation . . . . . . . 34
4.1 Simple CaesarJ+ Design Rule example . . . . . . . . . . . . . . . . . . . 38
4.2 Design Rule construct SDF grammar . . . . . . . . . . . . . . . . . . . . 39
4.3 Design Rule for the Di!culty feature of Tetris SPL . . . . . . . . . . . . 40
4.4 Complements construct SDF grammar . . . . . . . . . . . . . . . . . . . 41
4.5 Each class implementing a single DR role . . . . . . . . . . . . . . . . . . 42
4.6 A single class implementing more than one DR role . . . . . . . . . . . . 42
4.7 Design rule implementation SDF grammar . . . . . . . . . . . . . . . . . 43
4.8 Example of a DR instance for ExampleDR design rule . . . . . . . . . . . 44
4.9 Invalid DR instance: ExampleB implements role B, but is positioned in
the instantiation as role A implementation. Similar happens to ExampleA. 44
xii
LISTINGS xiii
4.10 DR instance using a class which implements more than one role . . . . . 44
4.11 Instantiation and references of a DR role . . . . . . . . . . . . . . . . . . 45
4.12 Design rule instantiation SDF grammar . . . . . . . . . . . . . . . . . . . 46
4.13 Caesar class example: classic Figure-Display problem . . . . . . . . . . . 47
4.14 Caesar class example: classic Figure-Display problem . . . . . . . . . . . 48
5.1 Generated CaesarJ ACI for ExampleDR (Listing 4.5) . . . . . . . . . . . 52
5.2 Generic ACI after the transformation of the complements construct . . . 54
5.3 ExampleA before transformation . . . . . . . . . . . . . . . . . . . . . . 56
5.4 Generated code for ExampleA . . . . . . . . . . . . . . . . . . . . . . . . 56
5.5 CaesarJ+ DR instance and references before transformation . . . . . . . 58
5.6 Generated CaesarJ code for DR instance . . . . . . . . . . . . . . . . . . 59
5.7 Main transformation rule of CaesarJ+ compiler . . . . . . . . . . . . . . 61
5.8 Manipulation of Design Rules . . . . . . . . . . . . . . . . . . . . . . . . 63
5.9 Compilation of DR implementations . . . . . . . . . . . . . . . . . . . . . 64
5.10 Manipulation of DR instances . . . . . . . . . . . . . . . . . . . . . . . . 65
5.11 How currently CaesarJ+ compiler accepts references to DR roles . . . . . 66
6.1 CaesarJ ACI for the di!culty feature . . . . . . . . . . . . . . . . . . . . 70
6.2 CaesarJ+ Design Rule for the di!culty feature . . . . . . . . . . . . . . . 71
6.3 CaesarJ ACI for the observer design pattern . . . . . . . . . . . . . . . . 74
6.4 CaesarJ Implementation of Subject binding . . . . . . . . . . . . . . . . 75
6.5 CaesarJ+ design rule for the observer design pattern . . . . . . . . . . . 75
6.6 CaesarJ+ implementation of ObserverDR Subject binding role . . . . . . 76
6.7 LSD design rule for the HW Transaction Concern . . . . . . . . . . . . . 78
6.8 CaesarJ+ design rule for the HW Transaction Concern . . . . . . . . . . 79
6.9 CaesarJ ACI for the HW Transaction Concern . . . . . . . . . . . . . . . 79
7.1 Possible alternative DR instantiation process . . . . . . . . . . . . . . . . 87
LIST OF TABLES
3.1 Problems on Template Method solution . . . . . . . . . . . . . . . . . . . 26
3.2 Problems on Mixin solutions . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.3 Problems Enumerated on this Chapter . . . . . . . . . . . . . . . . . . . 36
4.1 Use of wildcards in parameters declarations . . . . . . . . . . . . . . . . 48
5.1 Pointcuts which need to be updated . . . . . . . . . . . . . . . . . . . . . 55
6.1 Tetris SPL Di!culty Feature: Summary of the evaluation. The acronyms
mean Statically checked (SC), Partially checked (P) and No checking (N). 72
6.2 Observer Example: Summary of the evaluation. . . . . . . . . . . . . . . 76
6.3 HW Transaction Concern: Summary of the evaluation. . . . . . . . . . . 80
xiv
CHAPTER 1
INTRODUCTION
According to David Parnas [46], modularization is a mechanism for improving the flexibil-
ity and comprehensibility of a system, enabling the reduction of its development time. A
modular design depends on developer decisions and on the programming paradigm used
for the software development, as each paradigm has its own modularization strategies.
Object-Oriented Programming (OOP), a widely adopted paradigm in software indus-
try, has the class artifact as the main unit for modularizing concerns. However, when
using OOP, some concerns cannot be well modularized, their implementation is scattered
throughout several system modules, tangled with code responsible for the implementation
of other concerns. Those are called crosscutting concerns. Aspect-Oriented Programming
(AOP) [5] is a programming mechanism proposed to modularize crosscutting concerns,
aiming to increase software modularity. AOP languages modularize these concerns by
means of a new modular unit, named aspect. Distribution, tracing, persistence and
transactional management are examples of crosscutting concerns well addressed by AOP.
Nevertheless, the use of AOP might compromise several properties of a modular de-
sign. For instance, the parallel development of classes and aspects is limited, as program-
mers are not able to write aspects until the related classes have been implemented [24].
Otherwise, aspects and class developers must be in constant communication to establish
the minimum requirements they need to provide. Moreover, evolving a class might break
the intents of an aspect. As a consequence, developers might not be able to change a
class (or even an aspect) without considering the join points advised by the aspects. In
this way, classes lose their flexibility. This problem is known as fragile pointcut [36]. The
comprehensibility is also compromised, as programmers are not allowed to reason about
a class without considering all aspects that might advise it [12]. Therefore, constructs
introduced to support crosscutting modularity might actually break class modularity [51],
creating dependencies between classes and aspects.
Aiming to mitigate these issues, some works discuss the use of Design Rules (DRs)
for specifying interfaces between classes and aspects [38, 57, 43]. They claim that these
design rules, which generalize the notion of information hiding interfaces and must be
rigorously obeyed, reduce the dependencies in Aspect-Oriented (AO) systems, decoupling
1
INTRODUCTION 2
classes and aspects and enabling their independent development. Moreover, DRs work
as a guideline for developers of Object-Oriented (OO) and AO code.
Sullivan et al. [57], for instance, compares the use of design rules since the beginning
of the development process with the obliviousness approach, where no rules for classes
and aspects are defined before the implementation. They show that the code generated
using DRs is less complex and presents less dependencies between classes and aspects.
However, their DRs are specified using natural language, which might lead to verbose,
imprecise and ambiguous specifications. Later, Griswold et al. [24] introduce Crosscutting
Programming Interfaces (XPI), which uses AspectJ to express Design Rules. A clear
limitation of XPIs is that they do not represent in an explicit way the responsibilities
of class developers. Besides that, the use of AspectJ leads to complex specifications
(pointcuts), as this language was not designed to this purpose. Furthermore, many of the
restrictions have to be defined with natural language, which cannot be statically checked.
Costa Neto [43] presents a Language for Specifying Design Rules (LSD), which has the
specific purpose of specifying DRs in AO systems. However, the interfaces generated by
LSD are specific for AspectJ, which has some aspect reusability and modularity issues,
such as lacking of aspectual polymorphism and lacking support for multi-abstraction
aspects [42].
CaesarJ [10], on the other hand, is an aspect-oriented programming language with a
strong support for reusability and modularity of aspects. It combines the AO constructs,
pointcuts and advice, with advanced OO modularization mechanisms. Also, on CaesarJ
there is no explicit di"erentiation of classes and aspects, an aspect is a CaesarJ class
(cclass) with pointcuts or advice. This language introduces the Aspect Collaboration
Interface (ACI) concept [42], which enables us to specify nested interfaces of CaesarJ
classes.
In this work, we explore CaesarJ constructs in order to check if they can express
Design Rules that enable modular development between OO and AO code. After an initial
analysis, we conclude that the concept of ACI, along with its modularization mechanisms,
is not enough for expressing clear design rules. The interfaces defined using ACIs are not
clear enough to allow parallel development of the modules, and its rules might not be
automatically checked by the language compiler, as we discussed in a previous work [49].
Thus, we propose CaesarJ+, an extension to CaesarJ that aims to increase mod-
ularity. Our extension introduces the design rules construct into CaesarJ, enabling the
specification of rules for OO and AO code. We also introduce the use of wildcards on rules
related to methods and advice, which was not available in CaesarJ ACIs. A CaesarJ+
1.1 SUMMARY OF GOALS 3
compiler, which is responsible for verifying the rules established on the Design Rules, is
also presented. This compiler is implemented using Stratego/XT [55], a language and
toolkit for program transformations. In this way, a compiler error is raised if any of the
restrictions defined within the DRs is not respected.
We evaluate CaesarJ+ using three examples, a feature from a Tetris game SPL, the
Observer design pattern [21], and one concern from the Health Watcher system [53].
We compare the interfaces defined using our Design Rules approach with the interfaces
specified using CaesarJ ACIs. Our results reveal that we have a gain of expressiveness
when using CaesarJ+, as with its DRs we are able to express and check restrictions
that could not be expressed with CaesarJ ACIs. Moreover, we still can use all CaesarJ
functionalities.
As previous work illustrate [38, 57, 43], we also believe that the use of specific De-
sign Rules decouple classes and aspects, enabling their independent development. The
hypothesis of our work is that by allowing the specification of proper design rules in
CaesarJ we can have a modular (independent) development of OO and AO code.
1.1 SUMMARY OF GOALS
Our work has the following goals:
• Analyze the concept of Aspect Collaboration Interfaces (ACI) present on CaesarJ,
verifying how we can use it to define interfaces between OO and AO code;
• Enable the definition of design rules on CaesarJ to promote the modular (indepen-
dent) development of Object-Oriented and Aspect-Oriented code;
• Provide tool support for automatically verifying restrictions established by these
Design Rules.
1.2 ORGANIZATION
This dissertation is organized as follows:
• Chapter 2 reviews essential concepts used throughout this work: Software Modu-
larity and Aspect-Oriented Programming. It also overviews CaesarJ, describing its
main constructs addressed in this work, and discusses modularity issues related to
the development of classes and aspects.
1.2 ORGANIZATION 4
• Chapter 3 explores the use of some CaesarJ constructs. It introduces implementa-
tions of a Tetris game SPL feature, using several CaesarJ modularization mecha-
nisms. We have a discussion about the modularity problems of each implementa-
tion.
• Chapter 4 presents CaesarJ+, an extension to increase CaesarJ modularity, moti-
vating and discussing all of its proposed constructs.
• Chapter 5 presents CaesarJ+ compiler, which verifies and checks the restrictions
specified on the DRs. It explains how this compiler works and discuss implementa-
tion details, which uses the Stratego/XT language and toolkit for program trans-
formations.
• Chapter 6 describes the evaluation of CaesarJ+, which consists of a comparison be-
tween the implementations of 3 case studies using both CaesarJ+ DRs and CaesarJ
ACIs to define necessary interfaces.
• Chapter 7 describes the concluding remarks of our work, discussing our contribu-
tions, the related work, limitations of our approach and the future work.
• Appendix A depicts the CaesarJ+ SDF grammar.
CHAPTER 2
BACKGROUND
In this chapter we introduce the main concepts used as base for this work. First we discuss
about Software Modularity and the concept of modularity on which this work is based
(Section 2.1). In Section 2.2 we make a brief introduction of Aspect Oriented Program-
ming, while Section 2.3 introduces CaesarJ, the programming language used on this work,
depicting its main constructs mentioned throughout this dissertation. Finally, we discuss
about modularity issues between development of classes and aspects on Section 2.4.
2.1 SOFTWARE MODULARITY
Parnas [46] concept of modularity for software development is close related to design
decisions that decompose and organize the system into a set of modules. Although
proposed more than thirty years ago, Parnas criteria of modularity are still being used
in many works on Software Engineering and several other areas. According to him, the
following attributes are expected in a modular design:
• Comprehensibility: a modular design allows developers to understand a module
looking only at: (1) the implementation of the module itself; and (2) the interfaces
of the other modules referenced by it;
• Changeability: a modular design enables local changes. If changes are necessary
in the internal implementation of a module A, the other modules that depend
exclusively on A interface will not need to change, since there is no modification in
the module interface;
• Parallel Development: the specification of module interfaces enables the parallel
development of modules. Di"erent teams might only focus in their own modules,
reducing the time-to-market and the need of communication.
Parnas proposed the information hiding principle as the criteria to be used in de-
composition of systems into modules. According to him, the parts of a system that are
more likely to change must be hidden into modules with stable interfaces. These criteria
5
2.2 ASPECT ORIENTED PROGRAMMING 6
are enforced on the Object-Oriented (OO) paradigm in which classes implementations
details are hidden and only their interfaces are exposed. However, the interaction of
Aspect-Oriented (AO) and OO languages does not follow this principle, as mentioned on
Section 2.4.
More recently, Baldwin and Clark [6] proposed a theory which considers modularity
as a key factor to innovation and market growth, independent of the industry area. Their
theory uses Design Structure Matrices (DSMs) to reason about dependencies among
artifacts and claims that the task structure organization is closely related to that de-
pendencies. In this way, if two modules are coupled, their parallel and independent
development is impossible, requiring communication between the di"erent teams, or the
implementation of both modules by a single team.
We can improve modularity by removing dependencies between design decisions, but it
is necessary to elaborate several assumptions before that. Baldwin and Clark [6] represent
these assumptions as a special kind of parameter, named as Design Rules (DRs). DRs
are less likely to change and are used as interfaces between modules [38]. In this way,
they are used to decouple design parameters, like typical programming interfaces remove
the coupling between software components. Such design rules establish strict partitions
of knowledge and e"ort at the outset of a design process. We can say that programming
interfaces are specific representations of Design Rules. The most important is that DRs
are not just guidelines or recommendations, they must be rigorously obeyed in all phases
of design and production.
Ribeiro et al. [51] made a study in which DSMs were utilized to analyze three versions
of a real software application (OO, AO, and AO using Design Rules). The version of
the system that uses Design Rules su"ered a reduction on the coupling between classes
and aspects, generating a more modular design, specially when considering semantic
dependencies [13] between them.
2.2 ASPECT ORIENTED PROGRAMMING
Aspect-Oriented Programming (AOP) [34] is a programming mechanism proposed to
modularize crosscutting concerns. These concerns often cannot be cleanly decomposed
from the rest of the system, which results in either scattering or tangling, making the
code di!cult to understand and hard to maintain. Distribution, tracing, transaction
management, persistence, among others are well-accepted examples of crosscutting con-
cerns. AOP separates these kind of concerns, avoiding scattering and tangling of code,
2.2 ASPECT ORIENTED PROGRAMMING 7
promoting a more modular system. There are several Aspect-Oriented (AO) languages,
and AspectJ [5, 32], an AO extension to Java, is the well-known AOP language.
AOP encapsulates the crosscutting concerns inside units called aspects. AOP is based
on Join Point Interception model (JPI), which defines (1) the points in the program where
the aspects should be applied, called join points, (2) a way to specify or quantify these
join points, called pointcuts, and (3) a construct to specify code to run at a join point,
usually called advice. Next we describe the main AOP constructs that can be declared
inside an aspect [33]:
• Pointcut: It defines which points in the code are related to a given crosscutting
concern, the points where the concern should be applied. Pointcuts are used to
specify a set of join points, enabling the quantification in AOP. In AspectJ we have
some primitive pointcut designators (PCDs), like call, execution, this, target,
among others, which allow us to define the desired pointcuts. Listing 2.1 presents
three AspectJ pointcuts. Pointcut coordChange defines that calls to methods setX
or setY, of the Paint class, which have just one integer parameter might be in-
tercepted by aspects. Regarding pointCreation, it specifies that the execution of
Point constructor might be intercepted as well. We can combine pointcuts using
logical operators in most AOP languages, as we can see on Line 5.
Listing 2.1 Pointcut example on AspectJ
1 pointcut coordChange ( ) : ca l l (void Point . setX ( int ) )
2 | | ca l l (void Point . setY ( int ) )
3 pointcut po intCreat i on ( ) : execution ( Point .new ( ) ) ;
4
5 pointcut po intModi f i ed ( ) : coordChange ( ) | | po intCreat i on ( ) ;
• Advice: An advice is the construct used to specify the behavior that should be
applied to a given join point. Usually it uses a pointcut which specifies the points
where the advice should be applied. On AspectJ we have three types of advice,
which are applied before, after, or around a given join point. Listing 2.2 shows
an example of an advice that use the previously declared pointModified pointcut
to update the Display class.
Listing 2.2 Advice example on AspectJ
1 after ( ) : po intModi f i ed ( ) {
2 Display . update ( ) ;
3 }
2.3 CAESARJ 8
• Inter-type declaration: It enables programmers to declare in one place members
or parents of another class. Inter-type declarations (ITDs) provide a way to express
crosscutting concerns a"ecting the structure of modules, in order to enable that all
code related to a specific concern can be concentrated into aspects. In AspectJ
we have ITDs that declare new attributes, methods, change the parent of a given
class, among others. Listing 2.3 shows examples of AspectJ ITDs. On Line 1 class
Point is being declared to inherit from FigureElement. Line 3 declares the color
attribute inside class Point, whereas we have the declaration of method setColor
to modify this attribute in Lines 5-7.
Listing 2.3 Inter-type declaration on AspectJ
1 declare parents : Point extends FigureElement ;
2
3 private Color Point . c o l o r ;
4
5 public void Point . s e tCo lor ( Color co l o r ) {
6 this . c o l o r = co l o r ;
7 }
Classes and aspects are composed by aspect compilers (weavers, such as AJDT [2]
or abc [1] for AspectJ) in a process called weaving, illustrated in Figure 2.11. AOP was
initially defined as Quantification, due to pointcuts quantification, and Obliviousness, as
class developers were initially supposed to design and codify its classes without care about
aspects that would latter be applied [20]. However, more recently some authors [57, 54]
started to claim that the obliviousness approach is not well-suited for AOP, as classes
that where not developed with aspects in mind can lead to very complex pointcuts or join
points which are not able to be captured by aspects. In this work we consider that, in
order to achieve a better modularity between OO and AO code, class developers should
be aware of aspects and its behavior.
2.3 CAESARJ
CaesarJ [10] is a Java [28] based aspect-oriented programming language with a strong
support for reusability and modularity of components. It combines the AO constructs,
pointcuts and advice, with advanced object-oriented modularization mechanisms. From
an aspect-oriented point of view, this combination of features is particularly well-suited
to make large-scale aspects reusable - one can say, it enables aspect components. From a
1Figure adapted from http://commons.wikimedia.org/wiki/File:AspectJ_Weaving.svg.
2.3 CAESARJ 9
Figure 2.1 Aspect weaving process
component-oriented view, on the other hand, CaesarJ is addressing the problem of inte-
grating independent components into an application without modifying the component
to be integrated or the application [4].
First proposed as Caesar, CaesarJ has a higher-level module concept on top of Join
point interception (JPI), an important cornerstone of AO languages, providing a better
support for expressing an aspect as a set of collaborating abstractions, and for structuring
the interaction between two parts of an aspect, aspect implementation and aspect binding
(integration with a base code) [42].
CaesarJ is not completely independent from Java, its classes interact with Java classes
and interfaces, and the program main class must be a Java class. Moreover, CaesarJ
compiler generates Java bytecode, using the AspectJ weaver to insert the advice calls into
the generated bytecode.
On the next sections a few concepts and constructs of CaesarJ used in this work are
described. More details about the language can be found on [10, 4].
2.3.1 Caesar Classes
The principal module on CaesarJ is a caesar class, represented by the keyword cclass.
Di"erent from a Java class, a caesar class can have both roles of classes (OO) and aspects
(AO) at the same time. An aspect on CaesarJ is a cclass with AspectJ based pointcuts
and/or advice. They can be instantiated and referenced as any other object, its references
2.3 CAESARJ 10
can be polymorphic, enabling aspectual polymorphism, and multiple instances of an
aspect can be created and used simultaneously.
Di"erent from AspectJ, aspects on CaesarJ are not enabled by default, they must be
explicitly activated (deployed), otherwise its pointcuts will not match any join point and
its advice will not be executed. Caesar classes can be statically or dynamic deployed, as
we can see on Listing 2.4.
Listing 2.4 Caesar class example: classic Figure-Display problem
1 public deployed cclass DisplayUpdate {
2 pointcut moveFigure ( FigureElement f e ) : ( ca l l (void FigureElement+. s e t ! ( . . ) )
3 | | ca l l (void FigureElement+.moveBy ( . . ) ) && ta r g e t ( f e ) ;
4
5 after ( FigureElement f e ) : moveFigure ( f e ) {
6 Display . update ( f e ) ;
7 }
8 }
9
10 public abstract cclass LogAspect {
11 pointcut pointChange ( Point p ) : t a r g e t (p ) && ( ca l l (void Point . s e t ! ( . . ) )
12 | | ca l l (void Point .moveBy ( . . ) ) ) ;
13 }
14
15 public cclass SimpleLog extends LogAspect {
16 after ( Point p ) : pointChange (p) {
17 System . out . p r i n t l n ( ”Point ” + p + ” changed . ” ) ;
18 }
19 }
20
21 public cclass Detai l edLog extends LogAspect {
22 void around( Point p ) : pointChange (p) {
23 System . out . p r i n t l n ( ”Point ” + p + ” actua l coords : ” p . getCoords ( ) ) ;
24 proceed ( ) ;
25 System . out . p r i n t l n ( ‘New coords o f ’ + p + ‘ : ’ p . getCoords ( ) ) ;
26 }
27 }
28
29 public class Main {
30 public stat ic void main ( Str ing [ ] a rgs ) {
31 Point p1 , p2 ;
32 LogAspect l a ;
33 . . .
34 i f ( deta i l edLog ) l a = new Detai l edLog ( ) ;
35 else l a = new SimpleLog ( ) ;
36 . .
37 deploy ( l a ) {
38 p1 .moveBy ( 5 ) ;
39 }
40 p2 .moveBy ( 3 ) ;
41 }
42 }
2.3 CAESARJ 11
The code depicted above is an extension of the classic Figure-Display example, which
has Point and Line as subclasses of FigureElement. The deployed keyword in Line 1
specifies that DisplayUpdate is statically activated, working like an aspectj aspect. Lines
34-35 show the dynamic selection and instantiation of LogAspect, while Line 37 shows its
dynamic deploy (deploy keyword). Moreover, Lines 37-39 specifies LogAspect scope of
actuation, this aspect can intercept everything can be reached by commands within this
block. It means that the join point of Line 40 (calls to Point.moveBy method, defined
on pointChange pointcut, Lines 11-12) is only matched by DisplayUpdate aspect. As
we can see on Lines 16 and 22, pointcut inheritance is allowed on CaesarJ.
Caesar classes can only inherit from other caesar classes, its not possible for them
to inherit from a Java class. However, they can implement Java interfaces. In order to
facilitate comprehension and maintain consistency with other languages, we use the term
CaesarJ class throughout this work to reference a caesar class.
2.3.2 Aspects Collaboration Interfaces - ACIs
Collaboration Interfaces (CI) were proposed by Mezini and Osterman to cope with some
limitations existent on standards interfaces [41]. On CaesarJ the CI concept was extended
to support the use of AO constructs, originating the Aspect Collaboration Interfaces
(ACIs). An ACI is a cclass which groups a set of collaboration CaesarJ classes (inner
classes).
Di"erent from Java, on CaesarJ all inner classes of a given cclass are considered
virtual classes [39], as they are handled in the same way as virtual methods. They can
be redefined in subclasses of the enclosing class, allowing us to incrementally refine a set
of collaborating classes, as we can see on Listing 2.52.
Graph is a collaboration that groups classes Edge, DirectedEdge and Node. The col-
laboration WeightedGraph inherits from Graph, redefining Edge and Node, adding the cost
attribute. As references to virtual classes are always bound to the most specific redefini-
tion known in the context of the enclosing object, the superclass of WeightedGraph.
DirectedEdge is bound to WeightedGraph.Edge. Moreover, accessing the variables
start and end in the context of WeightedGraph allows us to use the newly introduced
properties of WeightedGraph.Node, although the declaration was made in Graph.Edge
itself.
That way, it is possible to refine classes of a collaboration, introducing new methods,
2Example adapted from http://caesarj.org/index.php/ProgrammingGuide/BasicConcepts
2.3 CAESARJ 12
fields and class relationships. Thus, it is not necessary to repeat previously defined inher-
itance relationships, methods and attributes. For example, if we redefine DirectedEdge
on WeightedGraph, its not necessary to declare it as a subclass of Edge, this relationship
is automatically inherited, as WeightedGraph.DirectedEdge is identified as a refinement
of Graph.DirectedEdge.
Listing 2.5 Set of collaboration classes (ACI) for the graph example
1 public cclass Graph {
2 public cclass Edge {
3 Node s tar t , end ;
4 }
5 public cclass DirectedEdge extends Edge {
6 int d i r e c t i o n ;
7 }
8 public cclass Node {
9 public abstract void getState ( ) ;
10 }
11 }
12
13 public cclass WeightedGraph extends Graph {
14 public cclass Edge {
15 f loat cos t ;
16 }
17 public cclass Node {
18 f loat cos t ;
19 }
20 }
We can define ACIs that specify only abstract inner classes, which contain only ab-
stract operations. These kinds of ACIs can be seen as interfaces, as they have only design
purpose, without any implementation.
2.3.3 Mixin composition
On CaesarJ it is possible to compose two or more CaesarJ classes using the & operator
on the extends clause of a given cclass. This process is a type of multiple inheritance,
allowing a class to have more than one super class. As CaesarJ classes are translated
to conventional Java classes, which do not support multiple inheritance, CaesarJ uses a
mixin-based algorithm [17] to linearize all the composed classes, generating a hierarchi-
cally organized order of the superclasses.
Listing 2.6 shows an example of composition using mixins. On the depicted code,
ColoredWeightedGraph is a composition of both ColoredGraph and previously defined
WeightedGraph (Line 28). On that way, ColoredWeightedGraph contain both vir-
2.3 CAESARJ 13
tual classes originated from ColoredGraph and WeightedGraph. Moreover, virtual class
Node of composition ColoredWeightedGraph contains attributes from ColorGraph.Node,
WeightedGraph.Node and Graph.Node. Figure 2.2 shows the superclass hierarchy gener-
ated after the execution of the mixin linearization process.
Listing 2.6 Mixin composition example
22 public cclass ColoredGraph extends Graph {
23 public cclass Node {
24 Color co l o r ;
25 }
26 }
27
28 public cclass ColoredWeightedGraph extends ColoredGraph & WeightedGraph { }
!"#"$%&'%()*%&+$,-* !"#"$%&+$,-* '%()*%&+$,-* +$,-*
Figure 2.2 Mixin linearization: Generated inheritance hierarchy
An interesting point about mixin composition is the way how it manages inheritance
links between virtual classes. A collaboration can refine its super collaboration with
new virtual classes and new inheritance links. The inheritance hierarchies of such refine-
ments can be merged using mixin composition. For example, suppose that we have a
new kind of graph, SpecialColoredWeightGraph, which refines ColoredWeightedGraph
(Listing 2.7).
Listing 2.7 SpecialColoredWeightedGraph collaboration
30 public cclass SpecialColoredWeightedGraph extends ColoredWeightedGraph {
31 public cclass Specia lEdge extends Edge {
32 . . .
33 }
34 public cclass DirectedEdge extends Specia lEdge {
35 }
36 }
This new collaboration defines a new edge, SpecialEdge (lines 31-33), which inher-
its from the previously defined Edge class. Besides that, this new collaboration refines
DirectEdge (Line 34), declaring that it now inherits from SpecialEdge (initially it was
subclass of Edge, as we can see on Line 5 of Listing 2.5).
Figure 2.3(a) shows the contents of ColoredWeightedGraph. The gray boxes rep-
resent virtual classes and relationships which were inherited, not declared inside the
2.3 CAESARJ 14
!"#"$%&'%()*%&+$,-*
(a)
!"#$%&'()')*#+,#%-.#+/*&".
(b)
Figure 2.3 ColoredWeightedGraph (a) refined by SpecialColoredWeightedGraph (b)
ColoredWeightedGraph cclass itself. Figure 2.3(b) depicts SpecialColoredWeightGraph.
The black boxes represent virtual classes declared or refined inside this new collaboration,
while the gray boxes are virtual classes inherited from ColoredWeightedGraph. As we
can see, the inheritance of DirectedEdge is modified, now it inherits from the new de-
clared cclass SpecialEdge. Although DirectedEdge is an empty cclass on Listing 2.7,
due to the refinement properties of CaesarJ virtual classes we can access all operation
and attributes of Graph.DirectedEdge (like direction, see Line 6 of Listing 2.5) when
using objects of SpecialColoredWeightedGraph.DirectedEdge.
2.3.4 Wrapper Classes
Wrapper is a mechanism introduced in CaesarJ to adapt (bind) an existing class to a role
defined in a collaboration. Wrapper classes, which are identified by the wraps clause (like
extends), are virtual classes which depend on an application object. They can access the
state of the enclosed object using the wrappee keyword, and can potentially introduce
additional state and operations to the wrapped object.
Listing 2.8 shows an example of wrapper classes, adapting existing classes Point and
Shape to the Node role defined on the Graph collaboration (see Listing 2.5). As wrapper
classes were proposed to increase reuse, it is possible to reuse the implementation of Edge,
DirectEdge and part of Node implementation (Graph Impl, Lines 38-42) and adapt the
Node role to its specific usage. When a Point is a node, the state of this node is given by
the coordinates of the Point, whereas the state of a node is the state of a Shape object
when we have a Node being a Shape.
As we can see on Listing 2.8, first Graph Impl is composed with PointWrappers to
2.4 DEVELOPMENT OF CLASSES AND ASPECTS: MODULARITY ISSUES 15
generate PointGraph (Line 57) and then the same implementation is reused and com-
posed with ShapeWrapper to generate ShapeGraph (Line 58). Although on this example
we are not showing any reuse of wrapper classes, it is also possible. If we have an-
other implementation of Graph, like ColoredGraph , we can reuse the existing bindings
PointWrapper and ShapeWrapper to generate new combinations of graph on which points
and shapes represent the nodes.
Listing 2.8 Wrapper classes
38 public cclass Graph Impl extends Graph {
39 public cclass Edge { . . . }
40 public cclass DirectedEdge { . . . }
41 public cclass Node { . . . }
42 }
43 public cclass PointWrapper extends Graph {
44 public cclass PointNode extends Node wraps Point {
45 public void getState ( ) {
46 System . out . p r i n t l n ( ” ( ” wrappee . getX ( ) , + ” , ” + wrappee . getY ( ) +” ) ” ) ;
47 }
48 }
49 }
50 public cclass ShapeWrapper extends Graph {
51 public cclass ShapeNode extends Node wraps Shape {
52 public void getState ( ) {
53 System . out . p r i n t l n (wrappee . ge tState ( ) ) ;
54 }
55 }
56 }
57 public cclass PointGraph extends Graph Impl & PointWrapper { }
58 public cclass ShapeGraph extends Graph Impl & ShapeWrapper { }
2.4 DEVELOPMENT OF CLASSES AND ASPECTS: MODULARITY ISSUES
As previously introduced in Section 2.2, Aspect-Oriented Programming (AOP) has been
proposed as a technique for modularizing crosscutting concerns. However, the use of AOP
can bring modularity problems, as developers must consider all aspect implementations
in order to reason about a specific class [57, 54, 12].
By referring to class implementation details in aspects, one can compromise modular
reasoning and changeability, requiring class modifications to be fully aware of which as-
pects a"ect a given class. Therefore, constructs aimed to support crosscutting modularity
might actually break class modularity [51]. As there is no interface between classes and
aspects, the parallel development of them is also compromised.
In order to avoid this conflict, some authors discuss how to expose aspect-oriented
interfaces and how to compute module interfaces in AOP systems. Sullivan initially
2.4 DEVELOPMENT OF CLASSES AND ASPECTS: MODULARITY ISSUES 16
!"#$%&'&$())!"#$%&!'!!!!$%&!()!*+''''!"#$%&'*+%,!,-&./$%&!(0!'!&1$,2(!3!(!4''''!"#$%&'*+%,!,-&5/$%&!*0!'!&1$,2*!3!*!4!!!!!!!!2224
!"#$%&'()!-&.!6789&-:$,7;9*!'''''!+%/.&".'7#$%&6789&-/"#$%&!70<!.(01-./70!=''''''''')-./>!"#$%&2>0!??!&($$/>!"#$%&2,-&>/2200+''''(2.-0/"#$%&!70<!7#$%&6789&-/70!'!!!!!!!!!:$,7;9*2@789&-/70+!!!!!44
!"#$$%&'('")*'+
,-.%&/$*"#0%/$%1)2%3'/14%5*6#2'6%%%%%%7-'1%#%8)/12%9-#14':%;%1''6%2)%6)%/22
<$*'92%&'('")*'+
='0>%?*6#2'&/$*"#0%#$*'92%#"+'#60%%%%%%5*6#2'$%&/$*"#0@%&)1A2%0)5%$''%/2:
Figure 2.4 Modularity Issues between Classes and Aspects
presented a comparative analysis between an AO system developed using an oblivious
approach and the same system developed using design rules which document interfaces
between classes and aspects [57]. The approach using design rules promises benefits when
relevant crosscutting behavior is anticipated. However, this solution uses natural language
to express the design rules, which may lead to verbose and ambiguous interpretation, not
mentioning the fact that it cannot be statically checked.
In later works [24, 56], they propose to express and check the design rules using
AspectJ, calling the approach Crosscutting Programming Interfaces (XPI). They claim
that one of the main benefits of its approach is that it does not require any new construct
in the language. However, as AspectJ was not designed for this purpose, its not possible to
express and check most constraints required for defining the responsibilities of classes and
aspects using the proposed XPI language, and the written specification can become very
complex. Natural language is used along with AspectJ code to specify some restrictions.
Costa Neto proposed a Language for Specifying Design Rules (LSD) [44] in order to
enable the definition of more precise design rules between OO and AO code. LSD Design
Rules impose both structural and behavioral restrictions over Java and AspectJ code, and
its compiler is able to statically check most of these restrictions. Beside having a Java
and AspectJ-like syntax, LSD introduces many new constructs, which require developers
to learn a new language.
Compared to other AO languages, CaesarJ introduces many new features and benefits.
Our objective in this work is to enable the specification of design rules in CaesarJ, without
modifying the existing compiler. For this we propose CaesarJ+, an extension to CaesarJ
where code is pre-compiled and transformed into valid CaesarJ code. This extension is
2.4 DEVELOPMENT OF CLASSES AND ASPECTS: MODULARITY ISSUES 17
presented on Chapter 4.
On the next chapter we discuss some issues found when using CaesarJ to specify
Design Rules to enable a more modular design.
CHAPTER 3
EXPLORING CAESARJ
In this chapter we explore the CaesarJ constructs Wrappers, Aspect Collaboration In-
terfaces and Mixin Composition introduced on Section 2.3, using them to implement
multiples versions of a Tetris Software Product Line (SPL) [47] example. A brief analysis
focusing on support for modular development of Aspect-Oriented and Object-Oriented
code is made for each implementation. This chapter is organized as follows: Section 3.1
describes the Tetris SPL example used in this chapter, whereas Sections 3.2, 3.3 and
3.4 describe implementations using Template Method, Mixin Composition and Wrapper
classes, respectively.
3.1 TETRIS SPL EXAMPLE
In order to explore the mentioned CaesarJ constructs, we use a simple Software Prod-
uct Line of Tetris games for mobile phones1. A SPL is an approach that enables the
generation of related software products from reusable assets, such as classes, aspects and
requirements, bringing an increase in productivity [47, 58]. This Tetris SPL generates,
among others, products (i) with normal di!culty, which shows only the next piece (tetris
block) that will appear, and (ii) with easy di!culty, showing the next two pieces, as
illustrated in Figure 3.1. It is important to note that some devices are not able to display
two next pieces, due to their limited screen-size.
As illustrated in the diagram of a single product of this SPL (Figure 3.2), TetrisCanvas
is the class responsible for organizing all components on the screen (board, pieces and
the information boxes), whereas the NextPiece class is responsible for showing the next
Tetris block (piece) that will appear on the game.
Starting from a single product, in order to implement the di!culty feature we need dif-
ferent versions (variations) of the following methods of NextPiece: (a) paintBox, which
is called by other methods of NextPiece (paint, for example) to repaint the box that
shows the next piece, and (b) updatePiece, which is called by the TetrisCanvas class to
update the next piece that will be displayed, as we can see in Figure 3.3. Also, there are
1The code of the single application used to extract this SPL can be downloaded at [31].
18
3.1 TETRIS SPL EXAMPLE 19
Figure 3.1 Tetris game: normal di!cult (left) and easy di!cult (right).
+paint( g : Graphics ) : void+drawPiece( type : int ) : void+updatePiece() : void+paintBox( g : Graphics ) : void
...
NextPiece
-np : NextPiece...
+init() : void+sideBoxes() : void
...
TetrisCanvas
TetrisConstants
DropThread
TetrisBoard
TetrisMidlet
DisplayBox
TetrisPiece TitleBox InfoBox
Figure 3.2 Tetris Game - Single product diagram
3.2 TEMPLATE METHOD 20
multiple scattered calls to NextPiece methods (updatePiece) on TetrisCanvas, which
is a class that does not need to vary to enable the di"erent variations of the di!culty fea-
ture. It is important to note that, when painting the box contents, the paintBox method
has to access non-variant members of NextPiece (like drawPiece, see Figure 3.3), which
characterizes a mutual (bi-directional) dependency: non-variant methods call variant
methods, while variant methods also call invariant operations.
Figure 3.3 Classes TetrisCanvas and NextPiece
There are multiple ways to implement these variations, including OO [40] techniques
(using design patterns) and AO techniques [34]. In order to analyze the support for mod-
ularity provided by CaesarJ we use in the following sections three di"erent approaches
(OO template method design pattern, Mixin Composition and Wrapper classes) to im-
plement the di!culty feature of this SPL using CaesarJ. For each approach we present
two di"erent implementations, one without using ACIs, and a second one using ACIs
to establish an interface that tries to guide the development of both common code and
variation code.
3.2 TEMPLATE METHOD
In this section we introduce CaesarJ implementations of the di!culty feature using the
Template Method design-pattern. Note that on Section 3.2.1 no CaesarJ specific con-
struct besides cclass is used in our implementations, while on section 3.2.2 the ACI
construct is introduced.
3.2.1 Template Method without ACIs
Listing 3.1 presents a possible implementation for the di!culty feature in CaesarJ using
the Template Method design pattern [21]. In this implementation we aim to achieve reuse
of the invariant (common) part of the feature implementation, while the variation part
3.2 TEMPLATE METHOD 21
is implemented in separated modules.
Listing 3.1 Template Method
abstract cclass NextPiece {
. . .
void paint ( ) { . . . paintBox () ; . . . }
void drawPiece ( int type ) { . . . }
abstract void updatePiece ( ) ;
abstract void paintBox ( ) ;
. . .
}
cclass NormalVariation extends NextPiece {
void updatePiece ( ) { . . . }
void paintBox ( ) { . . . drawPiece ( type ) . . . }
}
cclass EasyVar iat ion extends NextPiece {
void updatePiece ( ) { . . . }
void paintBox ( ) { . . . drawPiece ( type ) . . . }
}
In this solution, NextPiece is an abstract cclass that contains the implementation
of the common code (methods that will not vary, as drawPiece) and the signature of
the variant methods, updatePiece and paintBox. As detached on the code, invariant
method paint calls paintBox, which characterizes the template method. Each variation
is implemented in a single cclass (NormalVariation and EasyVariation), which inher-
its from the invariant class (NextPiece), providing the code for the abstract methods. A
factory can be used to instantiate and return the proper variation for each product.
A problem with this implementation is that we have design and implementation
tangling (problem labeled P1). The specification of the variations (abstract signatures)
is tangled with the implementation of other NextPiece methods, which implies that the
variations can only be implemented after the invariant class is defined. It is not possible
to split the development between two teams, one responsible for the common part and
the other responsible for the variation part.
An enhancement to this solution would be the specification of an interface on top of
the NextPiece cclass (Listing 3.2), specifying the signatures of all methods (including
the variable ones). In this solution, NextPiece now only has the implementation of
the common methods, but remains abstract, because it only implements the invariant
methods of INextPiece. Variations continue to be implemented on NormalVariation
and EasyVarition cclasses, which were omitted because they are exactly the same as
described on Listing 3.1.
3.2 TEMPLATE METHOD 22
Listing 3.2 Interface for Template Method
interface INextPiece {
. . .
void paint ( ) ;
void drawPiece ( int type ) ;
void updatePiece ( ) ;
void paintBox ( ) ;
}
abstract cclass NextPiece implements INextPiece {
. . .
void paint ( ) { . . . paintBox ( ) ; . . . }
void drawPiece ( int type ) { . . . }
. . .
}
Although it separates the design from implementation (solving P1), this enhancement
brings two problems: (P2) it is not possible to explicitly specify in the interface
which methods are related to common part and which are related to the varia-
tion part; and (P3) the variation code cannot be compiled independently of the
common code, because variations extend the class used for the implementation of the
invariant code (see Figure 3.4), which implies that a part of variation code development
can only be done after the implementation of the common code. Considering P2, one
can say that the use of comments on the interface is enough to specify the common and
the variation roles. In this way, developers may decide to follow or not the specification
of the comments. Thus, it is not possible to ensure (static check) that the specification
made by these comments is being obeyed, as comments are ignored by compilers.
INextPiece
NextPiece
EasyVariation NormalVariation
Figure 3.4 Template Method without ACIs: variations depend on invariant code (inheritance).
3.2 TEMPLATE METHOD 23
3.2.2 Template Method with ACIs
Aiming to solve problems P2 and P3 (Section 3.2.1) we use ACIs to specify interfaces that
provide a more modular design, trying to enable the parallel development of common and
variate code. Our first thought was to generate a kind of Design Rule which specifies that
two roles are needed for this implementation, base and variation. As an ACI can contain
more than one cclass, we tried to use it as a container to specify the classes that must
be implemented in our code, in order to split the development of base and variations so
it can be done in parallel.
Listing 3.3 presents NextPieceACI, our first idea of design rule in CaesarJ for this
variant. In Line 1 we have the declaration of the interface, which is an ACI containing
another CaesarJ class. Lines 2 and 9 present the declaration of cclasses that must
be implemented. Lines 3-6 and 10-11 specify the methods that must be present on the
implementation of the virtual classes, similar to a Java interface. However, as specified
on Section 3.1, the di!culty feature demands a mutual dependency between base and
variation (paintBox is called by other methods of NextPiece - e.g. paint, and paintBox
uses another methods of NextPieceBase - e.g. drawPiece), which is not possible to
specify using the design rule of Listing 3.3, as methods of NextPieceBase can not see
methods of NextPieceVariation.
Listing 3.3 NextPieceACI, Template Method
1 abstract cclass NextPieceACI {
2 abstract cclass NextPieceBase {
3 . . .
4 abstract void paint ( ) ;
5 abstract void drawPiece ( int type ) ;
6 . . .
7 }
8
9 abstract cclass NextPieceVar iat ion extends NextPieceBase {
10 abstract void updatePiece ( ) ;
11 abstract void paintBox ( ) ;
12 }
13 }
Listing 3.4 shows a CaesarJ interface that enables this mutual dependency. Lines 7 and
8 are the only di"erence between this interface and the one in Listing 3.3. At a first glance,
these lines look unnecessary because they are re-declared at NextPieceVariation, which
is a sub-class of NextPieceBase. However, they enable the use of both updatePiece
and paintBox by members of NextPiece, enabling the bi-directional dependency. This
mutual dependency could be easily achieved with the use of AspectJ like intertype dec-
3.2 TEMPLATE METHOD 24
larations, which are not supported by CaesarJ.
Listing 3.4 NextPieceACI enabling the bi-directional dependency, Template Method
1 abstract cclass NextPieceACI {
2 abstract cclass NextPieceBase {
3 . . .
4 abstract void paint ( ) ;
5 abstract void drawPiece ( int type ) ;
6
7 abstract void updatePiece ( ) ;
8 abstract void paintBox ( ) ;
9 . . .
10 }
11
12 abstract cclass NextPieceVar iat ion extends NextPieceBase {
13 abstract void updatePiece ( ) ;
14 abstract void paintBox ( ) ;
15 }
16 }
Listing 3.5 shows the implementation of the NextPieceACI interface. As our interface
is a Collaboration Interface, its roles (inner cclasses) must be implemented by virtual
classes, inside collaborations that inherit from our design rule. On Line 1 we have the
declaration of NextPiece Impl, a collaboration that inherits from NextPieceACI. This
collaboration is abstract because it only implements the invariant role of the interface.
Lines 2-7 show the refinement of the virtual class NextPieceBase, which was previ-
ously defined on the ACI. This refinement implements the methods of NextPieceBase
role. However, this refined class cannot be instantiated (abstract), because methods
updatePiece and paintBox present on NextPieceBase are only implemented by the
variations.
Listing 3.5 Implementations of NextPieceACI, Template Method
1 abstract cclass NextPiece Impl extends NextPieceACI {
2 abstract cclass NextPieceBase {
3 . . .
4 void paint ( ) { . . paintBox ( ) . . . }
5 void drawPiece ( int type ) { . . . }
6 . . .
7 }
8 }
9
10 cclass EasyVar iat ion Impl extends NextPiece Impl {
11 cclass EasyVar iat ion extends NextPieceVar iat ion {
12 void updatePiece ( ) { . . . }
13 void paintBox ( ) { . . . drawPiece ( type ) . . . }
14 }
15 }
3.2 TEMPLATE METHOD 25
EasyVariation Impl (10-15) is the collaboration which contains EasyVariation (Lines
11-14), a virtual class responsible for the implementation of NextPieceVariation (vari-
ation role of our interface). Other variants (such as normal) would have similar code
structure, di"ering only on the implementation of the methods that vary (updatePiece
and paintBox). In that way, now developers must instantiate first the cclass that con-
tain the implementation of the virtual class, and then they can instantiate the virtual
class itself, as we can see on Listing 3.6
Listing 3.6 Instantiation of the variation
public class Main {
public stat ic void main ( Str ing [ ] a rgs ) {
. . .
EasyVar iat ion Impl easyImpl = new EasyVar iat ion Impl ( ) ;
NextPieceACI . NextPieceVar iat ion easyVar = easyImpl .new EasyVar iat ion ( ) ;
. . .
}
}
Analyzing the interface NextPieceACI (Listing 3.4), we see that it completely solves
P1, this interface is only concerned with design. Although the interface contains two
abstract inner-classes that must be implemented, it is explicitly stated if updatePiece
and paintBox should be implemented only by the variations (NextPieceVariation sub-
classes) or if it should be implemented by the base part (subclasses of NextPieceBase)
and redefined by the variations. It may mislead the developers when looking only at the
ACI, leaving problem P2 only partially solved. Besides that, as we can see on the im-
plementation of the interface (Listing 3.5), due to the use of the template method design
pattern, the implementation of the variations are still coupled with the implementation
of the base code. As the implementation of the variations inherits from the common code
implementation (for example, EasyVariation Impl extends NextPiece Impl), it is not
possible to have a separated compilation of the variations (P3), as on Section 3.2.1.
Moreover, the code of Listing 3.5 is a little confusing. The use of virtual classes
makes the code harder to understand (confuse) (P4). It is necessary to write both
collaborations, NextPiece Impl and EasyVariation Impl, only to contain the virtual
classes implementing NextPieceACI roles. The result code would be simpler and cleaner
if we had a solution in which NextPieceBase and EasyVariation could be directly
written in top-level classes (without using virtual classes), respecting the specifications
of our interface.
Table 3.1 summarizes the problems faced on this section. A “-” in a cell represents
that a problem does not occur on a given approach, while “X” indicates that a problem
3.3 MIXIN COMPOSITION 26
occurs and “O” means that a problem partially occurs using a approach.
Table 3.1 Problems on Template Method solution
Template Method
Problems No ACI ACI
P1 - Design and implementation tangling O -
P2 - Roles not well defined on the interface X O
P3 - No separate compilation X X
P4 - Confusing code due to use of virtual classes - X
P1 occurs only on the first solution of Section 3.2.1, while the second solution using a
Java interface and the solutions using ACI avoid this problem. P2 can only be partially
avoided on the solutions with ACI, the ACI is confusing due to the repetition of methods
on both common and variation roles (see Listing 3.4). P3 occurs on both solutions (with
and without ACI), due to the use of template method on the implementation, while P4
arises from the use of virtual classes, which brings overhead to the code.
3.3 MIXIN COMPOSITION
One of CaesarJ constructs is the mixin-based composition mechanism [17], which enables
a class to have multiple super classes (multiple inheritance). With the use of mixins we
can partially implement a CaesarJ class (or a collaboration) in multiple modules and
then join these implementations in a single module. In this section we explore the use of
CaesarJ mixins to implement our SPL example, trying to achieve a more modular design,
which enables the parallel development of common and variation code. Throughout this
section we show two types of implementations, with and without using ACIs.
3.3.1 Mixins without ACIs
Our first use of mixins to implement the di!culty feature is very similar to the INextPiece
of Listing 3.2. The only di"erence is that we use an abstract CaesarJ class as our inter-
face (instead of a traditional one) and implement it in separate modules, NextPieceBase,
EasyVariation and NormalVariation, as we can see on Figure 3.5.
Analyzing the figure, NextPieceConcrete is the class that joins the partial implemen-
tations of base and variations, defining which variation would be used. On Listing 3.7
3.3 MIXIN COMPOSITION 27
Figure 3.5 Diagram of Mixin implementation without use ACIs
we can see a possible implementation of NextPieceConcrete, which specifies the use of
EasyVariation on the mixin list (extends clause). To enable other variations we can
have multiple versions of NextPieceConcrete, each one with a di"erent variation on
the extends clause, and then use a build mechanism along with a Configuration Knowl-
edge [16, 7] to put the specific NextPieceConcrete for each product of the SPL.
This solution enables the independent compilation of common and variation code, now
they depend only on NextPiece interface. However, NextPiece has the aforementioned
problem P2 (Section 3.2.1), it is not clear that two di"erent roles are specified on this
interface, which should be used as a guide for the development of common and variantion
roles. Besides that, on this implementation developers handle instances of the mixin
class, instead of instantiating classes that they implemented (NextPieceBase or
EasyVariation). We label this problem as P5. On this example, NextPieceConcrete
is the mixin class, it joins the classes that implement the ACI. In this way, developers
need to create objects of NextPieceConcrete type, but there is no specification of this
class-name on the interface, and developers cannot change this name without defining a
new cclass.
Listing 3.7 NextPieceConcrete class: Mixin of NextPieceBase and EasyVariation
cclass NextPieceConcrete extends NextPieceBase & EasyVar iat ion {
}
Next we show our implementation of the di!culty feature using ACIs, trying to solve
the open problems.
3.3 MIXIN COMPOSITION 28
3.3.2 Mixins with ACIs
Looking back to the interface (ACI) of Listing 3.4 and its implementation (Listing 3.5,
section 3.2.2), we can see that variations depend on the invariant code due to the inheri-
tance relationship, which is necessary because this implementation follows the template
method design pattern. Using mixin composition we can partially implement our inter-
face, eliminating this dependency, as we can see on Listing 3.8, keeping the same ACI of
Listing 3.4.
Lines 1-8 depict the implementation of the common part, NextPiece. Here, di"erent
from Listing 3.5, as variation code does not depend on common code implementation, the
virtual class that implements the invariant code can refine or extend the NextPieceBase
role (we can see in in Line 2 that inheritance is being used).
In Lines 10-15 of Listing 3.8 we have the definition of EasyVariation Impl, collabo-
ration responsible for the implementation of the variation code. Di"erent from the tem-
plate method version, the variations now depend only on the interface (NextPieceACI),
enabling the independent compilation of common and variation code (solving P3). Be-
sides that, this collaboration can not be instantiated, because it implements only part
of the interface. Instead, developers now have to instantiate the composition of both
invariant and variant code (P5), which is represented by NextPieceConcrete, defined
inside of mixin NextPieceMixin (18-21). This is a drawback of this solution, because, as
aforementioned, there is no specification of NextPieceConcrete nor NextPieceMixin on
NextPieceACI (our interface) and it is not possible to specify it dynamically. Moreover,
as we are using the same ACI of Listing 3.4, problem P2 remains open.
Listing 3.8 Implementation of NextPieceACI using Mixin Composition
1 abstract cclass NextPiece Impl extends NextPieceACI {
2 abstract cclass NextPiece extends NextPieceBase {
3 . . .
4 void paint ( ) { . . paintBox ( ) . . . }
5 void drawPiece ( int type ) { . . . }
6 . . .
7 }
8 }
9 abstract cclass EasyVar iat ion Impl extends NextPieceACI {
10 abstract cclass EasyVar iat ion extends NextPieceVar iat ion {
11 void updatePiece ( ) { . . . }
12 void paintBox ( ) { . . . drawPiece ( type ) . . . }
13 }
14 }
15 cclass NextPieceMixin extends NextPiece Impl & EasyVar iat ion Impl {
16 cclass NextPieceConcrete extends NextPiece & EasyVar iat ion { }
17 }
3.3 MIXIN COMPOSITION 29
Also, the use of mixin composition to implement collaborations allows us to define
roles on the interface (ACI) that are not on the same hierarchy, which was not possible
using template method. Our interface of Listing 3.4 (NextPieceACI, template method)
only defines two virtual classes because they are on the same hierarchy (one extends
the other). That way, we can now specify another role on NextPieceACI, for example,
Canvas. The definition of this role on the ACI is useful to avoid the scattered calls of
the updatePiece method, which occurs on the TetrisCanvas class, as introduced on
Section 3.1. As an aspect on CaesarJ is a simple cclass with pointcuts or advice, we can
extend NextPieceBase with a pointcut that captures the execution of Canvas methods
that call updatePiece (see Figure 3.3), as we can see on Listing 3.9. We could also have
defined pointcuts and advice on the solution of Section 3.2.2. However, due to the use of
the Template Method design-pattern on the implementation, it is not possible to specify
the Canvas role on the ACI, which is essential to guarantee that the desired join points
could be match.
The enhanced version of NextPieceACI now has three roles. NextPieceVariation is
exactly the same of Listing 3.4. Canvas (Lines 19-22), the new virtual class, defines that
methods init and sideBoxes must exist. In this way, we can write a pointcut on the
base role that matches executions of these methods, as we can see on NextPieceBase’s
matchCanvas (9-10).
Listing 3.9 NextPieceACI with the Canvas role
1 abstract cclass NextPieceACI {
2 abstract cclass NextPieceBase {
3 . . .
4 abstract void paint ( ) ;
5 abstract void drawPiece ( int type ) ;
6
7 abstract void updatePiece ( ) ;
8 abstract void paintBox ( ) ;
9 pointcut matchCanvas ( ) : execut i on (! Canvas . i n i t ( ) )
10 | | execut i on (! Canvas . s ideBoxes ( ) ) ;
11 . . .
12 }
13
14 abstract cclass NextPieceVar iat ion extends NextPiece {
15 abstract void updatePiece ( ) ;
16 abstract void paintBox ( ) ;
17 }
18 abstract cclass Canvas {
19 abstract void i n i t ( ) ;
20 abstract void s ideBoxes ( ) ;
21 }
22 }
3.3 MIXIN COMPOSITION 30
Listing 3.10 Mixin implementation of NextPieceACI with Canvas role
1 abstract cclass NextPiece Impl extends NextPieceACI {
2 abstract cclass NextPiece extends NextPieceBase {
3 . . .
4 void paint ( ) { . . paintBox ( ) . . . }
5 void drawPiece ( int type ) { . . . }
6
7 after ( ) : matchCanvas ( ) { . . . updatePiece ( ) ; . . . }
8 . . .
9 }
10 }
11
12 cclass Tetr i sCanvas Impl extends NextPieceACI {
13 cclass Tetr i sCanvas extends Canvas {
14 void i n i t ( ) { . . . }
15 void s ideBoxes ( ) { . . . }
16 }
17 }
18
19 cclass NextPieceMixin extends NextPiece Impl & EasyVar iat ion Impl & Tetr i sCanvas Impl {
20 cclass NextPieceConcrete extends NextPiece & EasyVar iat ion {
21 }
22 }
Listing 3.10 shows the implementation of this enhanced NextPieceACI. Lines 1-10
depict the collaboration that defines the implementation of the base part. The main
di"erence here is that we have an after advice which uses the matchCanvas pointcut
defined on the NextPieceBase role of NextPieceACI. This advice is responsible for
calling updatePiece, which is a variation method defined on both base and variation
roles, enabling invariant methods to call it, every time matchCanvas matches a join point
on the execution of our system. We omit the implementation of the variation role because
it is the same of Listing 3.8 (EasyVariation Impl). TetrisCanvas Impl (12-17) is the
collaboration that defines TetrisCanvas, the implementation of Canvas role.
The composition mixin NextPieceMixin (19-22) joins the implementation of the three
roles specified in the interface. It defines NextPieceConcrete class, which joins the im-
plementation of both NextPieceBase and NextPieceVariation roles, creating a concrete
class. NextPieceConcrete is necessary due to the bi-directional dependency of the roles
NextPieceBase and NextPieceVariation, which can be developed in parallel. In order
to support this dependency, the signature of some variation methods are redefined inside
the base definition. This way, implementation of both invariant and variation roles must
be abstract (because they only implement part of the role). This inner-mixin is necessary
to enable the instantiation of one of these classes.
As the Canvas role does not depend on any other role, its implementation can
3.3 MIXIN COMPOSITION 31
be concrete and no other inner-mixin related to Canvas needs to be specified inside
NextPieceMixin. It is important to note that on scenarios without this mutual depen-
dency the partial implementations do not need to be abstract (like Canvas for example,
which does not vary), and it is not necessary to define a virtual mixin (NextPieceConcrete)
composing the partial implementations inside the mixin class.
Our extended interface of Listing 3.9 has the same drawbacks P2 and P4 of the solu-
tion introduced on Listing 3.5. Moreover, the use of CaesarJ mixin composition brings
us another problem: CaesarJ compiler only obligates the implementation of vir-
tual classes of concrete collaborations [4]. We label this problem P6. As we are
using NextPieceACI as a kind of design rule, our objective is to obligate the implemen-
tation of all the roles specified inside it, which is not enforced by the CaesarJ compiler.
Therefore, if our composition mixin NextPieceMixin lacks the implementation for the
Canvas role (as we can see on Listing 3.11), or the implementation of both dependent roles
NextPieceBase and NextPieceVariation, no error message is given by the compiler.
As the NextPieceBase role of NextPieceACI specifies a pointcut that references the
Canvas role, if Canvas is not implemented as specified on the interface the pointcuts may
not match any join point, disabling advice that use these pointcuts.
Listing 3.11 Invalid mixin NextPieceMixin: No error given by CaesarJ compiler.
cclass NextPieceMixin extends NextPiece Impl & EasyVar iat ion Impl {
cclass NextPieceConcrete extends NextPiece & EasyVar iat ion {
}
}
Table 3.2 Problems on Mixin solutions
Mixin Implementations
Problems No ACI ACI
P2 - Roles not well defined on the interface X O
P4 - Confusing code due to use of virtual classes - X
P5 - Instantiate only mixin classes X X
P6 - Compiler does not check all ACI roles - X
Table 3.2 summarizes the problems faced on this section. As aforementioned, P2
remains partially opened, while P4 occurs on solutions with ACI, which use virtual classes.
P5 obligates developers to instantiate only objects of the mixin type, instead of objects
of the type of classes used to implement the roles. It is important to note that P6 only
3.4 WRAPPERS 32
occurs because the solution with ACI enables the specification of multiple roles in a single
interface, which is very useful for writing design rules.
3.4 WRAPPERS
Wrapper classes are used on CaesarJ as a mechanism to adapt external classes, intro-
ducing new state and operations on it dynamically [4]. On this section we explore this
feature of CaesarJ, trying to implement the variations as Wrapper classes that adapt
classes containing the invariant behavior, aiming to achieve a more modular design which
enables the reuse of the common code.
3.4.1 Wrappers without ACIs
In order to instantiate a wrapper class we need to specify an instance of the class that
is wrapped. As Wrapper classes were proposed to adapt an existing class to a specific
context of a collaboration, we use in our example NextPiece as the class to be wrapped
(containing the invariant code) and we define a collaboration for each variation, in order
to enable the adaptation of the common code to the specific context of each variation.
Thus, in order to instantiate a variation we use a invariant-type object as a parameter
(i.e. developers have to handle at least instances of two di"erent types). Our first
implementation using wrappers is shown on Listing 3.12.
Listing 3.12 First implementation using wrappers
1 cclass NextPiece {
2 void paint ( ) { . . paintBox ( ) . . . }
3 void drawPiece ( int type ) { . . . }
4 }
5
6 cclass EasyVar iat ion Impl {
7 cclass EasyVar iat ion wraps NextPiece {
8 void updatePiece ( ) { . . . }
9 void paintBox ( ) { . . . wrappee . drawPiece ( type ) . . . }
10 }
11 }
Lines 6-11 depicts the EasyVariation Impl, collaboration responsible for the defini-
tion of the wrapper cclass EasyVariation (7-10). On CaesarJ all wrapper classes must
be virtual classes, it is not possible to declare top-level (not virtual) wrapper classes,
that is the only reason we declare EasyVariation Impl in this solution, as the wrapper
class EasyVariation must be a virtual class. As we can see on Line 7 (keyword wraps),
EasyVariation is responsible for wrapping objects of NextPiece (1-4) type. However,
3.4 WRAPPERS 33
this implementation does not compile. As we can see on Line 2, due to the bi-directional
dependency of invariant and variation code, the paint method calls paintBox, which
is defined only on the variation. Methods of the invariant class NextPiece cannot see
variation methods, invariant code cannot depend on variant code (P7). On the
other hand, the variation, implemented on the wrapper class EasyVariation, can easily
access all methods and attributes of the common class (wrapped class) using the wrappee
keyword, as depicted in Line 9.
One way to implement the di!culty feature using wrapper classes is to remove the
common-variation dependency using inversion of control (pointcuts and advices). In this
way, methods of NextPiece would no longer call the variant methods (updatePiece or
paintBox), while methods that vary are free to access invariant methods by using the
wrappee keyword, as we can see on Listing 3.13.
The common code now does not depend on the variation code directly. Instead, the
variation has an advice that acts after the execution of NextPiece paint method (6-8).
Although it may work on this small example, on more complicated cases it is not that
simple to invert that dependency using pointcuts and advice only. Sometimes it is not
possible to write a pointcut that matches the exact join point desired, being necessary to
re-write the code adding a hook method to enable the match of a given pointcut.
Listing 3.13 Wrapper class EasyVariation with inversion of control
1 cclass EasyVar iat ion Impl {
2 cclass EasyVar iat ion wraps NextPiece {
3 void updatePiece ( ) { . . . }
4 void paintBox ( ) { . . . wrappee . drawPiece ( type ) . . . }
5
6 after ( ) : execution (! NextPiece . paint ( ) ) {
7 updatePiece ( ) ;
8 }
9 }
10 }
Although there is no interface on the code snippets of this section, we can easily
define an interface (or an abstract cclass) on top of NextPiece (e.g. INextPiece) and
an abstract cclass on top of the variations. However, as wrapper classes must be virtual,
the design rule (abstract cclass) of the variations must be a collaboration containing a
virtual class specifying the methods that must be present on the variation. Besides that,
as the wrapper relationship is not inheritable nor can be redefined, it is not possible
to specify on this interface that a class must wrap another one (problem P8).
Without this information, developers, which are being guided by the interface, might not
know that variations must wrap a specific class.
3.4 WRAPPERS 34
On the next section we describe the use of Wrapper classes with Aspect Collaboration
Interfaces to implement the di!culty feature.
3.4.2 Wrappers with ACIs
Using ACIs we can specify an interface that groups the specification of the invariant class,
which will be wrapped, and the variation class, the wrapper one, along with other classes
that may be used by our feature. This interface can be partially implemented on multiple
modules, which are then composed with mixins, as described on Section 3.3.2.
Listing 3.14 shows a possible ACI designed for the solution using wrapper classes.
This design rule is very similar to the solution presented on Listing 3.4 of Section 3.3.2,
the only di"erences are that invariant class (NextPiece) does not have the signatures
of updatePiece and paintBox and that variant class NextPieceVariation does not
inherits from the invariant class. In this interface we should be supposed to declare
that NextPieceVariation wraps from NextPiece. However, as wrapper inheritance nor
redefinition is allowed on CaesarJ, its not possible to specify on the ACI that one virtual
class wraps from another one (P8), that is why we put the wraps clause inside comments
on Line 9, meaning that this restriction cannot be enforced by the compiler.
Listing 3.14 NextPieceACI interface for Wrapper classes implementation
1 abstract cclass NextPieceACI {
2 abstract cclass NextPiece {
3 . . .
4 abstract void paint ( ) ;
5 abstract void drawPiece ( int type ) ;
6 . . .
7 }
8
9 abstract cclass NextPieceVar iat ion /!wraps NextPiece!/ {
10 abstract void updatePiece ( ) ;
11 abstract void paintBox ( ) ;
12 }
13 }
The solution using Wrapper classes with ACIs has all the advantages presented on
the solution of Section 3.3.2 (Mixins with ACIs). Considering the disadvantages, this
solution also has all the drawbacks listed on the aforementioned section plus problems
P7, wrappers can not express bi-directional dependency between two roles, and P8, which
may mislead developers that are being guided by the ACI.
Figure 3.6 depicts how the implementation of this ACI looks like. It is very similar
to the one listed on Section 3.8, however, besides inherit from the invariant class, the
3.5 CHAPTER SUMMARY 35
!"#$%&"'"()*'+"$"
!"#$%&"'"!"#$%&"'"()*
!"#$%&"'"+,-&,$&./
Figure 3.6 Diagram of Wrapper implementation using ACIs
variations now wrap it. Moreover, the implementation of the invariant class can be done
using refinement of inheritance, although only refinement is presented in Figure 3.6.
On the next section we summarize all the problems enumerated on this chapter.
3.5 CHAPTER SUMMARY
Table 3.3 summarizes the problems described on this chapter. Lines represent the prob-
lems observed (P1, P2, ..., P8) while columns represent the approaches used on the
implementations (Template Methods without ACIs, Mixin using ACIs, etc.).
We can group the problems described in this chapter on two groups, major problems
(gray lines) and minor problems (white lines). By major problems we mean problems
that harm the modular development of OO and AO code. They are P1, P2, P3 and
P7. As in this work we want to enable this modular development on CaesarJ, it should
be possible to develop classes and aspects in parallel, depending only on a common
interface, and allowing a separated compilation (P3). In order to enable it, we need
an interface which clear states the multiple roles that should be developed separated
(P2). Moreover, in a SPL we have situations where a product di"er from another only
on specific implementations of certain operations of a given class. These operations may
3.5 CHAPTER SUMMARY 36
Table 3.3 Problems Enumerated on this Chapter
Template Method Mixin Composition Wrapper Classes
Problems No ACI ACI No ACI ACI No ACI ACI
P1 O - - - - -
P2 X O X O X O
P3 X X - - - -
P4 - X - X - X
P5 - - X X - O
P6 - - - X - X
P7 - - - - X X
P8 - - - - X X
use or are used by other software operations, which may cause a mutual dependency
situation, like we have on the Tetris SPL example. In this way, this mutual dependency
should be supported (P7).
The minor problems, on the other hand, are P4, P5, P6 and P8. The ACIs demand
the use of virtual classes, which makes the code confuse to understand (P4). Moreover,
when using ACIs, CaesarJ compiler does not verifies if all ACI roles are implemented
(P6). Besides that, the use of mixins to compose partial implementations of an interface,
which enables the separate compilation of this modules, obligates developers to use the
composition mixin instead of instantiating the classes that they implemented (P5).
The template method implementations do not allow separate compilation of roles of a
given interface. Mixin composition, on the other hand, enables this separate compilation,
whereas the use of wrappers introduce problems P7 and P8. Moreover, solution using
wrapper classes with ACI also demands the use mixin composition and does not bring
any benefit not present when using only mixin composition.
Thus, among the discussed approaches, the solution with mixin composition using
ACIs is the one that provides a better modularity support. However, this approach
still has modularity issues, as discussed in Section 3.3.2 and summarized in this section.
On the next chapter we introduce CaesarJ+, an extension to CaesarJ that enables the
specification of design rules which aim to facilitate a more modular development of OO
and AO code, solving the problems mentioned on this chapter.
CHAPTER 4
CAESARJ+: AN EXTENSION TO INCREASE
CAESARJ MODULARITY
Chapter 3 explored multiple ways to implement the di!culty feature of a Tetris game SPL
using CaesarJ. In order to achieve a better modularity support, we have pushed CaesarJ as
far as we could, being necessary even to do an inversion of control in the implementations
using wrappers to enable the mutual dependency of common and variation code (see
Section 3.4).
As mentioned in Section 3.5, the solution using mixin compositions with ACI is the one
that provides better modularity support, allowing the specification of design rules that
have multiple roles and allowing the separate development and compilation of these roles
inside di"erent modules. Thus, these ACIs work as interfaces that specify the minimum
restrictions between these modules. However, this solution has many drawbacks, as
summarized in Section 3.5.
In order to minimize these drawbacks we propose in this work CaesarJ+, an extension
of CaesarJ that aims to increase modularity. This extension defines a set of constructs
on top of CaesarJ, which enable the specification of design rules for OO and AO code,
allowing independent development. Furthermore, the restrictions defined by CaesarJ+
DRs are automatically verified (statically checked). CaesarJ+ constructs syntax is similar
to LSD [43] constructs.
In the following sections we present the new constructs introduced by CaesarJ+.
4.1 DESIGN RULES CONSTRUCT
The design rules expressed using CaesarJ in the last chapter are CaesarJ classes that
contain one or more abstract cclasses (ACIs). As previously mentioned in Section 3.3, it
is possible to partially implement these interfaces in multiple modules and them compose
the implementations using mixin compositions. However, the CaesarJ compiler does
not enforce that all abstract CaesarJ classes of a given collaboration are implemented
(problem P6, see Sections 3.3.2 and 3.5), which can lead to situations where some roles
declared on the ACI are not present in the composed mixin.
37
4.1 DESIGN RULES CONSTRUCT 38
To avoid this problem we need a way to specify roles and restrictions that must be
present on the implementations of the interface. CaesarJ+ introduces the Design Rule
construct, represented by the dr keyword. CaesarJ+ design rules group one or more roles
(cclasses), similar to CaesarJ collaborations. They establish a contract, the roles and
restrictions specified on the DRs are enforced by CaesarJ+, which means that these roles
must have a proper implementation satisfying all the defined restrictions.
Listing 4.1 Simple CaesarJ+ Design Rule example
1 dr SimpleDR [ NextPiece , Canvas ]
2 public abstract cclass NextPiece {
3 int width , he i ght ;
4
5 public abstract void paint ( ) ;
6 public abstract void drawPiece ( ) ;
7 . . .
8 }
9 public abstract cclass Canvas {
10 abstract void s ideBoxes ( ) ;
11 . . .
12 }
13 }
Listing 4.1 shows a simple CaesarJ+ design rule based on the Tetris SPL exam-
ple (Section 3.1). The DR SimpleDR declares two roles, NextPiece and Canvas, each
one defining abstract methods, paint and drawPiece of NextPiece, and sideBoxes of
Canvas. The DR construct is mainly for design purposes, that is the reason that all the
methods on the depicted code are abstract. Nevertheless, as we use CaesarJ classes to
define our DR roles, it is also possible to have attributes and concrete methods declared
inside a DR role. For example, width and height (Line 3) are attributes that can be
used by all operations of NextPiece role. Although not described on the example, a DR
can also have declarations of constants which are global to all roles declared within the
DR, like Java constants.
A role declared inside a DR can reference all the other roles of the same DR. For
example, as described in Section 3.1, the Canvas role methods are responsible for paint-
ing the screen objects. Thus, its implementation needs to call the NextPiece paint
method. This role could also have another method which returns or receives a parameter
of NextPiece type.
As we can see in Line 1 of Listing 4.1, SimpleDR has two parameters, NextPiece
and Canvas. These parameters represent the roles declared within the DR, allowing the
abstraction of real role name by classes responsible for the DR implementation, increasing
the reuse of design rules. Thus, only name of types defined within the DRs can be declared
4.1 DESIGN RULES CONSTRUCT 39
as DR parameters. It is also possible to have roles declared inside a DR which are not
represented in the parameter list. Classes responsible for the implementation of these
kinds of roles need to have the same name as declared on the DR role. More details
about DR implementation are described in Section 4.3.
Listing 4.2 presents the grammar of CaesarJ+ DR construct using the Syntax Defini-
tion Formalism (SDF) [59], which is a meta-syntax to define context-free grammars. The
SDF meta-syntax is adopted in this work because it is used by Stratego/XT, which is the
language used to implement CaesarJ+ compiler. More details about Stratego/XT and
CaesarJ+ compiler are introduced in Chapter 5. Line 6 exports the design rule construct
(DRConstruct, LHS), specifying that it defines a language type (TypeDec, RHS). As de-
fined in Line 7, a design rule is composed by a declaration head (DrDeclarationHead),
which is the keyword dr plus the Id of a given design rule and the list of parameters
(Line 9), and a body (DrBody). A body of a DR (Line 10) is a block that contains mul-
tiple members, which can be constants or classes (Lines 15-16). Classes and constants
declarations are imported from Java grammar (Line 2). Java class declarations are later
modified, inside another SDF module, to include cclass declarations. A SDF parser
generates a tree with the parsed terms (parse tree). It is possible to define a specific rep-
resentation for each term of this parse tree. For example, , DrDec (cons("DRDec"), RHS
of Line 7) is the representation on the tree for a DrConstruct, containing a DrDecHead
(RHS of Line 9) and a DrBody (RHS of Line 10). A complete CaesarJ+ SDF grammar
is depicted in Appendix A.
Listing 4.2 Design Rule construct SDF grammar
1 imports
2 languages / java /JavaMix
3 exports
4 context!free syntax
5 DrConstruct !> TypeDec
6 DrDeclarationHead DrBody !> DrConstruct { cons ( ”DrDec” ) }
7
8 ”dr” Id DrParams !> DrDeclarationHead { cons ( ”DrDecHead” ) }
9 ”{” DrMembersDeclaration ! ”}” !> DrBody { cons ( ”DrBody” )}
10 ” [ ” { Id ” , ”}+ ” ] ” !> DrParams { cons ( ”DrParam” )}
11
12 context!free syntax
13 ConstantDec !> DrMembersDeclaration
14 ClassDec !> DrMembersDeclaration
15
16 l ex ica l syntax
17 ”dr” !> Keyword
4.2 COMPLEMENTS RELATIONSHIP 40
4.2 COMPLEMENTS RELATIONSHIP
In the last chapter we present an example of two mutually dependent roles, next piece
commonalities and variations, that should be separately developed in order to produce a
more modular design. As presented in Listings 3.4 and 3.9, design rules elaborated with
ACI enable this mutual dependency, allowing the separate development of these roles.
However, to enable that both roles access each other methods, it is necessary to duplicate
the abstract signatures of methods that vary inside the class that have the common
methods. This duplication generates a complex specification (P2, Section 3.5) that can
mislead developers that are being guided by these DRs. In other words, these design
rules cannot clearly guide the independent development of the aforementioned roles.
Aiming to have a more accurate DR, we introduce in CaesarJ+ the complements
cclass relationship. The idea of this relationship is to enable the modularization of part
of a role (a specific concern, for example) inside another module, allowing the remaining
operations of this role and the modularized methods to have full visibility of each other.
With the complements, it is now possible to express in a clear way the contents of the
mutually dependent roles, enabling their independent development.
Listing 4.3 Design Rule for the Di!culty feature of Tetris SPL
1 dr NextPieceDR [Common, Var i at i on ] {
2 abstract cclass Common {
3 abstract void paint ( ) ;
4 abstract void drawPiece ( int type ) ;
5 }
6
7 abstract cclass Var iat i on complements Common {
8 abstract void updatePiece ( ) ;
9 abstract void paintBox ( ) ;
10 }
11 }
Listing 4.3 shows a DR in CaesarJ+ similar to the ACI of Listing 3.4. NextPieceDR
uses the complements relationship (see Line 7, complements keyword), Variation is the
complementary role whereas Common is the complemented one. The contents of comple-
mentary roles are only part of the complemented role, which means that classes imple-
menting only complementary roles cannot be instantiated.
The complements construct should be used when we want to modularize parts of a
class. In this way, it is possible to develop on parallel two (or more) parts of the same
class. Then, when we join the implementations of all these parts (the complemented
and the complementary roles) we can instantiate a single module, the one responsible
4.3 DESIGN RULES IMPLEMENTATION 41
for the complemented role. In summary, we have a single module to be used that was
implemented (modularized) on more than one class.
Di"erent from the inheritance relationship, which is unidirectional, complements al-
lows that both complemented and complementary classes completely share its methods
and attributes. In this way, the Variation role (complementary) can access all methods
and attributes of the Common (complemented) role that were defined on the DR, and
vice-versa.
A cclass (role) of a design rule can only complement cclasses declared within the
same DR, otherwise it would not be possible to fully understand a DR looking only at
its code, compromising the comprehensibility (modularity). Moreover, a DR role can
complement one or more roles within the same DR.
The complements relationship is introduced as one more construct for CaesarJ classes.
Similar to a design rule (see Listing 4.2), a cclass is a composition of a head and a body.
Thus, it is necessary to modify only the head of a cclass (ClassDeclarationHead) to
enable the use of the complements construct. As we can see in Lines 3-5 of Listing 4.4, the
complements construct must appear after the declaration of superclasses and before the
implementation of interfaces. The {ClassType "&"}+ expression on the LHS of Line 8
means that we can use the & operator to specify that a given cclass of a DR complements
one or more cclasses.
Listing 4.4 Complements construct SDF grammar
1 context!free syntax
2
3 ( Annotations | Cla s sMod i f i e r s )! ” c c l a s s ”
4 Id TypeParams? SuperClass ? Complements?
5 I n t e r f a c e s ? Wraps? !> ClassDeclarat ionHead { cons ( ”CClassDecHead ” ) }
6
7
8 ”complements ” {ClassType ”&”}+ !> Complements { cons ( ”Complements” ) }
9
10 l ex ica l syntax
11 ”complements ” !> Keyword
4.3 DESIGN RULES IMPLEMENTATION
Sections 4.1 and 4.2 introduce and detail the CaesarJ+ design rules notion and its com-
plements notion. As the DRs are contracts that must be obeyed by modules of a system,
it is necessary to associate this contract with the classes responsible for their roles. In this
way, classes need to specify the design rules that they are implementing. As a CaesarJ+
4.3 DESIGN RULES IMPLEMENTATION 42
DR can have several roles, classes implementing a DR need to define which role they are
providing, in order to establish which are the class responsibilities.
To implement a DR, a cclass uses the implements keyword followed by the name
of the design rule that it is implementing and the name of role that it is responsible for.
For instance, Listing 4.5 shows a toy DR (ExampleDR) with roles A and B, which are im-
plemented by classes ExampleA and ExampleB, respectively. As we can see, ExampleA in-
forms that it implements ExampleDR role A (..implements ExampleDR [A] .., Line 10),
whereas ExampleB specifies that it is responsible for role B (..implements ExampleDR [B]
.., Line 13). In this way, ExampleA must provide the implementation of method x,
whereas ExampleB must provide implementation of y, as we can see in Lines 11 and 14,
respectively.
Listing 4.5 Each class implementing a single DR role
1 dr ExampleDR [A, B] {
2 public abstract cclass A {
3 public abstract void x ( ) ;
4 }
5 public abstract cclass B {
6 public abstract void y ( ) ;
7 }
8 }
9
10 cclass ExampleA implements ExampleDR [A] {
11 public void x ( ) { . . . }
12 }
13 cclass ExampleB implements ExampleDR [B] {
14 public void y ( ) { . . . }
15 }
Due to the use of DR parameters, we have multiple ways to implement a DR and its
roles. For example, a developer responsible for roles A and B can opt to implement them
using a single class. In this way, he has to specify that this class is responsible for these
two roles, as we can see in Listing 4.6 (ExampleAB). Thus, this class has to provide the
restrictions of both roles A and B. This is represented in Lines 2 and 3.
Listing 4.6 A single class implementing more than one DR role
1 cclass ExampleAB implements ExampleDR [A, B] {
2 public void x ( ) { . . . }
3 public void y ( ) { . . . }
4 }
Although not described in the code snippets, the implementation of a complementary
role is similar to the implementation of any other role. The only di"erence is that no
4.4 DESIGN RULES INSTANTIATION 43
objects of this class can be created, only classes implementing complemented or normal
roles can be instantiated, as described in Section 4.2.
The CaesarJ ACIs introduced in Chapter 3 obligate developers to create collaborations
in order to implement these ACI roles, as the roles represented in the ACIs must be
implemented inside virtual classes. As introduced in this section, the CaesarJ+ DRs are
implemented by means of top-level classes. With the use of top-level classes the code
written is more concise, easier to understand. It is not necessary to define a collaboration
and then define a virtual class for each role, as we have in Chapter 3.
The syntax of a design rule implementation is introduced as a modification into the
Java implements construct grammar. As presented in Line 5 of Listing 4.4, cclasses can
implement interfaces (Interfaces?). Thus, it is necessary to specify that a cclass now
can implement both interfaces and design rules, which is depicted in Listing 4.7. As we can
see in Lines 3-4, the implements keyword can be followed by multiple implementations of
interfaces or design rules. Line 6 depicts the implementation of DRs, which is composed
by the design rule name (ClassType) followed by a list of roles which it implements
(DrParams, see Listing 4.2), whereas Line 8 depicts the implementation of a Java interface.
In this way, all the classes responsible for implementing a DR role must use the implements
construct, di"erent from what we have in LSD [43], for example.
Listing 4.7 Design rule implementation SDF grammar
1 context!free syntax
2
3 ” implements ” {( In t e r f a c e s Imp l | DRImpl) ” , ”}+
4 !> I n t e r f a c e s { cons ( ” Implements” ) }
5
6 ClassType DrParams !> DRImpl { cons ( ”ImplDrDec” ) , p r e f e r }
7
8 ClassType !> In t e r f a c e s Imp l { cons ( ” ImplementsDec ” ) }
4.4 DESIGN RULES INSTANTIATION
CaesarJ+ DR constructs introduced in Section 4.1 specify a protocol of interaction be-
tween OO and AO code (CaesarJ classes). These protocols can be exercised by di"erent
classes, on di"erent contexts. Each set of classes implementing a DR in a specific con-
text is independent of the others. On CaesarJ+ we specify this set of classes during
the design rule instantiation. A CaesarJ+ DR designed by the developer works like a
model, as a specific DR is generated for each design rule instance. In summary, a DR
instantiation binds the classes responsible for implementing the design rule roles in a
4.4 DESIGN RULES INSTANTIATION 44
given context, generating a specific DR (interface) for each instantiation. An example of
DR instantiation is shown in Listing 4.8.
Listing 4.8 Example of a DR instance for ExampleDR design rule
dr InstaceExampleAB = ExampleDR [ ExampleA , ExampleB ]
The design rule ExampleDR (Listing 4.5) has two parameters, A and B, so its instance
requires two classes responsible for these parameters (ExampleA and ExampleB, as we
can see in Listing 4.8). In a DR instantiation, classes that implement DR roles must be
informed in the same sequence of the DR parameter list (see Figure 4.1). For example,
as cclass ExampleA is responsible for role A and ExampleB for role B, the instantiation
ExampleDR shown in Listing 4.9 results in an error, as ExampleB does not provide method
x and ExampleA does not provide y.
!"#!"#$%&"$'&"((("$)*"+
####$$%&''"$%"+"(((",####$$%&''"$'"+"(((",""""(((####$$%&''"$)"+"(((",,
!"#!-./01.23"4"!#5%&"5'&"((("5)*
$$%&''#5%"##()*%+)+,-'"!"#$%*"+""""(((,
$$%&''#5'"##()*%+)+,-'"!"#$'*"+""""(((,
$$%&''#5)"##()*%+)+,-'"!"#$)*"+""""(((,
Figure 4.1 The order of classes in a DR instances is the same of the DR parameters
Listing 4.9 Invalid DR instance: ExampleB implements role B, but is positioned in the in-
stantiation as role A implementation. Similar happens to ExampleA.
dr InstaceExampleBA = ExampleDR [ ExampleB , ExampleA ]
Listing 4.10 DR instance using a class which implements more than one role
dr InstaceExampleABAB = ExampleDR [ ExampleAB , ExampleAB ]
DR instantiations in CaesarJ+ are global, like public classes or interfaces declara-
tions. They must specify one class for each parameter of the instantiated DR, even if
4.4 DESIGN RULES INSTANTIATION 45
a given class is responsible for the implementation of more than one role. For exam-
ple, the design rule instance for ExampleDR using cclass ExampleAB (Listing 4.6) which
implements both roles A and B is depicted in Listing 4.10.
Each DR instance is independent of the others. A given DR instance can only han-
dle objects of classes specified within its instance. For example, suppose that method
x from ExampleDR role A receives a parameter of B role type. In that way, if we are
handling instance InstaceExampleAB, the x method can only receive an instance of
ExampleB cclass, because this is the class responsible for this role in this DR instance.
Even if we have another class implementing ExampleDR role B (ExampleB2, for example),
InstanceExampleAB would not be able to handle objects from ExampleB2, because this
class is not a member of this DR instance.
In order to create objects of a class that implements a DR role we first need a design
rule instance. After instantiating a DR we use its instance name followed by the new
keyword and the name of the class specified within the DR instance which we want to
instantiate. References to objects attributes of DR role type also need to be preceded by
the DR instance name. Listing 4.11 shows examples of both references and instantiations
of ExampleDR roles.
Listing 4.11 Instantiation and references of a DR role
1 dr InstaceExampleAB = ExampleDR [ ExampleA , ExampleB ]
2
3 public class Main {
4 private InstaceExampleAB .A aObject ;
5
6 private InstaceExampleAB .B bObject ;
7
8 public stat ic void main ( int [ ] a r gs ) {
9 aObject = InstanceExampleAB .new ExampleA ( ) ;
10
11 bObject = InstanceExampleAB .new ExampleB ( ) ;
12 }
13 }
In Line 1 we have the already mentioned InstaceExampleAB instance of ExampleDR.
Lines 4 and 6 show examples of how to declare variables of ExampleDR role type. Note that
it is necessary to specify the name of DR and the classes which implement the roles before
referencing the role itself (A or B). In Lines 9 and 11 we have the instantiation of classes
ExampleA and ExampleB, which are responsible for the implementation of ExampleDR
roles A and B, respectively.
CaesarJ also has a mechanism for specifying classes used in a collaboration. Regarding
the example of Section 3.3.2, mixin composition is the mechanism that specifies the classes
4.5 ENHANCING EXPRESSIVENESS 46
that implement the ACI roles. For this, it is necessary to define a collaboration mixin
and, for roles that are mutually dependent, it is also needed to define an inner-mixin.
This force developers to instantiate objects of this inner-mixin type, which is not defined
in the ACI (problem P5). In order to replace the implementation of a certain role we need
to create a new collaboration mixin indicating the class which contains the new code.
Considering mutually dependent roles, the instantiation of CaesarJ+ DRs avoids the
specification of the inner-mixin which was necessary in implementations of ACI using
mixin composition. Now, after instantiating a given design rule, we can then instantiate
classes which are responsible for the complemented roles, whereas classes implementing
complementary roles cannot be instantiated.
Listing 4.12 shows the SDF grammar that introduces the design rule instantiation.
First we declare the design rules instantiation (DrInstance) as a type declaration (Line
3). DrInstance is the composition of the dr keyword followed by the name of the instance
(Id), the equals signal, the name of the DR that is being instantiated (DrReference) and
the list of classes which implements the DR roles (DrParams), as depicted in Line 5. Line
7 depicts the DrReference construct, which is a simple Id.
Listing 4.12 Design rule instantiation SDF grammar
1 context!free syntax
2
3 DrInstance !> TypeDec
4
5 ”dr” Id ”=” DrReference DrParams !> DrInstance { cons ( ”DrInstance ” ) }
6
7 Id !> DrReference { cons ( ”DrReference ” ) }
4.5 ENHANCING EXPRESSIVENESS
The CaesarJ interfaces expressed in Chapter 3 using ACIs are useful to specify that rules
must exist and their implementations must provide methods with the same signature as
declared on each DR role. These restrictions are similar to Java interface restrictions.
Thus, the expressiveness of each restriction is low, as each signature restriction is a exact
requisite. For example, we cannot write general rules that are applied for more than one
method pattern, it is necessary to write one restriction for each specific method. So far,
the CaesarJ+ DR constructs introduced also follow the exact requisites principle.
In this way, in order to increase the expressiveness of our DRs, we propose the use of
AspectJ-like wildcards in the definition of DR roles’ method signatures. As DRs are used
to specify restrictions between AO and OO code, method signatures using wildcards can
4.5 ENHANCING EXPRESSIVENESS 47
be restrict enough to guarantee that a given pointcut is going to match. The restrictions
defined using wildcards are evaluated following the minium requisites principle. The use
of wildcards on CaesarJ+ is discussed in 4.5.1.
Moreover, CaesarJ ACIs already define some restrictions over pointcuts, as pointcuts
defined inside ACI inner-classes are inherited by cclasses which implement these roles.
However, it is not possible to define any restriction over advice. Thus, we also introduce
in CaesarJ+ a way to define restrictions over DR roles’ advice. These restrictions are
introduced in Section 4.5.2.
4.5.1 Wildcards
Listing 4.13 shows part of the DisplayExampleDR design rule for the Figure-Display
example, which depicts the use of wildcards in CaesarJ+ role method signatures (Line 4).
As DR are used to specify the minimum requirements between modules in order to enable
their modular development, the evaluation logic of method signatures that use wildcards
searches for at least one method that matches the signature. For example, the cclass
implementing PointRole must have at least one public method whose name starts with
set, returns void and has just one int parameter, such as public void setX(int x).
Listing 4.13 Caesar class example: classic Figure-Display problem
1 dr DisplayExampleDR [ . . . PointRole , LogRole , . . . ] {
2 . . .
3 public abstract cclass PointRole extends FigureElement {
4 public void s e t !( int ) ;
5 }
6
7 public abstract cclass LogRole {
8 pointcut pointChange ( Point p ) : t a r g e t (p) && ( ca l l (void Point . s e t ! ( . . ) ) ;
9 }
10 . . .
11 }
Method signatures of CaesarJ+ roles can have wildcards in cclass modifiers, return
type, method name and parameters type, with the latter option having an usage di"erent
from the other options. Besides the "*" (any) wildcard, parameters can be defined using
AspectJ wildcard "..", which represents any parameters of any type. Table 4.1 depicts
the possible combinations of wildcards when used to represent method parameters.
Also, only the "*" (any) wildcard can also be used to represent a method visibility
modifier or the return type of a method. Moreover, on CaesarJ+ DRs the use of wildcards
on the list of exceptions thrown by a method is not allowed, as we believe that it can
4.5 ENHANCING EXPRESSIVENESS 48
Table 4.1 Use of wildcards in parameters declarations
Parameter declaration Behavior
method(*) One parameter of any type
method(..) Any parameters of any type
method(T,*) Two parameters, one of type T and other of any type
method(T, ..) A parameter of type T plus zero or more of any type
method(T, *, ..) A parameter of T type plus one or more of any type
mislead the developers guided by the DR, which would not be able to identify what
exceptions he must be able to handle or throw when implementing a DR method.
4.5.2 Advice restrictions
When using CaesarJ ACIs, we are able to to specify that an implementation of a virtual
class (ACI role) must have some specific methods and pointcuts (if we declare abstract
pointcuts, for example). However, it is not possible to impose any restrictions over advice.
What we are to do is write an advice directly into a DR role, with the execution code
(behavior) inside it, but it is not possible to specify that classes implementing this role
should also provide a certain advice that uses (or not) a certain pointcut.
In this way, we introduce in CaesarJ+ the possibility to impose restrictions over advice
on DR roles. Listing 4.14 shows an extension of LogRole (Listing 4.13) which specifies
that an after advice, using at least pointChange pointcut, must be present on LogRole
implementation, as we can see in Line 4.
Listing 4.14 Caesar class example: classic Figure-Display problem
1 public abstract cclass LogRole {
2 pointcut pointChange ( Point p ) : t a r g e t (p ) && ( ca l l (void Point . s e t ! ( . . ) ) ;
3
4 after ( Point p , . . ) : pointChange (p) . . ;
5 }
Looking carefully to the declared advice, we can see three di"erences comparing to a
normal AspectJ/CaesarJ pointcut : (1) it uses a wildcard (“..”) at the variable bindings,
(2) it has a wildcard after the specification of the pointcut (“..”), and (3) it does not
have a body, as this rule is only for design purpose. Regarding (1), it is possible to use
the parameter wildcards detailed in Table 4.1 within the advice parameter bindings. For
4.6 CHAPTER SUMMARY 49
example, if we use the "*" wildcard instead of ".." (resulting in after(Point p, *))
we need an advice which binds exactly two parameters, with the first one of Point type,
in order to match the advice restriction. Considering (2), the ".." wildcard indicates
that the pointcut which is being used by the advice can be complemented. The eval-
uation logic for advice restriction also follows the minimum requisites principle, which
means that any after advice that exposes at least a parameter of Point type and uses at
least the pointChange pointcut (receiving the exposed parameter of Point type) matches
the rule of Line 4 (Listing 4.14). For example, an implementation of LogRole declaring
the advice after(Point p): pointChange(p) && anotherPointcut() { .. } cor-
rectly matches the advice restriction rule.
We can also write advice restrictions without specifying any pointcut, with the use
of wildcards. For example, before(..): *; indicates that a before advice using any
pointcut and exposing any parameter must be present on the cclass which implements
LogRole.
4.6 CHAPTER SUMMARY
In this chapter we have introduced CaesarJ+, a language for increasing modularity of
CaesarJ, and discussed its constructs. The purpose of CaesarJ+ is to provide support
for modular development of OO and AO code. The DR construct introduced guide
programmers on the development of OO and AO code, helping them to identify what
they should be able to do or not. CaesarJ+ DRs enable the definition of restrictions more
expressive than the ones defined by using only CaesarJ ACIs.
Our language, however, does not verify if changes on role implementations break the
intents of an aspect. We believe that our design rules provide the necessary information
to help developers make their own decisions. For example, if one is implementing a DR
role A that specifies the pointcut execM: execution(* A.m*(..)), this developer must
realize that all methods whose name starts with m are subject to being intercepted by
an aspect. Thus, if he writes a method m2() or modifies a method name from m1() to
n1(), it should be a conscious decision, as he explicitly declares that he is following the
rules established on the DR role A. So, prior to making these changes, he must be aware
of the rules established on the DR.
Also, the restrictions enforced by our language are based on the syntax of the program.
We can define only structural restrictions now, but we do plan to enable the specification
of behavioral rules (see Section 7.2), like LSD [43] behavioral rules, which define what
4.6 CHAPTER SUMMARY 50
must occur inside a specific scope (method call, attribute set, etc.). Semantic restrictions
such as the definition of what is a specific concern (for example, what the GUI concern
comprises), which demand the specification of a formal model of the system, are beyond
the scope of this work.
In the next chapter we introduce the transformations necessary to translate CaesarJ+
constructs into CaesarJ code. We also discuss the implementation of CaesarJ+ compiler.
CHAPTER 5
IMPLEMENTATION DETAILS
In order to evaluate the language constructs introduced in Chapter 4 we have developed a
CaesarJ+ compiler. The actual version is a prototype that verifies, validates, and trans-
forms CaesarJ+ constructs into valid CaesarJ code, which is then ready to be compiled
by CaesarJ original compiler.
In this chapter we detail how the CaesarJ+ compiler works, introducing the transfor-
mations to CaesarJ in Section 5.1. Moreover, in Section 5.2 we discuss the implementation
of such transformations, which is developed using the Stratego/XT [55] language for pro-
gram transformations. In the end of this section we discuss the actual limitations of our
compiler.
5.1 TRANSFORMATIONS
After concluding the specification of our constructs, we started to analyze how to intro-
duce them into CaesarJ. Three options were available, (1) build a new compiler from the
scratch, (2) modify the CaesarJ compiler, introducing the proposed constructs, and (3)
build a pre-compiler which handles the proposed constructs and transforms them into
valid CaesarJ code.
Building a new compiler for the scratch for both CaesarJ and CaesarJ+ would require
plenty of time and compiler knowledge. As we had limited time and were not experts on
compilers, the first option was discarded. Regarding (2), by introducing our constructs
into the existing CaesarJ compiler, our modifications would be highly coupled with the
actual implementation. Thus, any new release of the compiler could break all of our
modifications. Analyzing the third option, we have that CaesarJ is able to express our
restrictions, although it requires complex specifications and cannot statically check most
of them. In this way, we decided to develop a CaesarJ+ compiler which verifies the
proposed CaesarJ+ constructs, statically checks the restrictions, and then transforms the
CaesarJ+ code into valid CaesarJ code.
Next we describe through examples how each CaesarJ+ construct is transformed into
CaesarJ code.
51
5.1 TRANSFORMATIONS 52
5.1.1 Design Rules
As CaesarJ does not support the design rule (dr) construct, it is necessary to transform
a design rule into a CaesarJ class. A naive way to make this transformation is to convert
a design rule directly into a collaboration, as presented in Listing 5.1.
Listing 5.1 Generated CaesarJ ACI for ExampleDR (Listing 4.5)
1 public abstract cclass ExampleDR {
2 public abstract cclass A {
3 public abstract void x ( ) ;
4 }
5
6 public abstract cclass B {
7 public abstract void y ( ) ;
8 }
9 }
As we can see, the generated code for the design rule of Listing 4.5 is a simple ACI,
with one virtual class for each role defined within the DR. Moreover, the parameters of the
DR were discarded, there is no sign of them in the depicted code. Hence, all classes which
declare to implement this ACI can collaborate with each other. However, as specified on
last the last chapter, our idea with CaesarJ+ is to have a restrict collaboration, allowing
only classes specified within a given context to collaborate with each other. Thus, only
this transformation of Listing 5.1 is not enough.
!!"#!$%&'("#)*+',-."
/"+"$)01!"#!$%'2134$!+#56$7!8)6+
1!"#!$%'213
1!"#!$%'213
1!"#!$%'2134$!+#56$7!8)6+56$'"!09'(,'3+#8!+0"
!"#$%&'(%)*&
+(*&(,-.#)/0123('2/%#1,/)*&&#/4#!*&25%#"63*&
Figure 5.1 Overview of Design Rules compilation process
As stated in Section 4.4, CaesarJ+ design rules generates one specific design rule for
each DR instance. Thus, initially each CaesarJ+ DR is transformed into a generic ACI,
5.1 TRANSFORMATIONS 53
exactly as described in Listing 5.1. Moreover, this generic ACI is transformed for each
DR instance, which specifies all the classes that implement the DR roles, generating a
specific DR for each instance. Figure 5.1 describes this process.
This first part of the DR transformation, which generates the generic ACI, is respon-
sible for dealing with the complements construct. The transformations related to the
complements are detailed in Section 5.1.2. Next, the compiler analyzes the classes of the
system, looking for classes which declare to implement a DR, and verifies if these class
obey the DR restrictions. The transformations of the DR implementations are explained
in Section 5.1.3. After this, the compiler analyzes the DR instantiations, verifying if
the informed classes really implement the correspondent roles. Each DR instantiation
generates a specific ACI (highlighted in gray, Figure 5.1). These specific ACIs have the
same body of the generic one, di"ering only in the name, which is based on the following
rule: DR name plus the names of the classes which implement each DR role, separated
by underscores. For example, the ACI generated for the DR instance of Listing 4.8 is
named as ExampleDR ExampleA ExampleB. More details about the transformations of a
DR instance are detailed in Section 5.1.4.
5.1.2 Complements
As stated in Section 4.2, our objective with this construct is to enable the modularization
of part of a role (class, for example) on more than one module, enabling the parallel
development of this role. Thus, it is necessary that all these separated parts of this role
have access to each other operations.
We have identified two possible approaches for the complements transformation. The
first approach transforms the complements relationship into an inheritance relationship,
and then copies the signatures of the operations declared within the complementary
cclasses into the complemented cclass, similar to described in Section 3.3.2. The
second approach unifies the complemented and all of its complementary roles in a single
module, with the same name of the complemented role, copying all the attributes and op-
erations of all these complementary roles into this newly created module. This approach
results in a single cclass for each complemented role that contains all the operations
declared within the complementary roles. Both approaches have its advantages and dis-
advantages. The first approach restricts the visibility of the complemented roles, as they
can access only the operations of the complementary roles, not the attributes, whereas
complementary roles can access complemented roles methods and attributes. This occurs
5.1 TRANSFORMATIONS 54
due to the use of the inheritance relationship. Also, it is necessary to make a slightly
modifications on pointcuts referencing the complemented role, as now this role has, be-
sides its original methods, the method signatures copied from the complementary roles.
The second approach, on the other hand, does not limit the roles visibility, as the roles
are now unified in a single module. However, as it eliminates all the complementary roles
from the interface, we have that all the references to the complementary types must be
modified to point now for the created role. Thus, it is also necessary to modify pointcuts
which used to reference the complementary roles.
We believe that the first approach is more intuitive, as it maintains all the virtual
classes specified within the design rule, resulting in a DR more consistent with the estab-
lished specifications. In this way, we have decided to use this approach on the comple-
ments transformations. However, we plan to do a more detailed analysis of this second
transformation approach as a future work (see Section 7.2).
In this way, we transform the CaesarJ+ complements construct into CaesarJ code
by (1) transforming the complements relationship in the complementary cclass into an
inheritance relationship, and (2) copying the signatures of the operations declared within
the complementary cclass into the complemented cclass.
Listing 5.2 Generic ACI after the transformation of the complements construct
1 public abstract cclass NextPieceDR {
2 abstract cclass Common {
3 abstract void paint ( ) ;
4 abstract void drawPiece ( int type ) ;
5
6 abstract void updatePiece ( ) ;
7 abstract void paintBox ( ) ;
8 }
9
10 abstract cclass Var iat i on extends Common {
11 abstract void updatePiece ( ) ;
12 abstract void paintBox ( ) ;
13 }
14 }
Listing 5.2 shows the generic ACI generated after the transformation of NextPieceDR
(see Listing 4.3). In Line 10 we have the declaration of the virtual class Variation,
which inherits from Common. In the original design rule, Variation is a complementary
cclass, which complements Common. Lines 6-7 depict the signatures of updatePiece
and paintBox, which are methods from the complementary class (Variation) that were
copied inside the complemented class in order to enable Common original methods (paint,
drawPiece) to access them, as this is assured by the complements construct semantics
5.1 TRANSFORMATIONS 55
(Section 4.2). It is important to remember that developers write CaesarJ+ design rules,
which are clear, easy to understand and checked by the compiler. They should not have
access to this generated code, which is confusing and hard to understand, like the ACI
presented in Listing 3.4.
In order to maintain consistency it is necessary to adapt a few pointcuts of the generic
ACI during the transformation of the complements. Pointcuts which use wildcards to
reference methods of the complemented classes must be modified to avoid matching the
introduced complementary methods. For example, the pointcut call(* Common.*(..))
is transformed to call(* Common.*(..)) && ( !call(* Common.updatePiece() ) &&
!call(* Common.paintBox()) ), avoiding that the original pointcut, which was de-
signed considering the original design rule, matches methods that it is not supposed
to match. Table 5.1 lists which pointcuts need to be transformed in order to maintain
the DR consistency.
For all the call/execution pointcuts depicted in the table, the modifications are
similar to the call(* Common.*(..)) example. The within pointcut needs a di"erent
modification, it is necessary to add a !withincode into the pointcut in order to avoid
matching of the introduced methods. For example, whithin(Common) is transformed to
whithin(Common) && !withincode(updatePiece()) && !withincode(updatePiece()).
In order to avoid the generation of cotraditory pointcuts (such as call(A) && !call(A))
we still need to do a more detailed analysis of this pointcut transformation process, using
more complex examples.
Table 5.1 Pointcuts which need to be updated
Pointcut Wildcard on Note
call/execution(ReturnType Class.*(..)) methodName Class is a complemented role
call/execution(* Class.methodName(..)) ReturnType Class is a complemented role
call/execution(ReturnType Class.methodName(*)) args type Class is a complemented role
call/execution(ReturnType Class*.methodName(..)) Class name Class* matches a complemented role
within(Class) - Class is a complemented role
within(Class*) Class name Class* matches a complemented role
If the second transformation approach for the complements was used, instead of having
both Common and Variation cclasses in Listing 5.2, we would have only the Common
virtual class containing the signature of the four methods. Thus, all references to the
Variation virtual class must be updated, pointing now to the Common role. A more
detailed analysis of this second approach, comparing the advantages and disadvantages
of it with the used transformation approach, can be done as a future work.
5.1 TRANSFORMATIONS 56
5.1.3 Implementation
As design rules are transformed into collaborations, it is necessary to implement its
roles (inner CaesarJ classes) inside virtual classes (as explained in Section 2.3). Though,
as introduced in Section 4.3, the implementations of design rules occur inside top-level
classes. Hence, it is necessary to transform these DR implementations into virtual-classes.
In this way, CaesarJ+ compiler analyzes the top-level classes that implement the DR,
verifying if they provide the implementations of the roles which they are responsible
for, and them transform these top-level classes into CaesarJ code. Listing 5.3 presents
ExampleA, a CaesarJ+ implementation of ExampleDR (Listing 4.5) role A, whereas List-
ing 5.4 shows how ExampleA looks after the transformation to CaesarJ code.
Listing 5.3 ExampleA before transformation
cclass ExampleA implements ExampleDR [A] {
public void x ( ) { . . . }
}
Listing 5.4 Generated code for ExampleA
cclass ExampleA Cjp extends ExampleDR {
cclass ExampleA extends A {
public void x ( ) { . . . }
}
}
This transformation process occurs as follows:
1. Generation of collaboration cclass: CaesarJ+ compiler generates a collabo-
ration cclass on top of the original cclass and uses the following rule to name
it: OriginalClassName plus the su!x Cjp. For example, in Listing 5.3 we have
ExampleA as a top-level cclass, and Listing 5.4 has the collaboration ExampleA Cjp
on top of ExampleA.
2. Inheritance organization: First, CaesarJ+ defines that the generated collabora-
tion inherits from the generic ACI originated after the transformation of the DR. For
example, ExampleA design rule is transformed into ExampleA generic ACI (described
in Section 5.1.1, Listing 5.1). This way, the compiler defines that ExampleA Cjp
inherits from ExampleA ACI (Line 1 of Listing 5.4). Thus, the compiler verifies if
the virtual class obeys all the restrictions specified on the ACI role. This estab-
lishes that the ExampleA Cjp is following the generic ACI, which means that any
virtual class of ExampleA Cjp can reference and use the roles (virtual classes) of the
generic ACI. After this, CaesarJ+ compiler declares that the virtual class inherits
from the roles that the top-level class declared to implement. In our example, as
the top-level class ExampleA was responsible for ExampleDR role A, the virtual class
ExampleA has to inherit from A after the transformation, as we can see in Line 2 of
5.1 TRANSFORMATIONS 57
Listing 5.3. It makes the ExampleA virtual class responsible for the implementation
of the generic ACI virtual class A.
3. References update: CaesarJ+ compiler looks in the source code for references
to the top-level classes that were transformed. That way, all return types, vari-
able declarations and other references that points to the old top-level classes are
then updated to point to the virtual class of the new collaboration. Following
our example, all references on the code to the ExampleA cclass are updated to
ExampleA Cjp.ExampleA. Moreover, DR instances are also updated, replacing the
name of the original class for it new name with the Cjp su!x.
Other cclasses relationships, like interface implementation and class wrapping, can
still be used in cclasses that implement DR roles. However, after the compilation pro-
cess, these relationships are moved to the virtual class, as this is the class that originally
contains the code written by developers.
5.1.4 Instantiation
Design rules instances in CaesarJ+ are responsible for binding a set of classes that declare
to implement a DR in a specific context. Thus, a specific interface is generated for each
DR instance, restricting that only cclasses informed in a given instance can collaborate
with each other, as explained in Section 4.4. As the dr construct is not supported by
CaesarJ, it is necessary to transform it using an existing CaesarJ construct.
As mentioned in Section 4.4, mixin composition is the mechanism used in CaesarJ to
bind the implementations of a collaboration. Therefore, CaesarJ+ compiler transforms a
design rule instance into a mixin composition. As introduced in Section 5.1.1, design rules
are first transformed into generic ACIs, which then generate a specific ACI for each DR
instance. The transformation process of CaesarJ+ design rules instances into CaesarJ
code occurs as follows:
1. Generation of specific ACI: CaesarJ+ compiler analyzes the DR instance and
verifies if the informed classes are responsible for the correspondent DR roles. Next,
it uses the generic ACI as a base for the creation of the specific ACI, which has the
same content of the generic one, but with a di"erent name. The compiler uses the
following rule to name the specific ACI: generic ACI name (which is the same name
of the original DR) plus the names of the classes which implement each DR role,
separated by underscores. It is important to note that two di"erent DR instances
specifying the same classes as DR parameters generate di"erent specific ACIs.
5.1 TRANSFORMATIONS 58
2. Inheritance update: In this compilation stage, CaesarJ+ compiler updates the
superclasses of each cclass informed on the DR instance parameters list. Here the
collaborations created in Section 5.1.3 (with the Cjp su!x) are updated, now they
inherit from the specific ACI instead of the generic ACI.
3. Mixin creation: In this step the compiler generates a new mixin collaboration,
which inherits from all the classes specified on the DR instance parameter list.
This generated mixin receives the same name informed at the DR instance. Also,
this mixin defines a static getInstance method, which returns the instance of
the mixin. Moreover, a new inner-mixin is created for each group of complement-
ed/complementary cclasses. This inner-mixin refines the complemented cclass,
stating that this cclass is now concrete and inherits from all the classes which
complemented it.
4. Update of references: CaesarJ+ compiler analyzes the source code, updating
the references of a given DR instance to the newly created mixin. That way,
there is a modification in the instantiation of DR roles. Now these instantiations
call the introduced static getInstance method. For example, the construction
DesignRuleInstace.new ClassImplementRole is updated to DesignRuleInstace.
getInstance().new ClassImplementRole.
Listing 5.5 presents examples of CaesarJ+ DR instance (NextPieceInstance in-
stance, Line 1), reference to a DR role type (Common, Line 4) and instantiation of a
DR role (Line 8). Listing 5.6 shows the generated CaesarJ code after the transforma-
tions. Note that, although not depicted in this listing, the first part of the DR instances
transformations (Generation of specific ACI ) generates the specific ACI for this instance,
while both classes specified as parameters are updated to inherit from this specific ACI
(second part of transformation, Inheritance update).
Listing 5.5 CaesarJ+ DR instance and references before transformation
1 dr NextPieceInstance = NextPieceDR [ NextPieceBase , EasyVar iat ion ]
2
3 public class Main {
4 NextPieceIns tance .Common common ;
5
6 public stat ic void main ( int [ ] a r gs ) {
7 . . .
8 common = NextPieceInstance .new NextPieceBase ( ) ;
9 }
10 }
5.2 COMPILER IMPLEMENTATION 59
The third part of the DR instance transformation process (Mixin creation) orig-
inates NextPieceInstance mixin, which inherits from both NextPieceBase Cjp and
EasyVariation Cjp (Lines 1-11, Listing 5.6). NextPieceInstance also defines the inner-
mixin NextPieceBase (Lines 10-11), which refines the original virtual class declaring that
it is now concrete and inherits from EasyVariation. This inner-mixin is necessary in or-
der to enable the instantiation of the complemented class NextPieceBase. Besides that,
the static method getInstance (Lines 4-8) and the static field with the same name of
the mixin cclass (nextPieceInstance in our example, Line 2) are also created.
Listing 5.6 Generated CaesarJ code for DR instance
1 public cclass NextPieceIns tance extends NextPieceBase Cjp & EasyVar iat ion Cjp {
2 private stat ic NextPieceIns tance nextP i ece Ins tance ;
3
4 public stat ic NextPieceInstance ge t In s tance ( ) {
5 i f ( nextP i ece Ins tance == null )
6 nextP i ece Ins tance = new NextPieceInstance ( ) ;
7 return nextP i ece Ins tance ;
8 }
9
10 public cclass NextPieceBase extends EasyVar iat ion { }
11 }
12
13 public class Main {
14 NextPieceDR NextPieceBase EasyVariation .Common common ;
15
16 public stat ic void main ( int [ ] a r gs ) {
17 . . .
18 common = NextPieceInstance . g e t In s tance ( ) .new NextPieceBase ( ) ;
19 }
20 }
The last part of the DR instance transformation (Update of references) is responsible
for updating the references to the DR instance on the source code. Thus, references
to instances of DR roles are updated, replacing NextPieceInstance.new.. (Line 8 of
Listing 5.5) for NextPieceInstance.getInstance().new ..., as we can see in Line 18
of Listing 5.6.
5.2 COMPILER IMPLEMENTATION
CaesarJ+ compiler is responsible for checking the restrictions of the introduced constructs
and for transforming CaesarJ+ code into valid CaesarJ code, which can be later compiler
by CaesarJ compiler. We have implemented a prototype of this compiler, using the
Stratego/XT language and toolkit for program transformations.
5.2 COMPILER IMPLEMENTATION 60
In this section we describe the implementation of CaesarJ+ compiler. We start by in-
troducing Stratego/XT in Section 5.2.1, whereas Section 5.2.2 depicts the implementation
of the compiler. The complete code of CaesarJ+ compiler can be dowloaded at [48].
5.2.1 Stratego/XT
According to [8] and [55], Stratego/XT combines Stratego, a small and e!cient domain-
specific language for implementing transformations based on the paradigm of programmable
rewriting strategies, with XT, a collection of reusable components and tools for the devel-
opment of transformation systems, such as powerful parser and pretty-printer generators
and grammar engineering tools.
Figure 5.2 Overview of Stratego/XT transformation process [9].
Stratego/XT supports the development of program transformation infrastructure,
domain-specific languages, compilers, program generators, and a wide range of meta-
programming tasks. It represents programs by means of terms, which are essentially
trees. Stratego/XT parses the original program into a tree of specific terms, which are
then manipulated (transformed) and then parsed to the output language, as depicted in
Figure 5.2.
Stratego language constructs rules and strategies are used to specify the trans-
formations. The rules are responsible for transforming a given term into another term.
These rules are executed only when specific conditions (restrictions), which are expressed
5.2 COMPILER IMPLEMENTATION 61
within strategies, are valid (do not fail).
Before starting the transformations, it is necessary to parse the input program into a
tree of terms. Stratego/XT parser uses a table of symbols that is generated by the XT
tools using the language definition specified in the SDF grammar. It is also necessary to
define the pretty-printer for the output language, which is responsible for converting the
tree of transformed terms into the output code.
Next section depicts the main steps of CaesarJ+ compiler.
5.2.2 CaesarJ+ Compiler
CaesarJ+ compiler is a Stratego/XT program which receives CaesarJ+ code, analyzes
it, verifies its constructs and then transforms the input code, generating CaesarJ valid
code. CaesarJ+ is a superset of CaesarJ, containing all of its constructs plus the ones
introduced in Chapter 4.
The compilation process starts by constructing the tree of terms after parsing the
input CaesarJ+ program. After this, the main function starts the transformations by
applying the ManipulateCompilationUnit transformation rule (see Listing 5.7) to the
tree of terms. A Stratego rule is composed of a LHS representing the expected term
to be transformed (Line 3) and a RHS which is the result of the transformation. The
transformation itself is composed by the application of other rules and strategies, which
are depicted after the where construct. It only occurs if the rules and expressions of the
where clause do not fail.
Listing 5.7 Main transformation rule of CaesarJ+ compiler
1 rules
2 ManipulateCompilationUnit :
3 CompilationUnit ( packageDec , importDec , typeDec )
4 !>
5 CompilationUnit ( packageDec , importDec , typeDecMod )
6 where
7 // F i l t e r i n g the Design!Rules and Non Design!Rules de c l a ra t i on s
8 drDec := < f i l t e r (HasDr)> typeDec ;
9 nonDrDec := < f i l t e r (not (HasDr))> typeDec ;
10 //Manipulation of Design Rules
11 <map(ManipDrDec)> drDec => drDecMod ;
12 //Compiling the c c l a s s e s t ha t implement DRs, updat ing r e f e r enc e s
13 <handleNonDrDec ( | drDecMod , drDec)> nonDrDec ;
14 //Handling Design Rule i n s t an t i a t i o n
15 hand l eDr Ins tan t i a t i on ( | drDecMod) ;
16 //El iminat ing the Design!Rule con s t ruc t s
17 removeComplementsFromSignatures => typeDecMod ;
5.2 COMPILER IMPLEMENTATION 62
As depicted above, ManipulateCompilationUnit receives a CompilationUnit term
(Line 3), which is the main node of the tree terms generated after parsing a Java-like (Cae-
sarJ+) file, and transforms its type declarations (design rules, classes, cclasses, etc.),
replacing typeDec for typeDecMod (Line 5). Lines 7-17 depicts the strategies which
are applied in order to enable this transformation and generate the modified declarations.
Three main steps are executed during this transformation process of the declarations,
which are:
1. Manipulation of Design Rules: This step is responsible for handling the design
rules declared on CaesarJ+’s code. It starts with the application of ManipDrDec
rule to each DR identified in the source code (Line 11). Also, during this activity the
complements construct is transformed into an inheritance relationship, as described
in Section 5.1.2.
2. Compilation of DR implementations: This transformation phase is responsible
for checking all the cclasses that declare to implement design rules, verifying
if they provide the necessary implementations for each DR role. It starts with
the application of handleNonDrDec strategy, which receives two parameters, the
recent modified DR declaration list and the initial DR declaration list, to the list of
declarations which are not DRs (see Line 13). Also, this step transforms the classes
which implement the DR, creating the collaboration, updating the inheritances, and
updating the references to these classes in the rest of the source code, as described
in Section 5.1.3.
3. Manipulation of DR instances: This step is responsible for handling the DR
instances. It starts with the application of the handleDrInstantiation strategy,
which receives the modified DR declaration list as a parameter, to the tree originated
from step 2 (Line 15). During this step the compiler verifies if the DR instances
provide the correct classes for each DR parameter, creates a mixin for each DR
instance, and updates the references to a DR instance, pointing to this newly created
mixin, as described in Section 5.1.4.
After these three steps we have a modified version of the declarations tree, with the
CaesarJ+ constructs transformed into CaesarJ valid code. However, it is still necessary to
remove the complements construct, which is still present on the specific ACI declarations.
This removal occurs by calling the strategy removeComplementsFromSignatures (see
Line 17 of Listing 5.7).
Next we detail the implementation of each of the three steps introduced above.
5.2 COMPILER IMPLEMENTATION 63
5.2.2.1 Manipulation of Design Rules
The manipulation of CaesarJ+ design rules is composed of two specific activities, trans-
formation of the complements construct into an inheritance relationship, and duplication
of complementary cclasses method signatures into the complemented cclasses. List-
ing 5.8 shows ManipDrDec, the Stratego/XT rule responsible for this transformation step.
Listing 5.8 Manipulation of Design Rules
1 rules
2
3 ManipDrDec :
4 DrDec (DrDecHead ( drId , params ) ,DrBody(members ) )
5 !>
6 DrDec (DrDecHead ( drId , params ) ,DrBody(membersMod) )
7 where
8 <copyComplementsToExtends>members ;
9 membersMod := <complementDrClassesSignatures> ;
As we can see, ManipDrDec modifies the members declared inside the DR body (Lines
4-6), which are declarations of DR roles. Strategy copyComplementsToExtends (Line 8) is
responsible for transforming the complements construct into an inheritance relationship.
However, the complements construct are not yet removed, they are also used during
the manipulation of DR instances. Then, complementDrClassesSignatures strategy is
applied over the resulting term, copying method signatures of complementary roles to the
complemented roles. After this step, the design rules are ready to be transformed into
generic ACIs.
5.2.2.2 Compilation of DR implementations
The compilation of cclasses which implements CaesarJ+ design rules is composed by
three activities: verification of the provided methods, compilation of cclasses and up-
date of references. Listing 5.9 presents handleNonDrDec, the strategy responsible for this
second step of our transformation process. The list of DR declarations is provided as a
parameter for this strategy (initialDrDecList).
This step starts by obtaining the list of cclasses which implement design rules. This
is done by the strategy getCClassImplementsDr (see Line 5), which applies some list
filters to retrieve these cclasses. In Line 6 we have verifyClassesImplementations,
strategy responsible for verifying if the cclasses provide all the implementations of the
DR roles that they declare to implement. This strategy is applied over the term resultant
of getCClassImplementsDr and uses the list of DR declarations as a parameter.
5.2 COMPILER IMPLEMENTATION 64
Listing 5.9 Compilation of DR implementations
1 strategies
2
3 handleNonDrDec ( | i n i t i a lD rDe cL i s t ) =
4 ? al lSystemDec ;
5 getCClassImplementsDr => cc lasses ImplementDr ;
6 ver i f yC las s es Impl ementa t i on s ( | i n i t i a lD rDe cL i s t ) ;
7 <compileDrRelatedCClasses> cc lasses ImplementDr => compi l edCc las s es ;
8 l i s tCc las sUpdated := <getListCclassUpdated ( | [ ] ) > compi l edCc las s es ;
9 <mergeClasses ( | compi ledCclasses , l i s tCc l as sUpdated )> al lSystemDec ;
10 updateReferencesCompi ledCClasses ( | l i s tCc l as sUpdated )
The compilation of cclasses, which is responsible for creating the collaboration and
updating the inheritances of the cclasses, is done inside compileDrRelatedCClasses
(Line 7). Strategy getListCclassUpdated generates a list of pairs, with the old cclasses
name and their new name after the compilation, whereas mergeClasses (Line 9) merges
this list of compiled cclasses with the other cclasses of the system. In Line 10 we have
updateReferencesCompiledCClasses, strategy which is responsible for the last activity
of this step, the actualization of references to the compiled cclasses.
After this second step, all the cclasses which implement design rules are now col-
laborations, and references to this classes have been updated, pointing now to the virtual
classes of the created collaborations.
5.2.2.3 Manipulation of DR instances
Four activities compose the manipulation of DR instances transformation step: verifi-
cation of DR instances, generation of specific interfaces, generation of mixins and actu-
alization of DR instance references. Listing 5.10 depicts handleDrInstantiation, the
strategy responsible for this transformation step. It starts by separating the declarations
of DR instances from the other declarations of the program (Lines 5-6).
Strategy verifyClassesInstantiation (Line 7) verifies if cclasses specified at the
DR instances implement the correct parameters of the DR that is being instantiated.
The strategy genInterfacesAndInstanceListParam (Lines 9-11) is responsible for
generating the specific ACIs for each DR instance. We use the hashGenInterfaceIds
hashtable to avoid the generation of two specific ACIs with the same name, as it could
occur if we have more than one instantiation of the same DR using the same classes as pa-
rameters (see Section 5.1.4). Strategy genInterfacesAndInstanceListParam generates
a tuple composed by (1) a list with the generated specific ACIs, and (2) a list of pairs of
the form (class, List-Of-Interfaces-To-Implements) for all classes declared within
5.2 COMPILER IMPLEMENTATION 65
an DR instance. In this way, updateReferences (Lines 12-14) uses this list of pairs to
update the inheritances of each class that implements a DR role, replacing the inheritance
of the generic ACI for the newly created specific ACI.
Listing 5.10 Manipulation of DR instances
1 strategies
2
3 hand l eDr Ins tan t i a t i on ( | l i s tDrDec ) =
4 ? al lSystemDec ;
5 < f i l t e r (? DrInstance ( , , ))> al lSystemDec => l i s tD r I n s t a n c e s ;
6 < f i l t e r (not (? DrInstance ( , , )))> al lSystemDec => l i s tNo tDr In s tance s ;
7 <v e r i f yC l a s s e s I n s t a n t i a t i o n ( | l i s tDrDec , l i s tNo tDr In s tance s)> l i s tD r I n s t a n c e ;
8 new!hashtab l e => hashGenInter f ace Ids ;
9 ( i n t e r f a c e L i s t , l i s tDrInstancesAndParams) :=
10 <genInter facesAndInstanceListParam ( | l i s tDrDec ,
11 hashGenInter face Ids , [ ] , [ ] )> l i s tD r I n s t a n c e s ;
12 newSystemDec :=
13 <updateReferences ( | l i s tDrDec ,
14 l i s tDrInstancesAndParams)> l i s tNo tDr In s tance s ;
15 generatedMixins :=
16 <generateMixinsFromInstances ( | [ ] , l i s tNotDr Ins tance s ,
17 l i s tDrDec)> l i s tD r I n s t a n c e s ;
18 <concat> [ i n t e r f a c eL i s t , newSystemDec , generatedMixins ]
Strategy generateMixinsFromInstances (Lines 15-17) is responsible for generating
the mixins for each DR instance, as introduced in Section 5.1.4. Here it is necessary to
analyze which classes are complemented (by analyzing the complements construct which
is still present), in order to create the inner-mixins for the complemented classes (see
Section 5.1.4).
The last activity of this step, actualization of DR instances references, is not yet
implemented. More details about the actual limitations of CaesarJ+ compiler are detailed
in Section 5.2.3. Finally, in Line 18 we have the concatenation of the generated interfaces,
the updated system declarations and the newly generated mixins, which compose our
transformed CaesarJ program.
After this step we have transformed almost all CaesarJ+ construct of the input pro-
gram into CaesarJ code. However, it is still necessary to remove the complements con-
struct from the generated specific ACIs, which are still present in the tree of terms.
Strategy removeComplementsFromSignatures, depicted in Line 19 of Listing 5.7, is re-
sponsible for removing this constructor.
5.2 COMPILER IMPLEMENTATION 66
5.2.3 Compiler Limitations
CaesarJ+ compiler prototype was developed in order to evaluate the constructs proposed
in this work. In this way, some functionalities were not implemented, while some of the
implemented functionalities have restrictions. In this section we discuss the limitations
of the actual implementation.
Regarding the whole compilation process, our compiler can handle only a single file
as input. Thus, in order to compile a CaesarJ+ program, it is necessary to copy all of its
code into a single archive. As our idea is to validate the proposed constructs, we prefer
not to lose time extending the compiler to handle multiples CompilationUnit (multiple
files) at the same time.
Considering the complements construct, the update of pointcuts described in Sec-
tion 5.1.2 is not yet implemented. Also, the transformation of the DR instances is not
completely implemented. The actual compiler does not support references to specific
DR instances (or DR roles), as the updating of DR instances references (fourth stage of
Section 5.1.4) is still to be implemented. For example, the code of Listing 5.5, which
depicts the syntax designed for our language, actually must be written as described in
Listing 5.11. As we can see, it is necessary to direct reference the cclass which im-
plement the DR role during variable declarations (NextPieceBase, Line 3) and cclass
instantiation (Line 7).
Listing 5.11 How currently CaesarJ+ compiler accepts references to DR roles
1 dr NextPieceInstance = NextPieceDR [ NextPieceBase , EasyVar iat ion ]
2
3 public class Main {
4 NextPieceBase common ;
5
6 public stat ic void main ( int [ ] a r gs ) {
7 . . .
8 common = new NextPieceBase ( ) ;
9 }
10 }
Another limitation of the actual compiler is related to the enhancement of expressive-
ness introduced in Section 4.5. The method signatures that use wildcards and the advice
restrictions are not complete, so they are not copied into the generated specific ACIs.
Instead, they should be verified in order to check if their restrictions are being matched.
However, these verifications are not yet implemented.
The actual implementation also lacks a more precise and accurate validation and
error message mechanism for invalid structures. Stratego/XT error messages are vague,
5.2 COMPILER IMPLEMENTATION 67
general. In this way, the error messages generated by CaesarJ+ compiler are also general,
without informing, for example, the specific position of the error. Besides that, some
validations are not yet implemented. A possible improvement is to make a verification
using a compiler system, like JastAdd [26, 27], which is more suitable for validate the
code structure and generate proper error messages, before applying the Stratego/XT
transformations.
CHAPTER 6
EVALUATION
In this chapter we present an evaluation of CaesarJ+. As the objective of this work is to
enable the definition of design rules which increase CaesarJ modularity, our evaluation
compares CaesarJ implementations using ACIs with CaesarJ+ implementations which
use the introduced Design Rules to specify interfaces.
For this, we consider the same criteria of [43] for comparing languages, which are [18]:
• Language expressiveness: quantifies the degree to which a language is able to
express a restriction. It is a three level factor — a language supports, does not
support, or partially supports a specific rule.
• Language conciseness: measures how simple it is to express a restriction in
a language. We use the number of tokens required to express a constraint as a
measurement of conciseness.
Three examples are used in this evaluation, the Tetris SPL di!culty feature (Sec-
tion 6.1), an implementation of the Observer design pattern (Section 6.2), and one con-
cern of the Health Watcher System [53] (Section 6.3). The latter example also compares
the LSD (see Section 7.1.4) design rules with CaesarJ+ design rules.
6.1 TETRIS SPL - DIFFICULTY FEATURE
The Tetris SPL di!culty feature (briefly introduced in Section 3.1) is responsible for
displaying the box which shows the next tetris block (piece) of the game. This feature
has several variations, such as easy and normal, which show, respectively, the next two
pieces or the next piece that appear on the screen. The only di"erence between the
variations are (1) the update of the piece(s) to be displayed, and (2) the dimensions and
caption of the box which displays the next piece(s) on the screen. It is important to
note that the update of the next block(s) happens in several places of the source code,
for example, after a piece is dropped, when the game is restarted, when it is paused or
resumed, etc.
68
6.1 TETRIS SPL - DIFFICULTY FEATURE 69
In this way, in order to have a modular development of this feature, we should be able
to specify the following restrictions:
(R1) The implementation of the feature must contains two types of operations:
• Invariant operations, which are reused independently of the selected vari-
ation (easy or normal, for instance). They are responsible (1) for the initial
configuration of the component, which receives the dimensions of the box and
the class that has the graphic component (setup method, for example), (2) for
the representation of each piece (drawPiece) on the box, and (3) for the gen-
eral steps necessary for painting (paint) the box on the screen. These general
paint steps are independent of the selected variation, for example, defining the
initial position of the box (x and y), setting the background color, etc.
• Variant operations, which have a specific implementation depending on
which variation is selected. They are responsible for updating (update) the
pieces that appear on the game and for painting the box (paintBox) which
displays the next piece(s) to be dropped.
(R2) We aim to separate development of common (invariant) and variant operations. The
design rule which express these restrictions needs to have at least two roles, one
for the common operations and the other for the variant methods (NextPieceBase
and NextPieceVariation, for instance).
(R3) Common and variant operations depend on each other, as the general paint method
(paint) calls the specific paint operation (paintBox) provided by each variation,
and, in order to represent the next piece that is displayed, these specific paint oper-
ations call the invariant operation responsible for drawing each piece on the screen
(drawPiece). Moreover, the variant method updatePiece, which is responsible
for the update of the next block that is dropped, needs to call the generic paint
method. This implies that we have a bi-directional dependency between modules
which express common and variant operations.
(R4) As the update of the next piece to be displayed is scattered throughout di"er-
ent places (methods), we need a pointcut which specifies the set of join points
that should match. For example, the execution of Canvas class methods init and
updateBoxes. This pointcut is independent of which variation is selected.
6.1 TETRIS SPL - DIFFICULTY FEATURE 70
(R5) We need to specify that an advice, which uses at least the pointcut defined in R4,
must be implemented by the module responsible for the invariant operations. In
this case, it might be after advice.
(R6) It is also necessary to define that classes and methods used in the pointcuts declared
on the DR must exist. In this way, we can assure that classes and operations
specified on the pointcuts have an implementation.
Listing 6.1 shows a design rule specified using CaesarJ ACIs for the Tetris SPL di!-
culty feature, which is a more detailed version of the DR introduced in Listing 3.9. This
interface tries to impose restrictions R1 to R6. Lines 7-9 and 19-20 specify the common
and the variant methods of R1, respectively, whereas Lines 4-5 depict the attributes used
by these methods1.2.
Listing 6.1 CaesarJ ACI for the di!culty feature
1 public abstract cclass NextPieceCI {
2 public abstract cclass NextPieceBase {
3
4 protected int width , he i ght ;
5 protected Tetr i sCanvas tc ;
6
7 public abstract void setup ( int width , int height , Tetr i sCanvas tc ) ;
8 protected abstract void paint ( ) ;
9 protected abstract void drawPiece ( int type ) ;
10
11 protected abstract void paintBox ( ) ; // Implemented by var i a t i on
12 public abstract void updatePiece ( ) ; // Implemented by var i a t i on
13
14 pointcut matchCanvas ( ) : execution (! Canvas+. i n i t ( . . ) )
15 | | execution (! Canvas+. s ideBoxes ( . . ) ) ;
16 after ( ) : matchCanvas ( ) { }
17 }
18 public abstract cclass NextPieceVar iat ion extends NextPieceBase {
19 protected abstract void paintBox ( ) ;
20 public abstract void updatePiece ( ) ;
21 }
22 public abstract cclass Canvas {
23 protected abstract void i n i t ( Graphics g ) ; //Used by the po in t cu t s
1On theory the Canvas cclass must inherit from the JME Api Canvas class. However, as CaesarJ
classes cannot inherit from Java classes, we use the TetrisCanvas type, which inherits from Canvas
JME API class and is responsible for instantiate and communicate with the Canvas CaesarJ class of
Listing 6.1.2We use the TetrisCanvas type because CaesarJ classes cannot inherit from Java classes, i.e., the
Canvas role cannot inherit from the Java class which provides the paint component.
6.1 TETRIS SPL - DIFFICULTY FEATURE 71
24 protected abstract void s ideBoxes ( Graphics g ) ; //Used by the po in t cu t s
25 }
26 }
As we can see, this DR defines two roles, one for the common operations (NextPiece-
Base, 2-17) and another for the variant operations (NextPieceVariation, 18-21), which is
demanded by R2. However, the CaesarJ compiler does not enforce that all the virtual
classes defined within a given ACI must be implemented, which means that R2 is only par-
tially assured (checked). Restriction R3 can be specified with the duplication of method
signatures of one role inside another role (NextPieceVariation methods duplicated in-
side NextPieceBase, Lines 11-12), as detailed in Sections 3.2.2 and 3.3.2. However, it
compromises the comprehensibility of the DR, as this duplication generates a confusing
interface.
The matchCanvas pointcut (Lines 14-15) specifies R4. However, the pointcut alone
is not enough to guarantee that methods init and sideBoxes of a Canvas class exist,
which is required by R6. In this way, the Canvas role is declared in Lines 22-25, defining
that its implementations must provide at least methods init and sideBoxes. However,
as already stated, CaesarJ compiler does not enforce that Canvas virtual class will have
an implementation, which leaves R6 partially assured.
Line 16 presents an after advice which attempts to represent R5. However, it is a
weak condition, since R5 states that an after advice, which uses at least matchCanvas
pointcut, must be present in the implementation of the invariant operations, whereas Line
16 means that this DR role has an empty after advice. In this way, if the implementation
of NextPieceBase does not have an advice, or has one which does not use matchCanvas,
no error message is indicated by CaesarJ compiler.
Listing 6.2 CaesarJ+ Design Rule for the di!culty feature
1 dr NextPieceDR [Common, Var iat ion , Canvas ] {
2 public abstract cclass Common {
3 protected int width , he i ght ;
4 protected Tetr i sCanvas tc ;
5
6 public abstract void setup ( int width , int height , Tetr i sCanvas tc ) ;
7 protected abstract void paint ( ) ;
8 protected abstract void drawPiece ( int type ) ;
9
10 pointcut matchCanvas ( ) : execution (! Canvas+. i n i t ( . . ) )
11 | | execution (! Canvas+. s ideBoxes ( . . ) ) ;
12 after ( . . ) : matchCanvas ( ) . . ;
13 }
14 public abstract cclass Var iat i on complements Common {
15 protected abstract void paintBox ( ) ;
6.1 TETRIS SPL - DIFFICULTY FEATURE 72
16 public abstract void updatePiece ( ) ;
17 }
18 public abstract cclass Canvas {
19 protected abstract void i n i t ( . . ) ; //Used by the po in t cu t s
20 protected abstract void s ideBoxes ( . . ) ; //Used by the po in t cu t s
21 }
22 }
The use of CaesarJ+ design rules can mitigate these problems. Listing 6.2 depicts
NextPieceDR, a CaesarJ+ design rule for this feature. This DR looks similar to the
ACI of Listing 6.1, however, it guarantees restrictions R1 to R6. CaesarJ+ compiler
enforces that all the roles declared as NextPieceDR parameters must be implemented
when this DR is being used, encompassing R2 and R6. Line 13 depicts an after advice
which uses the matchCanvas pointcut, the wildcard “..”, and does not have a body. This
declaration means that the implementation of the Common role must have an after advice
which uses at least the matchCanvas pointcut (minimum requirement that matches the
wildcards), otherwise an error is raised by the compiler3. Moreover, the complements
construct enables the bi-directional dependency among two roles (restriction R3), without
compromising the comprehensibility of the DR.
Table 6.1 summarizes our evaluation for this example. Regarding expressiveness,
restrictions R1, R3 and R4 are statically checked by CaesarJ compiler, although the
representation of R3 compromises the ACI comprehensibility. R5 cannot be expressed
(nor checked), whereas R2 and R6 are only partially checked, as the compiler raises error
if the implementation of the roles do not provide the correct methods, but no error is
given if the ACI is used without an implementation for these roles. Instead, CaesarJ+
DRs can statically check all the imposed restrictions (R1 to R6).
Table 6.1 Tetris SPL Di!culty Feature: Summary of the evaluation. The acronyms mean
Statically checked (SC), Partially checked (P) and No checking (N).
Expressiveness Conciseness
R1 R2 R3 R4 R5 R6 R1 R2 R3 R4 R5 R6
CaesarJ ACI SC PC SC* SC N PC 45 16 16 27 - 24
CaesarJ+ DR SC SC SC SC SC SC 45 19 2 27 10 26
Analyzing conciseness, we have similar numbers of tokens for both ACI and DR.
3As discussed in Section 5.2.3, this feature is not yet implemented in the actual CaesarJ+ compiler
prototype.
6.2 OBSERVER DESIGN PATTERN 73
We consider the following as a token: language keywords (such as public, abstract),
operators (ex. &&, ||), delimiters (ex. “.”, “,”), brackets and parenthesis. Restriction,
R2 is expressed by the declarations of NextPieceBase and NextPieceVariation (Lines 2
and 18, Listing 6.1) on CaesarJ ACI, whereas it is represented by the signatures of Common
and Variation (Lines 2 and 15, Listing 6.2) plus the parameters Common and Variation
of NextPieceDR (Line 1). Similar occurs with R6, which needs two more tokens on the
DR due to the parameter Canvas (Line 1). Although there is a slight increase for this two
restrictions, the DR enables the static checking of them, which was not possible using
ACIs. Restriction R5, which cannot be expressed by the ACI, is expressed by the DR
using 10 tokens.
Considering the implementation of ACIs and DRs, when using DR we have a small
reduction on the number of tokens used, as developers now use top-level classes to im-
plement the DR roles, instead of using virtual-classes (see Section 5.1.3). Finally, the
instantiations process of ACIs and DRs uses the same quantity of tokens (Section 5.1.4).
As we can see, the use of CaesarJ+ design rules enable the specification of restrictions
which were not able to be expressed using only CaesarJ ACIs. Moreover, CaesarJ+ DRs
allows the static checking of restrictions which could not be checked by CaesarJ compiler,
representing a gain of expressiveness. Furthermore, the amount of tokens necessary by
CaesarJ+ to impose those restrictions is almost the same used by CaesarJ ACI which
can only partially express some of the restrictions.
6.2 OBSERVER DESIGN PATTERN
Mezini and Ostermann introduces in [42] the initial concepts of CaesarJ. They argue that
AspectJ Join point Interception model has some deficiencies, such as lack of support for
sophisticated mapping, as all methods of a given aspect are top-level methods of the
enclosing aspect, it is not possible to separate the roles inside an aspect. Another problem
listed is related to the aspect binding, as in AspectJ every aspect binding is coupled to
one specific implementation, it is not possible to reuse an specific binding with a di"erent
aspect implementation.
In order to detail these and other problems related to the AspectJ Join point inter-
ception mechanism, Mezini and Ostermann use an implementation of the observer design
pattern in CaesarJ4, comparing it to the AspectJ implementation of the same pattern pro-
posed by Hannemann and Kiczales [25]. The authors state that the following restrictions
4In fact, the authors detail an implementation in Caesar, which later became CaesarJ.
6.2 OBSERVER DESIGN PATTERN 74
should be respected:
(R1) We must be able to define multiple abstractions (facets) inside the aspect, one
representing the Subject and the other representing the Observer. This increases
the aspect internal separation of concern, which cannot be done using AspectJ.
(R2) The implementation of the Aspect facets must contain the following operations:
• Subject: Amethod for inserting a new Observer (addObserver), an operation
which removes a specific observer (removeObserver), and a method for up-
dating the observers (update) are needed. A method which returns a String
containing informations about the specific state of the updated subject is also
necessary (getState).
• Observer: This facet needs a method which is notified about modifications
that occur within a subject which is being observed (notify).
(R3) The Aspect implementation should be separate from the binding, allowing the reuse
of an Aspect implementation in di"erent contexts (with di"erent bindings), and the
reuse of an Aspect binding (for a specific context) with di"erent implementations.
The Subject abstraction, for example, has operations related to the Aspect im-
plementation (addObserver, removeObserver and update, these implementations
depend on the date structure used), and one method related to the class which is
being a"ected by the aspect (getState).
Listing 6.3 depicts ObserverProtocol, the CaesarJ ACI for the observer design pat-
tern implementation5. The definition of virtual classes Subject and Observer (Lines 2
and 9) specifies R1. However, as previously discussed, CaesarJ compiler does not enforce
that these virtual classes will be implemented. For example, no error is given if only
an implementation of Observer is provided. Lines 3-6 and Line 10 guarantee that the
implementation of Subject and Observer, if provided, have all the needed methods (R2).
Listing 6.3 CaesarJ ACI for the observer design pattern
1 public abstract cclass ObserverProtocol {
2 public abstract cclass Subject {
3 public abstract void addObserver ( Observer o ) ;
4 public abstract void removeObserver ( Observer o ) ;
5 public abstract void update ( ) ;
6 public abstract Str ing getState ( ) ;
5The Observer is an o!cial CaesarJ example and its source code can be downloaded at [10].
6.2 OBSERVER DESIGN PATTERN 75
7 }
8
9 public abstract cclass Observer {
10 public abstract void no t i f y ( Subject s ) ;
11 }
12 }
The implementations of this ACI roles use the wrapper (see Section 2.3.4) mechanism
to adapt (bind) existing classes to the aspect facets (roles) Subject and Observer, as we
can see in Listing 6.4. However, considering R3, the ObserverProtocol ACI does not
have any indication that the getState method should be developed separated from the
other methods, inside a module responsible only for the aspect binding. We can extend
this ACI splitting the Subject role into two roles, Subject and SubjectImplementation,
similar to NextPieceBase and NextPieceVariation of Listing 6.1. However, even with
this extension we can only partially express R3, as the extension would lead to the same
problems of duplicated methods discussed in Sections 3.2.2 and 3.3.2.
Listing 6.4 CaesarJ Implementation of Subject binding
1 public abstract cclass ColorObserver extends ObserverProtocol {
2 public cclass PointSubject extends Subject wraps Point {
3 public Str ing getState ( ) {
4 return ”Point co l o r ed ” + wrappee . getColor ( ) ;
5 }
6 after ( Point p ) : ( ca l l (void Point . s e tCo lor ( Color ) ) && target (p ) ) {
7 PointSubject (p ) . update ( ) ;
8 }
9 }
10 . . .
11 }
Listing 6.5 CaesarJ+ design rule for the observer design pattern
1 dr ObserverDR [ Subject , SubjectImplementat ion , Observer ] {
2 public abstract cclass Subject {
3 public abstract Str ing getState ( ) ;
4 }
5 public abstract cclass SubjectImplementation complements Subject {
6 public abstract void addObserver ( Observer o ) ;
7 public abstract void removeObserver ( Observer o ) ;
8 public abstract void update ( ) ;
9 }
10 public abstract cclass Observer {
11 public abstract void no t i f y ( Subject s ) ;
12 }
13 }
Listing 6.5 depicts a possible CaesarJ+ design rule for this example. Di"erent from
the ObserverProtocol ACI, now we have a clear identification on the design rule of
6.2 OBSERVER DESIGN PATTERN 76
roles Subject, responsible for the binding, and SubjectImplementation, responsible for
the implementation facet. In this way, R3 is now guaranteed, as the implementation
of Subject provides the binding method getState, whereas the cclass implementing
SubjectImplementation provides the methods of the implementation facet, otherwise
a compiler error is raised. Due to the complements relationship, the Subject object
received by Observer method notify (Line 11) has access to both operations of Subject
and SubjectImplementation, which is necessary by the pattern.
Restriction R1 is now enforced by CaesarJ+ compiler, as all the roles (inner cclasses)
are declared as parameters of the DR, which means that an implementation for each of
them must be provided. The other restriction, R2, is specified by Lines 3, 6-8 and 11,
which guarantee that both Subject and Observer roles have the needed methods. The
implementation of ObserverDR binding roles is similar to the implementation of a non-
binding DR role, the only di"erence is the use of the wrapper keyword and the name of
the class that we want to bind on the cclass signature, as we can see in Listing 6.6.
Listing 6.6 CaesarJ+ implementation of ObserverDR Subject binding role
1 public cclass PointSubject implements ObserverDR [ Subject ] wraps Point {
2 public Str ing getState ( ) {
3 return ”Point co l o r ed ” + wrappee . getColor ( ) ;
4 }
5 after ( Point p ) : ( ca l l (void Point . s e tCo lor ( Color ) ) && target (p ) ) { . . . }
6 }
Table 6.2 summarizes our evaluation for the Observer example, depicting the results
for the solutions using ACI (the first and the extended one) and CaesarJ+ DR to express
the interface. Considering expressiveness, the DR is able to guarantee R1 to R3, whereas
the first ACI can only express R1 and R2, but cannot statically check R2. The extended
ACI can express the three restrictions, but can only statically check R2.
Table 6.2 Observer Example: Summary of the evaluation.
Expressiveness Conciseness
R1 R2 R3 R1 R2 R3
CaesarJ ACI PC SC N 12 41 -
Extended CaesarJ ACI PC SC PC 12 41 33
CaesarJ+ DR SC SC SC 15 41 10
In order to express R1, the number of tokens used by the DR has a slightly in-
6.3 HEALTH WATCHER TRANSACTION CONCERN 77
crease comparing to the ACI solutions (15 to 12), however the DR solution now enforces
this restriction, whereas the ACI solutions can only partially check it. Moreover, the
ObserverDR uses only 10 tokens (8 tokens of SubjectImplementation signature plus 2
tokens of its parameter on the DR signature) to guarantee R3, whereas the first ACI can-
not express this restriction and the extended one uses 33 tokens (due to the duplicated
method signatures inside the Subject role) only to express R3, as it cannot statically
check it.
6.3 HEALTH WATCHER TRANSACTION CONCERN
The Health Watcher (HW) system [53] is a web-based information system originally im-
plemented in Java and later restructured with AspectJ [32]. It was developed to improve
the quality of the services provided by health care institutions, allowing citizens to reg-
ister complaints regarding health issues, so that health care institutions can investigate
and take required actions. HW design has a significant number of non-crosscutting and
crosscutting concerns, requiring a number of recurrent design decisions related to Trans-
actions, GUI, persistence, and other concerns. The HW system has been used as a case
study of several aspect-oriented works [23, 53, 43].
Costa Neto [43] uses the HW Transactional Concern as one case study of his Language
for Specifying Design Rules (LSD), comparing the specification of this concern in LSD
with another implementation that uses the XPI approach [24]. In this section we compare
one CaesarJ+ DR for this example with the LSD DR introduced by Costa Neto and with
an implementation using CaesarJ ACIs.
In order to enable the parallel development between classes and aspects responsible
for implementing the transaction concern, the following restrictions must be specified by
our interface [43]:
(R1) There must exist an interface (ITransactionMechanism) that defines methods for
starting (begin), committing (commit), and rolling back transactions (rollback);
(R2) These methods may throw an exception TransactionException in case of error;
(R3) Also, in order to enable the definition of the pointcuts, we need to specify a facade
named HWFacade;
(R4) The transaction aspect HWTransactionAspect must call ITransactionMechanism
methods. Moreover, these calls have to occur at specific places, detailed in what
follows:
6.3 HEALTH WATCHER TRANSACTION CONCERN 78
• A transaction must be started before any facade method (the aspect should
call ITransactionMechanism.begin());
• After the return of any facade method, the current transaction should be
committed (the aspect should call ITransactionMechanism.commit());
• If any exception is raised by facade methods, the current transaction should
be rolled back (the aspect should call ITransactionMechanism.rollback());
and
(R5) These calls must only occur within the aspect HWTransactionAspect.
Listing 6.7 shows the LSD (see Section 7.1.4) design rule for the HW Transaction
Concern. Without discussing syntax details, TransactionManagementDR restricts that
ITransactionMechanism must be an interface with three methods that throw an excep-
tion (R1 and R2), and that TransactionManagement must be an aspect, otherwise a
compilation error is raised. In addition, LSD xcall construct assures that a call occurs
only within a specified scope among the DR components. In this way, the DR restricts
that begin, commit and rollback can only be called within before, after returning
and after throwing advice, respectively (R4 and R5). The DR also states that a class
named HWFacade must exists (R3).
Listing 6.7 LSD design rule for the HW Transaction Concern
1 dr TransactionManagementDR
2 [ ITransactionMechanism , TransactionManagement , HWFacade ] {
3
4 interface ITransactionMechanism {
5 void begin ( ) throws Transact ionException ;
6 void commit ( ) throws Transact ionException ;
7 void r o l l ba ck ( ) throws Transact ionException ;
8 }
9 aspect TransactionManagement {
10 pointcut t r an s ac t i ona lPo i n t s ( ) : ca l l (! HWFacade . ! ( . . ) ) ;
11
12 be f o r e ( ) : t r an s a c t i ona lPo i n t s ( ) {
13 xcal l (void ITransactionMechanism . begin ( ) ) ;
14 }
15 after ( ) returning : t r an s a c t i ona lPo i n t s ( ) {
16 xcal l (void ITransactionMechanism . commit ( ) ) ;
17 }
18 after ( ) throwing : t r an s a c t i ona lPo i n t s ( ) {
19 xcal l (void ITransactionMechanism . r o l l ba ck ( ) ) ;
20 }
21 }
22 class HWFacade { }
23 }
6.3 HEALTH WATCHER TRANSACTION CONCERN 79
Listing 6.8 depicts the implementation for the Transaction Management feature using
CaesarJ+ DR. The abstract cclass ITransactionMechanism (Lines 2-6) specifies R1 and
R2, depicting the three methods throwing a specific exception (TransactionException),
whereas HWFacade (Line 13) specifies R4. The TransactionManagement role specifies that
its implementation must have three advices using the transactionalPoints pointcut, but
it is not possible to define restrictions over the behavior of this advice, which is demanded
by R4. However, as stated in Section 7.2, we do plan to include behavioral restrictions
in CaesarJ+. Regarding R5, it is also not possible to express in CaesarJ+ that calls to
a method must occur only inside a given scope, which is defined in LSD by the xcall
construct.
Listing 6.8 CaesarJ+ design rule for the HW Transaction Concern
1 dr TransactionDR [ ITransactionMechanism , TransactionManagement , HWFacade ] {
2 public abstract cclass ITransactionMechanism {
3 public abstract void begin ( ) throws Transact ionException ;
4 public abstract void commit ( ) throws Transact ionException ;
5 public abstract void r o l l ba ck ( ) throws Transact ionException ;
6 }
7 public abstract cclass TransactionManagement {
8 pointcut t r an s ac t i ona lPo i n t s ( ) : ca l l (! HWFacade . ! ( . . ) ) ;
9 b e f o r e ( ) : t r an s a c t i ona lPo i n t s ( ) ;
10 after ( ) returning : t r an s a c t i ona lPo i n t s ( ) ;
11 after ( ) throwing : t r an s a c t i ona lPo i n t s ( ) ;
12 }
13 public abstract cclass HWFacade { }
14 }
Table 6.3 shows the results of our evaluation for the HW Transaction Concern. Note
that neither CaesarJ ACI (see Listing 6.9) nor CaesarJ+ DR can express R5, while
CaesarJ+ DR can only partially express R4, as it can specify that some advice, which
use a specific pointcut, must be present on the role implementation, but it cannot enforce
that those advice have to call a specific method. Moreover, CaesarJ ACI cannot express
restrictions over advice, and CaesarJ compiler does not statically check R1 and R3, as
no error is given if implementations of ITransactionMechanism nor HWFacade virtual
classes are not provided.
Listing 6.9 CaesarJ ACI for the HW Transaction Concern
1 public abstract cclass TransactionACI {
2 public abstract cclass ITransactionMechanism {
3 public abstract void begin ( ) throws Transact ionException ;
4 public abstract void commit ( ) throws Transact ionException ;
5 public abstract void r o l l ba ck ( ) throws Transact ionException ;
6 }
7 public abstract cclass TransactionManagement {
6.3 HEALTH WATCHER TRANSACTION CONCERN 80
8 pointcut t r an s ac t i ona lPo i n t s ( ) : ca l l (! Facade . ! ( . . ) ) ;
9 }
10 public abstract class Facade { }
11 }
Table 6.3 HW Transaction Concern: Summary of the evaluation.
Expressiveness Conciseness
R1 R2 R3 R4 R5 R1 R2 R3 R4 R5
LSD DR SC SC SC SC SC 20 6 6 81 9
CaesarJ ACI PC SC PC N N 27 6 6 - -
CaesarJ+ DR SC SC SC PC N 28 6 8 50 -
Analyzing conciseness, we have similar number of tokens used in both LSD DR and
CaesarJ+ DR. CaesarJ+ needs more tokens to express some restrictions due to the key-
words public and abstract, which must be present on the DRs. If we had a construct
similar to LSD call or xcall in CaesarJ+, we would use 30 more tokens to express and
check R4, resulting in 83 tokens, only two tokens more than LSD. As already said, these
two tokens are relative to the keywords public and abstract (Line 7 of Listing 6.8).
CHAPTER 7
CONCLUDING REMARKS
In this work we present CaesarJ+, an extension to increase CaesarJ modularity. CaesarJ+
introduces design rules construct, which enforces syntactic restrictions over multiple roles
that collaborate in a specific context. As these roles are implemented by caesarj classes, we
can define restrictions on the DR relative to both Object-Oriented and Aspect-Oriented
code. In this way, by using the design rules we can obtain crosscutting modularity with-
out compromising class modularity. A CaesarJ+ compiler was developed to verify wether
the rules specified within the DRs are being obeyed. It uses the Stratego/XT [8] trans-
formation language and generates valid CaesarJ code after the compilation process. We
evaluate CaesarJ+ by specifying interfaces for three di"erent examples, using CaesarJ+
DRs and CaesarJ ACI, and them comparing the expressiveness and conciseness of both
approaches.
Initially we studied the use of CaesarJ ACIs to specify interfaces for OO and AO code.
However, regarding modularity, we have found several issues when specifying ACI inter-
faces. For example, some roles cannot be well defined on the ACIs (duplicated code), and
CaesarJ compiler does not enforce that all the specified roles must have an implementa-
tion, compromising the parallel (independent) development. CaesarJ+ design rules, for
instance, enforces that all roles specified within a DR must have an implementation. Our
extension introduces the complements relationship, enabling the parallel development of
parts of a class. CaesarJ+ is also more expressive than CaesarJ, as our DR notion allows
the use of AspectJ like wildcards to specify rules for methods and advice restrictions,
whereas CaesarJ ACIs has only exact restrictions, and they cannot express advice re-
strictions. Nevertheless, CaesarJ+ can only express syntactic restrictions. Our DRs are
not able to express semantic restrictions. CaesarJ+ also facilitates the implementation
of the DR roles, as developers use top-level classes to implement the DRs roles, while,
when using ACIs, they had to define both a top-level class and a virtual class.
In order to use CaesarJ+, developers must get used to the new languages constructs.
On the other hand, it helps the development of the new OO and AO code, as the DRs
express and check restrictions that should be obeyed by the developers. Our language,
does not verify wether changes on roles implementations break the intents of an aspect.
81
7.1 RELATED WORK 82
However, it provide the necessary informations for the identification of these issues by
developers, as classes participating of a collaboration must explicitly implement a DR,
indicating to the developer that he must analyze the DR code prior to any changes. We
believe that it helps to mitigating the fragile pointcut problem [36].
Although we discuss the use of CaesarJ+ DRs to guide the independent development
of OO and AO code, our design rules can also be useful to existing CaesarJ systems.
In this scenario, some modifications on the source code need to be applied, but after
established, CaesarJ+ DRs assist software maintenance and evolution, guiding developers
to discover what changes they are able to do without modifying the aspects intentions.
In summary, the main contributions of this work are:
• An analysis of the use of CaesarJ ACIs focusing on the specification of modular
interfaces for OO and AO code;
• CaesarJ+, a language that enables the specification of design rules for increase
CaesarJ modularity;
• A compiler for CaesarJ+, which allows the static checking of the restrictions spec-
ified on the design rules.
7.1 RELATED WORK
Several authors have been discussing modularity problems in aspect-oriented languages [50,
54, 57, 12]. For instance, Rajan and Sullivan [50] argue that the asymmetry of classes
and aspects complicates system composition, harming modularity. For them, separating
classes and aspects reduces the conceptual integrity of the programming model. In this
way, they propose Classpects, a construct that unifies the capabilities of classes and as-
pects. As a proof of concept, they use a classpect-oriented language, which uses static
and non-static binding along with method calls (binding methods) to replace the un-
named AspectJ-like advice. This static and non-static binding are similar to CaesarJ
dynamic binding, while both languages enable aspects instances. However, di"erent from
CaesarJ+, Classpects does not have any interface mechanism which can specify and check
restrictions of related OO and AO code.
In a similar way, Clifton and Leavens state that AOP languages harm comprehensibil-
ity, since they require system to be studied in their entirety [12]. They propose a simple
set of restrictions to improve comprehensibility in AOP systems, which characterizes as-
pects as (1) observers, which does not change modules specifications, or as (2) assistants,
7.1 RELATED WORK 83
aspects that might change module specifications. Observers preserve modular reasoning
even in the cases that advised modules do not make explicit references to them. The
authors argue that modules advised by assistants aspects should make explicit references
them, in order to preserve the modular reasoning. They introduce accept type, a new
construct which indicates that a module accepts to be advised by an assistant aspect.
In this way, class developers become aware that an assistant aspect exists and should be
studied before any modifications on the code. CaesarJ+ DRs, for instance, can depict the
necessary pointcuts and also have informations about advice. Thus, it informs developers
that a specific AO implementation should be observed, avoiding the need of a complete
system study.
Chavez et al [11] present crosscutting interfaces as a conceptual tool for dealing with
complexity of heterogeneous aspects at the design level. This work also presents a mod-
eling notation for description of architectural-level aspects that also supports the explicit
representation of crosscutting interfaces. However, despite of using a visual notation is
important for documentation purpose, it does not enable to check if the code was built
according to established interfaces.
On AspectJ [34, 33] we can define abstract aspects, which may work like an interface.
However, they can only specify restrictions related to structure of aspects, its not possible
to specify classes restrictions. Moreover, we cannot define multiple roles inside an abstract
aspects, in order to organize the multiple facets of a given crosscutting concern, as we
can do with CaesarJ+ DRs. Also, it is not possible to define any restrictions related to
advice. CaesarJ+ DRs, for instance, can enforce restrictions to aspects and classes. It is
possible to define multiple facets (roles) inside our DRs, and they can specify restrictions
related to advice.
Other works discuss how to expose more stable aspect-oriented interfaces and how to
compute module interfaces in AOP systems. In the following sections we discuss some of
these work, which are more related to our proposal.
7.1.1 Open Modules
Open Modules is an approach for dealing with modularity issues in AOP [3]. Aldrich
suggested that any exposed joinpoint must be declared in the interface of a module. In
this way, the maintainer of this module has to preserve the joinpoint behavior, helping
to mitigate the fragile pointcut problem. Clients of these modules can advise only the
exported pointcuts, which introduces a form of module joinpoint encapsulation. A later
7.1 RELATED WORK 84
work provides a open-modules implementation for AspectJ [45], generalizing the open
modules to handle arbitrary AspectJ pointcuts.
However, this joinpoint hiding mechanism does not provide any information to the
aspect developer beyond the exported joinpoints and public methods, like advice infor-
mation and use of a certain pointcut by an advice, which are useful for helping aspects
developers. CaesarJ+, on the other hand, o"er mechanisms to describe all the types that
participate of a given collaboration, beyond the possibility to describe aspect responsi-
bilities, as the existence of a specific advice. As a consequence, module developers are
still able to unintentionally implement part of a concern assigned to a di"erent team
because they cannot assume the existence of any behavior expected to be modularized
as an aspect.
7.1.2 Aspect Aware Interfaces
Kiczales and Mezini discuss in [35] about interfaces for modules in systems developed
with AOP. The authors state that, when using Aspects, it is necessary to analyze the
whole system in order to determine the complete interface of a module. They introduce
Aspect-Aware Interfaces (AAI), a new type of interface which is automatically computed
after each modification on the source code. This interface shows the dependencies between
related classes and aspects, specifying where a given aspect a"ects each system class. The
authors argue that Aspect-Aware interface helps developers to reason about the e"ects
of new modifications on the source code.
A later work [52] stores the computed AAIs and compare then with new interfaces
generated after modifications on the source code, verifying if there is any change on the
join points intercepted by the aspects. This approach identifies missing and accidentally
captured join points. In this way, AAIs are very useful for evolution of a AO system.
However, this approach does not support earlier development phases, as this interfaces
are only generated after the whole system is ready. CaesarJ+ DRs, for instance, should
be specified before the development of the OO and AO code, being used as a guide for
the development of both classes and aspects. Moreover, the use of CaesarJ+ DRs enables
the static checking of the development code, verifying if they match the established rules.
7.1.3 Crosscutting Programming Interfaces (XPIs)
Sullivan et al. present in [57] a comparative analysis between an AO system developed
using the oblivious approach and the same system developed with clear design rules that
7.1 RELATED WORK 85
document interfaces between classes and aspects. The latter approach promises benefits
when relevant crosscutting behavior are anticipated and when new code, anticipated or
not, can be written against existing interfaces (design rules). However, this work uses
natural language to describe the design rules, which may lead to long and ambiguous
interpretations that cannot be statically checked.
In a subsequent work [24], they propose the Crosscutting Programming Interfaces
(XPIs), which uses AspectJ to express and check their design rules. The authors argue
that the main advantages of their XPIs are that (1) it does not require any new construct
in the AspectJ language; and (2) there is no restriction to the pointcut visibility. These
characteristic encourage the use of XPIs in sites that are already using the AspectJ
language. However, most of the constraints required for defining the responsibilities of
both class developers and aspect developers cannot be checked using the proposed XPI
language, specially the restrictions relative to classes contents. In this way, di"erent
from CaesarJ+, XPIs cannot guarantee (static check) that certain design rules are being
obeyed. It happens because pointcut constructs in AspectJ were proposed for specifying
points of execution that should be augmented by advices, not for specifying restrictions
applied for base code developing.
Although it is possible to check part of the design rules using XPIs by means of AspectJ
declare warning and declare error, the use of a language not designed to this purpose leads
frequently to complex specifications (in this case, complex AspectJ pointcuts). Finally,
when using CaesarJ+ we also have all the benefits of CaesarJ aspects, such as dynamic
deploy and aspect polymorphism (Section 2.3).
7.1.4 Language for Specifying Design Rules (LSD)
Costa Neto [43, 44] proposes LSD, a language for specifying design rules in systems imple-
mented with AspectJ. As in this work, the author argues that through the establishment
of design rules it is possible to obtain crosscutting modularity and preserve class mod-
ularity. LSD provides structural and behavioral rules witch enable the establishment of
minimum requirements necessary for a independent development of related classes and
aspects. The structural rules specify which artifacts should be implemented (interfaces,
classes or aspects) and what should be implemented by these artifacts (methods, at-
tributes, pointcuts, advice), whereas the behavioral rules restricts what should happen
inside a specific scope, for example, a method call or the definition (set) or retrieval (get)
of a specific attribute.
7.1 RELATED WORK 86
LSD provides powerful constructs for rules quantification, such as all (for instance,
for all public methods of a class, apply one restriction), exists and none. Moreover, it
is also possible to combine LSD DR constructs with boolean operators (&&, ||) or deny
them using the negation operator (!).
CaesarJ+ is inspired on LSD, both have similar syntax, design rule parameters, and
DR instance. In this way, CaesarJ+ put together the concept of Design Rules with the
benefits of CaesarJ, allowing the static checking of the established rules, aiming to increase
CaesarJ modularity. The actual version of CaesarJ+ has only behavioral rules, however
we do plan to insert behavioral rules to our extension (see Section 7.2). Finally, LSD
is more expressive than CaesarJ+, as it has many constructs for express quantification
of rules, and its design rules instances can specify multiple classes or a package as a
DR parameter, whereas in CaesarJ+ we can only specify one class for each DR instance
parameter (Section 5.1.4).
7.1.5 CrossMDA2
CrossMDA2 [19] is a model based approach for minimizing the fragile pointcut prob-
lem. It proposes Conceptual-View Based Pointcuts , a particular instance of Kellens
model-based pointcut [29] approach, and uses View-based pointcuts [30] as a base, which
introduces an intermediate model (Conceptual Model) in order to decouple the pointcuts
from the base model (Business Model), increasing modularity. CrossMDA2 extends this
intermediate model, introducing more relationships and restrictions, increasing the model
flexibility.
This conceptual model defines design rules that must be obeyed during the devel-
opment process. It is composed of views, which are similar to our DR roles. However,
CrossMDA2 design rules are only unidirectional, their rules are only related to classes.
CaesarJ+ DRs are multidirectional, they define restriction to both classes and aspects.
Moreover, as this approach is model based, their restrictions are specific, they cannot
be generalized, relaxed. Our DRs can impose more generic restrictions with the use of
wildcards, as introduced in Section 4.5.1 (although the actual implementation does not
support it). Also, the restrictions imposed by this Conceptual Model are only structural,
similar to our restrictions and di"erent from LSD 7.1.4, which can define both behavioral
and structural restrictions.
CrossMDA2 has a map between the Conceptual Model and the Business Model, which
is similar to our design rules instantiation process. However, this mapping is much more
7.2 FUTURE WORK 87
powerful than the our DR instantiation process, being even more powerful than LSD DR
instantiation process. In CrossMDA2 it is possible to define alternative instantiations
to the model, using expressions to define members responsible for each view (role), and
them verify if both alternative expressions results in the same set of members (classes,
methods, etc.), otherwise an error is raised. The actual version of CaesarJ+ allows only
a single class for each DR role in the instantiation process, whereas LSD allows group of
classes, like all classes of a given package. For example, if this alternative instantiation
process was enabled in CaesarJ+ it would look like code of Listing 7.1.
Listing 7.1 Possible alternative DR instantiation process
1 dr Al t e r na t i v e In s t = DR[ Impl ! , Example ! ]
2 | | DR[ Implementation , example . ! ]
The depicted code would mean that instance AlternativeInst of design rule DR
(two parameters) would have all classes of the system whose name starts with Impl as
the first parameter and all classes of the system whose name starts with Example as the
second parameter (Line 1). Moreover, the alternative instance in Line 2 would mean
that Implementation must be the only class which name starts with Impl, while all the
classes whose name starts with Example must be inside the example package (and the
example package must have only classes with name starting by Example).
Finally, the restrictions of CrossMDA2 does not enforce that a given member (class or
method) must exist, whereas the restrictions of our design rules obligates that classes re-
sponsible for a given role must provide all the methods specified within the DR, otherwise
an error is raised.
7.2 FUTURE WORK
First, we plan to conclude the implementation of CaesarJ+ compiler, as the actual ver-
sion does not encompasses the whole language. The most important points which are not
covered by the compiler are the references to DR instances, the update of the comple-
mented roles pointcuts, the DR advice restrictions and the use of wildcards on methods
and advice, as discussed in Section 5.2.3. We also need to make more evaluations of
CaesarJ+, analyzing the implementation of new examples. Another thing to do is to
increase the tool support for developers, as the the actual compiler is a command-line
application, which displays the error messages on the console. An Eclipse [15] plugin for
CaesarJ+ could facilitate the use of the language.
We also intend to insert new constructs to CaesarJ+. We have identified the need
7.2 FUTURE WORK 88
of enhanced quantification mechanisms for expressing rules, such as LSD constructs all,
exists, one and none [43]. Functionalities such as DR inheritance are also needed, in
order to enable the specification of high-level general design rules which could be then
inherited and adapted to a specific context, increasing the possibility of DRs reuse. We
also plan to extend CaesarJ+ to support behavioral rules, with constructs similar to LSD
call and xcall. These kind of rules are important because aspect developers usually
trust on some calls at a pointcut specification.
Another possible future work is the integration of CaesarJ+ with Van Landuyt et
al. [37] work, which introduces a domain-driven process for identifying abstractions that
lead to reusable pointcut signatures. In this way, we could adapt Van Landuyt approach
for generating CaesarJ+ DR instead of generating their pointcut interfaces. Finally, we
also plan to analyze how can we apply the proposed CaesarJ+ constructs into ECae-
sarJ [22], a language that extends CaesarJ and integrates it with the events and state
machine features of EAOP [14]. As ECaesarJ is yet to be released, it was not possible to
already compare and see how it could be integrated with CaesarJ+.
APPENDIX A
CAESARJ+ SDF GRAMMAR
A.1 GENERAL CAESARJ+ SPECIFICATION
module CaesarJP[CaesarJCtx]
imports
languages/java/JavaMix[CaesarJCtx]
languages/java/JavaMix[AspectTheCtx]
languages/java/JavaMix[PointcutTheCtx]
languages/java/JavaMix[PatternTheCtx]
languages/aspectj/lexical/Keyword
languages/aspectj/aspect/Declaration[AspectTheCtx JavaTheCtx]
languages/aspectj/pattern/Main[PatternTheCtx]
languages/aspectj/pointcut/Declaration[PointcutTheCtx]
languages/aspectj/pointcut/Expression[PointcutTheCtx JavaTheCtx]
languages/aspectj/common/BooleanComposition[PointcutExpr[[CaesarJCtx]]]
languages/aspectj/ajf/Keyword
DrDec
exports
sorts JavaTheCtx AspectTheCtx PointcutTheCtx PatternTheCtx
context-free start-symbols CaesarJCtxCompilationUnit
context-free syntax
CompilationUnit[[CaesarJCtx]] -> CaesarJCtxCompilationUnit
Externalization? ImportDec[[CaesarJCtx]]* TypeDec[[CaesarJCtx]]+
-> CompilationUnit[[CaesarJCtx]] {cons("CompilationUnit"),prefer}
%%% CCLASS %%%
"cclass" PackageName[[CaesarJCtx]] ";" -> Externalization {cons("Externalization")}
89
A.1 GENERAL CAESARJ+ SPECIFICATION 90
(Anno[[CaesarJCtx]] | ClassMod[[CaesarJCtx]])* "cclass"
Id[[CaesarJCtx]] TypeParams[[CaesarJCtx]]?
Super[[CaesarJCtx]]?
Complements[[CaesarJCtx]]?
InterfacesDr[[CaesarJCtx]]?
Wraps[[CaesarJCtx]]?
-> ClassDecHead[[CaesarJCtx]] {cons("CClassDecHead")}
%%% COMPLEMENTS %%%
"complements" {ClassType[[CaesarJCtx]] "&"}+
-> Complements[[CaesarJCtx]] {cons("Complements")}
%%%
"extends" ClassType[[CaesarJCtx]] "&" {ClassType[[CaesarJCtx]] "&"}+
-> Super[[CaesarJCtx]] {cons("SuperDec")}
"wraps" ClassType[[CaesarJCtx]]
-> Wraps[[CaesarJCtx]] {cons("Wraps")}
context-free syntax
%%% IMPLEMENTS DR %%%
"implements" {(ExtendLine1 | ExtendLine2) ","}+
-> InterfacesDr[[CaesarJCtx]] {cons("Implements")}
ClassType[[CaesarJCtx]] -> ExtendLine1 {cons("ImplementsDec")}
ClassType[[CaesarJCtx]] DrParams[[CaesarJCtx]]
-> ExtendLine2 { cons("ImplDrDec"), prefer}
%%%
context-free syntax
Mixin -> MethodMod[[CaesarJCtx]]
"mixin" -> Mixin {cons("Mixin")}
"deployed" -> ClassMod[[CaesarJCtx]] {cons("Deployed")}
A.1 GENERAL CAESARJ+ SPECIFICATION 91
context-free syntax
DeployDec[[CaesarJCtx]] -> ClassMemberDec[[CaesarJCtx]]
"deploy" Expr[[CaesarJCtx]] ";"-> DeployDec[[CaesarJCtx]] {cons("DeployDec")}
context-free syntax
PointcutDec[[CaesarJCtx]] ->ClassMemberDec[[CaesarJCtx]]
%%% ASPECTJ-LIKE POINTCUTS %%%
PointcutDecHead[[CaesarJCtx]] PointcutBody[[CaesarJCtx]]
-> PointcutDec[[CaesarJCtx]] {cons("PointcutDec")}
(Anno[[CaesarJCtx]] | Modifier[[CaesarJCtx]])* "pointcut"
Id[[CaesarJCtx]] "(" {FormalParam[[CaesarJCtx]] ","}* ")"
-> PointcutDecHead[[CaesarJCtx]] {cons("PointcutDecHead")}
":" PointcutExpr[[CaesarJCtx]] ";" -> PointcutBody[[CaesarJCtx]] {cons("PointcutBody")}
%%%
context-free syntax
"call" "(" MethodConstrPattern ")" -> PointcutExpr[[CaesarJCtx]] {cons("Call")}
"execution" "(" MethodConstrPattern ")" -> PointcutExpr[[CaesarJCtx]] {cons("Exec")}
%%%NAMED POINTCUT %%%
PointcutName[[CaesarJCtx]] "(" {TypeOrIdPattern ","}* ")"
-> PointcutExpr[[CaesarJCtx]] {cons("NamedPointcut")}
sorts PointcutName
context-free syntax
Id[[CaesarJCtx]] -> PointcutName[[CaesarJCtx]] {cons("PointcutName")}
ClassOrInterfaceType[[CaesarJCtx]] "." Id[[CaesarJCtx]]
-> PointcutName[[CaesarJCtx]] {cons("PointcutName")}
%%%
A.1 GENERAL CAESARJ+ SPECIFICATION 92
context-free syntax
"if" "(" Expr[[CaesarJCtx]] ")" -> PointcutExpr[[CaesarJCtx]] {cons("If")}
context-free syntax
"this" "(" TypeOrIdPattern")" -> PointcutExpr[[CaesarJCtx]] {cons("This")}
"target" "(" TypeOrIdPattern")" -> PointcutExpr[[CaesarJCtx]] {cons("Target")}
"args" "(" {TypeOrIdPattern ","}* ")" -> PointcutExpr[[CaesarJCtx]] {cons("Args")}
Type[[CaesarJCtx]] "." "cclass" -> ClassLiteral[[CaesarJCtx]] {cons("Class")}
"void" "." "cclass" -> ClassLiteral[[CaesarJCtx]] {cons("VoidClass")}
%%% ADVICE %%%
sorts AdviceDec AdviceMod
context-free syntax
AdviceDec[[CaesarJCtx]] -> ClassMemberDec[[CaesarJCtx]]
AdviceMod[[CaesarJCtx]]* AdviceSpec[[CaesarJCtx]] Throws[[CaesarJCtx]]? ":"
PointcutExpr[[CaesarJCtx]] MethodBody[[CaesarJCtx]]
-> AdviceDec[[CaesarJCtx]] {cons("AdviceDec")}
StrictFP[[CaesarJCtx]] -> AdviceMod[[CaesarJCtx]]
Anno[[CaesarJCtx]] -> AdviceMod[[CaesarJCtx]]
sorts AdviceSpec
context-free syntax
"before" "(" {FormalParam[[CaesarJCtx]] ","}* ")"
-> AdviceSpec[[CaesarJCtx]] {cons("Before")}
"after" "(" {FormalParam[[CaesarJCtx]] ","}* ")" ExitStatus?
-> AdviceSpec[[CaesarJCtx]] {cons("After")}
ResultType[[CaesarJCtx]] "around" "(" {FormalParam[[CaesarJCtx]] ","}* ")"
-> AdviceSpec[[CaesarJCtx]] {cons("Around")}
"returning" -> ExitStatus {cons("Returning")}
A.1 GENERAL CAESARJ+ SPECIFICATION 93
"returning" "(" ")" -> ExitStatus {cons("Returning")}
"returning" "(" FormalParam[[CaesarJCtx]] ")" -> ExitStatus {cons("Returning")}
"throwing" -> ExitStatus {cons("Throwing")}
"throwing" "(" ")" -> ExitStatus {cons("Throwing")}
"throwing" "(" FormalParam[[CaesarJCtx]] ")" -> ExitStatus {cons("Throwing")}
%%%
lexical syntax
"cclass" -> Keyword[[CaesarJCtx]]
"deployed" -> Keyword[[CaesarJCtx]]
"wraps" -> Keyword[[CaesarJCtx]]
"complements" -> Keyword[[CaesarJCtx]]
[\ \t \r \n] -> LAYOUT
lexical syntax
"cclass" -> Keyword[[CaesarJCtx]]
"deployed" -> Keyword[[CaesarJCtx]]
"wraps" -> Keyword[[CaesarJCtx]]
"complements" -> Keyword[[CaesarJCtx]]
[\ \t \r \n] -> LAYOUT
lexical restrictions
"cclass" -- [A-Za-z0-9 $]
"uses" -- [A-Za-z0-9 $]
"requires" -- [A-Za-z0-9 $]
"deployed" -- [A-Za-z0-9 $]
"complements" -- [A-Za-z0-9 $]
A.2 DESIGN RULES CONSTRUCT SDF 94
A.2 DESIGN RULES CONSTRUCT SDF
module DrDec[CaesarJCtx]
imports
languages/java/JavaMix[CaesarJCtx]
exports
sorts CaesarJCtx
context-free syntax
DrDecHead[[CaesarJCtx]] DrBody[[CaesarJCtx]]
-> DrDec[[CaesarJCtx]] { cons("DrDec") }
"{" DrMemberDec[[CaesarJCtx]]* "}" -> DrBody[[CaesarJCtx]] {cons("DrBody")}
"dr" Id[[CaesarJCtx]] DrParams[[CaesarJCtx]]
-> DrDecHead[[CaesarJCtx]] { cons("DrDecHead") }
"[" {Id[[CaesarJCtx]] ","}+ "]" -> DrParams[[CaesarJCtx]] {cons("DrParam")}
DrDec[[CaesarJCtx]] -> TypeDec[[CaesarJCtx]]
"dr" Id[[CaesarJCtx]] "=" DrReference[[CaesarJCtx]] DrParams[[CaesarJCtx]]
-> DrInstance[[CaesarJCtx]] { cons("DrInstance") }
Id[[CaesarJCtx]] -> DrReference[[CaesarJCtx]] { cons("DrReference") }
DrInstance[[CaesarJCtx]] -> TypeDec[[CaesarJCtx]]
context-free syntax
ConstantDec[[CaesarJCtx]] -> DrMemberDec[[CaesarJCtx]]
AbstractMethodDec[[CaesarJCtx]] -> DrMemberDec[[CaesarJCtx]]
ClassDec[[CaesarJCtx]] -> DrMemberDec[[CaesarJCtx]]
A.2 DESIGN RULES CONSTRUCT SDF 95
";" -> DrMemberDec[[CaesarJCtx]] {cons("Semicolon")}
lexical syntax
"dr" -> Keyword[[CaesarJCtx]]
lexical restrictions
"dr" -- [A-Za-z0-9 $]
BIBLIOGRAPHY
[1] abc: The AspectBench Compiler for AspectJ. http://aspectbench.org/.
[2] Ajdt. Getting started with ajdt. http://www.eclipse.org/ajdt/gettingstarted.php,
September, 2009.
[3] Jonathan Aldrich. Open modules: Modular reasoning about advice. In Proceed-
ings ECOOP 2005, volume 3586 of LNCS, pages 144–168, Glasgow, UK, July 2005.
Springer Verlag.
[4] Ivica Aracic, Vaidas Gasiunas, Mira Mezini, and Klaus Ostermann. An overview
of CaesarJ. Transactions on Aspect-Oriented Software Development, 3880:135–173,
2006.
[5] Aspectj.org. Aspectj. http://www.eclipse.org/aspectj/, October, 2009.
[6] Carliss Y. Baldwin and Kim B. Clark. Design Rules, Volume 1: The Power of
Modularity. MIT Press, Cambridge, MA, USA, 1999.
[7] Rodrigo Bonifacio and Paulo Borba. Modeling scenario variability as crosscutting
mechanisms. In AOSD ’09: Proceedings of the 8th ACM international conference on
Aspect-oriented software development, pages 125–136, New York, NY, USA, 2009.
ACM.
[8] Martin Bravenboer, Karl Trygve Kalleberg, Rob Vermaas, and Eelco Visser. Strat-
ego/XT 0.17. A language and toolset for program transformation. Science of Com-
puter Programming, 2008. Special issue on Experimental Systems and Tools.
[9] Martin Bravenboer, Karl Trygve Kalleberg, and Eelco Visser. Stratego/xt manual.
http://hydra.nixos.org/build/428755/download/1/manual/, December, 2009.
[10] Caesarj.org. Caesarj. http://www.caesarj.org, March, 2010.
96
BIBLIOGRAPHY 97
[11] Cristina Chavez, Alessandro Garcia, Uira Kulesza, Claudio Sant’Anna, and Car-
los Lucena. Crosscutting interfaces for aspect-oriented modeling. Journal of the
Brazilian Computer Society, 12(1):43–58, 2006.
[12] Curtis Clifton and Gary T. Leavens. Observers and assistants: A proposal for mod-
ular aspect-oriented reasoning. In Gary T. Leavens and Ron Cytron, editors, FOAL
2002 Proceedings: Foundations of Aspect-Oriented Languages Workshop at AOSD
2002, number 02-06 in Technical Reports, pages 33–44. Department of Computer
Science, Iowa State University, April 2002.
[13] Alberto Costa Neto, Marcio de Medeiros Ribeiro, Marcos Dosea, Rodrigo Bonifacio,
Paulo Borba, and Sergio Soares. Semantic dependencies and modularity of aspect-
oriented software. In ACoM ’07: Proceedings of the First International Workshop
on Assessment of Contemporary Modularization Techniques, page 11, Washington,
DC, USA, 2007. IEEE Computer Society.
[14] Remi Douence and Mario Sudholt. A model and a tool for event-based aspect-
oriented programming (EAOP). Technical report, Ecole des Mines de Nantes, De-
cember 2002.
[15] Eclipse.org. Eclipse. http://www.eclipse.org/, November, 2009.
[16] Ulrich W. Eisenecker and Krzysztof Czarnecki. Generative Programming: Methods,
Tools, and Applications. Addison-Wesley, 2000.
[17] Erik Ernst. Propagating class and method combination. In ECOOP ’99: Proceedings
of the 13th European Conference on Object-Oriented Programming, pages 67–91,
London, UK, 1999. Springer-Verlag.
[18] Matthias Felleisen. On the expressive power of programming languages. In Science
of Computer Programming, pages 134–151. Springer-Verlag, 1990.
[19] Victor Fernandes, Flavia Delicato, Paulo Pires, Uira Kulesza, and Thais Vascon-
celos Batista. Crossmda2: Uma abordagem baseada em modelos para gerencia de
evolucao de pointcuts. In SBCARS’09: Proceedings of 2nd Brazilian Symposium on
Components, Architecture and Software Reuse, oct 2009.
[20] Robert E. Filman and Daniel P. Friedman. Aspect-oriented programming is quan-
tification and obliviousness. In Aspect-Oriented Software Development, pages 21–35.
Addison-Wesley, 2005.
BIBLIOGRAPHY 98
[21] Erich Gamma., Richard Helm., Ralph Johnson Johnson, and John Vlissides. Design
patterns. Addison-Wesley Reading, MA, 1995.
[22] Vaidas Gasiunas, Mira Mezini, Jacques Noye, Angel Nunez, Nicolas Anquetil,
Ludger Fiege, Iris Groher, Christine Schwanninger, Markus Volter, Pablo Sanchez,
and Lidia Fuentes. Ample deliverable D3.3: Implementation platform and doc-
umentation for using it. Technical report, Ample project, November, 2009.
http://www.ample-project.net/.
[23] Phil Greenwood, Thiago T. Bartolomei, Eduardo Figueiredo, Marcos Dosea, Alessan-
dro F. Garcia, Nelio Cacho, Claudio Sant’Anna, Sergio Soares, Paulo Borba, Uira
Kulesza, and Awais Rashid. On the impact of aspectual decompositions on design
stability: An empirical study. In Erik Ernst, editor, ECOOP 2007 - Object-Oriented
Programming, 21st European Conference, Berlin, Germany, July 30 - August 3,
2007, Proceedings, volume 4609 of Lecture Notes in Computer Science, pages 176–
200. Springer, 2007.
[24] William G. Griswold, Kevin Sullivan, Yuanyuan Song, Macneil Shonle, Nishit
Tewari, Yuanfang Cai, and Hridesh Rajan. Modular software design with cross-
cutting interfaces. IEEE Software, 23(1):51–60, 2006.
[25] Jan Hannemann and Gregor Kiczales. Design pattern implementation in Java and
AspectJ. In Cindy Norris and Jr. James B. Fenwick, editors, Proceedings of the 17th
ACM conference on Object-oriented programming, systems, languages, and applica-
tions (OOPSLA-02), volume 37, 11 of ACM SIGPLAN Notices, pages 161–173, New
York, November 4–8 2002. ACM Press.
[26] Gorel Hedin. Generating language tools with jastadd. In 3rd Summer School on Gen-
erative and Transformational Techniques in Software Engineering (GTTSE), Braga,
Portugal, 2009.
[27] Jastadd.org. Jastadd. http://jastadd.org/, March, 2010.
[28] Java. Java o!cial website. http://java.sun.com/, March, 2009.
[29] A. Kellens, K. Gybels, J. Brichau, and K. Mens. A model-driven pointcut lan-
guage for more robust pointcuts. Proceedings of Software engineering Properties of
Languages for Aspect Technologies (SPLAT?06), Bonn, Germany, 2006.
BIBLIOGRAPHY 99
[30] A. Kellens, K. Mens, J. Brichau, and K. Gybels. Managing the evolution of aspect-
oriented software with model-based pointcuts. ECOOP 2006–Object-Oriented Pro-
gramming, pages 501–525, 2006.
[31] Jordan Kiang. Tetris midlet. http://kiang.org/jordan/software/tetrismidlet/.
[32] Gregor Kiczales, Erik Hilsdale, Jim Hugunin, Mik Kersten, Je"rey Palm, and
William Griswold. Getting started with AspectJ. Communications of the ACM,
44(10):59–65, October 2001.
[33] Gregor Kiczales, Erik Hilsdale, Jim Hugunin, Mik Kersten, Je"rey Palm, and
William G. Griswold. An overview of AspectJ. In J. Lindskov Knudsen, editor,
ECOOP 2001 — Object-Oriented Programming 15th European Conference, volume
2072 of Lecture Notes in Computer Science, pages 327–353. Springer-Verlag, Bu-
dapest, Hungary, June 2001.
[34] Gregor Kiczales, John Lamping, Anurag Menhdhekar, Chris Maeda, Cristina Lopes,
Jean-Marc Loingtier, and John Irwin. Aspect-oriented programming. In Mehmet
Aksit and Satoshi Matsuoka, editors, ECOOP ’97—Object-Oriented Programming
11th European Conference, Jyvaskyla, Finland, Proceedings, volume 1241 of Lecture
Notes in Computer Science, pages 220–242, New York, NY, June 1997. Springer-
Verlag.
[35] Gregor Kiczales and Mira Mezini. Aspect-oriented programming and modular rea-
soning. In Gruia-Catalin Roman, William G. Griswold, and Bashar Nuseibeh, ed-
itors, 27th International Conference on Software Engineering (ICSE 2005), 15-21
May 2005, St. Louis, Missouri, USA, pages 49–58. ACM, 2005.
[36] Christian Koppen and Maximilian Storzer. PCDi": Attacking the fragile pointcut
problem. In Kris Gybels, Stefan Hanenberg, Stephan Herrmann, and Jan Wloka,
editors, European Interactive Workshop on Aspects in Software (EIWAS), September
2004.
[37] Dimitri Van Landuyt, Steven Op de beeck, Eddy Truyen, and Wouter Joosen.
Domain-driven discovery of stable abstractions for pointcut interfaces. In Kevin J.
Sullivan, Ana Moreira, Christa Schwanninger, and Je" Gray, editors, Proceedings of
the 8th International Conference on Aspect-Oriented Software Development, AOSD
2009, Charlottesville, Virginia, USA, March 2-6, 2009, pages 75–86. ACM, 2009.
BIBLIOGRAPHY 100
[38] Cristina Videira Lopes and Sushil Krishna Bajracharya. Assessing aspect modular-
izations using design structure matrix and net option value. LNCS Transactions on
Aspect-Oriented Software Development I, 3880:1–35, 2006.
[39] Ole Lehrmann Madsen and Birger Moller-Pedersen. Virtual classes: a powerful mech-
anism in object-oriented programming. In OOPSLA ’89: Conference proceedings on
Object-oriented programming systems, languages and applications, pages 397–406,
New York, NY, USA, 1989. ACM.
[40] Bertrand Meyer. Object-Oriented Software Construction. Prentice Hall PTR, 2nd
edition, March 2000.
[41] Mira Mezini and Klaus Ostermann. Integrating independent components with on-
demand remodularization. In Proceedings of the 17th ACM SIGPLAN conference
on object-oriented programming, systems, languages, and applications, pages 52–67,
Seattle, Washington, USA, 2002. ACM.
[42] Mira Mezini and Klaus Ostermann. Conquering aspects with caesar. In Proceedings
of the 2nd international conference on Aspect-oriented software development, pages
90–99, Boston, Massachusetts, 2003. ACM.
[43] Alberto Costa Neto. Specifying Design Rules in Aspect-Oriented Systems. PhD
thesis, Informatics Center, University of Pernambuco, March 2010.
[44] Alberto Costa Neto, Arthur Marques, Rohit Gheyi, Paulo Borba, and Fernando Cas-
tor Filho. A design rule language for aspect-oriented programming. In XIII Brazilian
Symposium on Programming Languages - SBLP’09, Gramado-RS, Brazil, August
2009. To appear.
[45] Neil Ongkingco, Pavel Avgustinov, Julian Tibble, Laurie Hendren, Oege de Moor,
and Ganesh Sittampalam. Adding open modules to AspectJ. In Proceedings of the
5th International Conference on Aspect-Oriented Software Development (AOSD),
pages 39–50, March 2006.
[46] David Parnas. On the criteria to be used in decomposing systems into modules.
Communications of the Association for Computing Machinery, 15:1053–1058, 1972.
[47] Klaus Pohl, Gunter Bockle, and Frank van der Linden. Software Product Line Engi-
neering: Foundations, Principles and Techniques. Springer, Berlin Heidelberg New
York, 2005.
BIBLIOGRAPHY 101
[48] Carlos Eduardo Pontual. Caesarj+ source code.
http://cin.ufpe.br/~ceplc/caesarjp, April, 2010.
[49] Carlos Eduardo Pontual, Rodrigo Bonifacio, Henrique Rebelo, Marcio Ribeiro,
and Paulo Borba. Modularizing variabilities with CaesarJ collaboration inter-
faces. In 3rd Workshop on Assessment of Contemporary Modularization Techniques
(ACoM’09) at ACM SIGPLAN International Conference on Object-Oriented Pro-
gramming (OOPSLA’09), Orlando, USA, October 2009.
[50] Hridesh Rajan and Kevin J. Sullivan. Classpects: unifying aspect- and object-
oriented language design. In Gruia-Catalin Roman, William G. Griswold, and Bashar
Nuseibeh, editors, 27th International Conference on Software Engineering (ICSE
2005), 15-21 May 2005, St. Louis, Missouri, USA, pages 59–68. ACM, 2005.
[51] Marcio Ribeiro, Marcos Dosea, Rodrigo Bonifacio, Alberto Costa Neto, Paulo Borba,
and Sergio Soares. Analyzing class and crosscutting modularity with design structure
matrixes. In SBES ’07: Proceedings of 21 th Brazilian Symposium on Software
Engineering, pages 167–181, oct 2007.
[52] Leonardo Humberto Guimaraes Silva. Definicao de conjuntos de juncoes robustos
usando aspect-aware interfaces e aspectos anotadores. Master’s thesis, PUC/Minas,
June 2008.
[53] Sergio Soares, Eduardo Laureano, and Paulo Borba. Implementing distribution and
persistence aspects with aspectj. In OOPSLA ’02: Proceedings of the 17th ACM
SIGPLAN conference on Object-oriented programming, systems, languages, and ap-
plications, pages 174–190, New York, NY, USA, 2002. ACM.
[54] Friedrich Steimann. The paradoxical success of aspect-oriented programming. SIG-
PLAN Not., 41(10):481–497, 2006.
[55] Strategoxt.org. Stratego/xt. http://strategoxt.org/, February, 2010.
[56] Kevin Sullivan, William G. Griswold, Hridesh Rajan, Yuanyuan Song, Yuanfang
Cai, Macneil Shonle, and Nishit Tewari. Modular Aspect-Oriented design with XPIs.
ACM Transactions on Software Engineering and Methodology (TOSEM), 2009.
[57] Kevin Sullivan, William G. Griswold, Yuanyuan Song, Yuanfang Cai, Macneil
Shonle, Nishit Tewari, and Hridesh Rajan. Information hiding interfaces for aspect-
oriented design. In ESEC/FSE’05, pages 166–175, New York, NY, USA, 2005. ACM.
BIBLIOGRAPHY 102
[58] F. Van Der Linden, K. Schmid, and E. Rommes. Software product lines in action:
the best industrial practice in product line engineering. Springer-Verlag New York
Inc, 2007.
[59] Eelco Visser. A family of syntax definition formalisms. In M. G. J. van den
Brand et al., editors, ASF+SDF 1995. A Workshop on Generating Tools from Alge-
braic Specifications, pages 89–126. Technical Report P9504, Programming Research
Group, University of Amsterdam, May 1995.