<<

Aspect-Oriented Modelling of Framework Interfaces

Emil Dafinov

Master of Science

School of

McGill University Montreal,Quebec 2013-08-15

A thesis submitted to McGill University in partial fulfillment of the requirements of the degree of Master of Science Copyright 2013 Emil Dafinov. All rights reserved DEDICATION

This work is dedicated to three very important women in my life, all of whom are far more accomplished academics than I could ever hope to be. One is my sister, who embarked on the road to graduate studies, despite her claims that she would never do that. The second is my mother, who stressed the importance of education throughout my whole life. She set a shining example by starting her graduate studies after her eldest daughter had already done so and graduating before her. The last but not least person I would like to mention is the lovely lady who became a part of my life at the time of the writing of this thesis. Something tells me she would have have preferred a citation to a dedication.

ii ACKNOWLEDGEMENTS

First and foremost, I would like to thank my supervisor, Professor J¨org Kienzle, for his patience, guidance and continuous support throughout my graduate studies. I would also like to thank my colleagues at the McGill University : Wisam Al Abed, Omar Alam and Matthias Sch¨ottlefor putting up with my endless questions about the workings of Reusable Aspect Models (RAM), and everyone at the the Lab in general, for being a great friend and for making my M.Sc. experience so enjoyable.

iii ABSTRACT

Object-oriented software frameworks are a prominent way of software reuse, since they allow for increased developer productivity. However, frame- works often present the user with a steep learning curve before they can be leveraged efficiently. This issue is caused by the fact that frameworks offer rich feature sets, yet their documentation is often incomplete and informal. In the following thesis we propose a method that relies on feature diagrams in order to describe the features offered by a given framework and the relation- ships between them. The Reusable Aspect Models method is used in order to formally describe the individual features’ interfaces. The interfaces’ structural and behavioral properties are described using UML class diagrams and UML sequence diagrams, respectively. A complete model of the subset of a given framework’s interface that is relevant to a particular client application can be created by composing the models of the framework features used by that application. The individual feature models serve as a basis for generating tu- torials showcasing the framework’s capabilities, or even portions of the client application code necessary to interface with the framework. In order to test this method, a case study focusing on the Spring framework was conducted.

iv ABREG´ E´

Les frameworks orient´esobjet sont un moyen important de la r´eutilisation de code, car ils permettent d’am´eliorerla productivit´edes d´eveloppeurs. Cepen- dant, les frameworks pr´esentent souvent `al’utilisateur une courbe d’apprentissage abrupte avant qu’ils ne puissent ˆetreexploit´eesefficacement. La cause de ce probl`emeest le fait que les frameworks offrent des nombreuses fonctionnalit´es, mais leur documentation est souvent incompl`eteet informelle. Dans la th`ese suivante, nous proposons une m´ethode qui s’appuie sur les feature models afin de d´ecrireles caract´eristiques(oufeatures) offertes par un framework et les relations qu’ils existent entre eux. La m´ethode RAM est utilis´eepour d´ecrire formellement les interfaces des caract´eristiques individuelles. Les propri´et´es structurelles des interfaces sont d´efinies`al’aide des diagrammes de classes tandis que les propri´et´escomportementales des interfaces sont d´efinies`al’aide des diagrammes de s´equence.La m´ethode RAM permette aussi de composer les mod`elesindividuels afin de cr´eerun mod`elede la partie de l’interface du framework qui s’applique l’application cliente. Les mod`elespermettent de g´en´ererdes exemples pour l’utilisation du framework. Afin de tester nˆotre m´ethode, une ´etude de cas bas´eesur le framework Spring a ´et´er´ealis´ee.

v TABLE OF CONTENTS

DEDICATION ...... ii ACKNOWLEDGEMENTS ...... iii ABSTRACT ...... iv ABREG´ E...... ´ v LIST OF TABLES ...... viii LIST OF FIGURES ...... ix 1 Introduction ...... 1 1.1 Motivation ...... 1 1.2 Thesis Goals ...... 2 1.3 Thesis Contributions ...... 3 1.3.1 Novel method of formalizing framework interfaces . 3 1.3.2 Adapting the Reusable Aspect Models methodology to a new problem ...... 4 1.3.3 Case study: the Spring framework ...... 4 1.4 Thesis Outline ...... 4 2 Background ...... 6 2.1 Software Frameworks ...... 6 2.2 Reusable Aspect Models ...... 9 2.2.1 The Structural View ...... 10 2.2.2 Message Views ...... 12 2.2.3 Aspect Dependencies and Instantiation ...... 14 2.2.4 Aspect Weaving ...... 16 2.3 Feature Models ...... 22 3 Theoretical Contributions ...... 25 3.1 Capturing framework features with feature models . . . . . 25 3.2 Discovering framework features ...... 26 3.3 Modelling the interface of individual features ...... 30 3.4 Deriving feature relationships ...... 33 3.5 Generating the interface of a combination of features (tuto- rials) ...... 35

vi 4 The Spring Framework Case Study ...... 37 4.1 The Spring Framework ...... 37 4.2 Features Modelled ...... 38 4.2.1 Feature Model ...... 38 4.2.2 Individual Features ...... 39 4.2.3 Combining Spring Features ...... 58 4.3 Difficulties Encountered ...... 61 5 Related Work ...... 64 5.1 Understanding framework ...... 64 5.2 Aspect-Oriented Modelling ...... 67 5.3 Software Product Lines ...... 68 6 Conclusions and Future Work ...... 70 6.1 Observations ...... 72 6.2 Limitations of the TouchRAM tool ...... 73 6.3 Future Work ...... 74 6.4 Final Remarks ...... 75 LIST OF REFERENCES ...... 76

vii LIST OF TABLES Table page 3–1 Some Open Source projects using the Spring framework . . . . 27

viii LIST OF FIGURES Figure page 2–1 The Observer aspect ...... 11 2–2 The ZeroToMany aspect ...... 16 2–3 The Observer and ZeroToMany aspects woven together . . . . 17 2–4 The PushObserver aspect ...... 19 2–5 The PushObserver and Observer aspects woven together . . . 20 2–6 A sample feature model [13] ...... 23 3–1 E-Shop Feature Model [4] ...... 25 3–2 Sample Feature Model including the Observer and PushOb- server features [8] ...... 34 4–1 Spring Features ...... 38 4–2 Structural View of the BeanContainer aspect ...... 40 4–3 Message Views of the BeanContainer aspect ...... 41 4–4 Structural View of the XmlBeanFactory aspect ...... 42 4–5 Structural View of the BeanContainerConfigurable aspect . . . 43 4–6 BeanContainerConfigurable.setupContainer Message View Ref- erence ...... 44 4–7 BeanContainerConfigurable.readDefinitions Aspect Message View 44 4–8 Structural View of the InitializingBean aspect ...... 45 4–9 InitializingBean.initialize Aspect Message View ...... 47 4–10 InitializingBean.getBeanInstance Message View Reference . . . 47 4–11 Structural View of the BeanPostProcessor aspect ...... 48 4–12 BeanPostProcessor.setupContainer Message View Reference . . 48 4–13 BeanPostProcessor.getBeanInstance Message View Reference . 48

ix 4–14 BeanPostProcessor.addPostProcessor Aspect Message View . . 49 4–15 BeanPostProcessor.postProcessBefore Aspect Message View . 50 4–16 BeanPostProcessor.postProcessAfter Aspect Message View . . 51 4–17 Structural View of the EventPublisher aspect ...... 53 4–18 EventPublisher.setupApplicationContext Aspect Message View 54 4–19 EventPublisher.setupContainer Message View Reference . . . . 54 4–20 EventPublisher.publishEvent Aspect Message View ...... 55 4–21 Structural View of the Transaction aspect ...... 56 4–22 Transaction.transactionaExecution Aspect Message View . . . 57 4–23 Woven model for the {BeanContainer, XmlBeanFactory} fea- ture selection ...... 59 4–24 Woven model for the {BeanContainer, XmlBeanFactory, Initial- izingBean, BeanPostProcessor, BeanContainerConfigurable} feature selection - Structural View ...... 60 4–25 Woven model for the {BeanContainer, XmlBeanFactory, Initial- izingBean, BeanPostProcessor, BeanContainerConfigurable} feature selection - Message Views ...... 63

x Chapter 1 Introduction 1.1 Motivation

As the complexity of modern software increases, the need for relying on reusable software modules becomes greater than ever. In order to increase productivity, software developers need to be able to concentrate on develop- ing high-level features that are specific to the products they are working on. Having to spend time implementing lower-level application infrastructure is often tedious and time-consuming. Moreover, a lot of this low-level function- ality could be present in multiple applications. Good software engineering practices suggest that the code implementing this shared functionality should not be re-implemented for every client application. In order to address these issues, developers need to rely on software frameworks. A software framework provides code that can be reused by client applications in order to solve a particular problem. Although this definition sounds very similar to the defi- nition of software libraries, there are several important distinctions that exist between the two. First and foremost, an object-oriented software library con- tains classes and methods that the client code would instantiate and call in order to achieve its (the client’s) goals. Frameworks on the other hand are based on the principle of (IoC): the client is responsible for writing application specific code that is to be called by the framework code at runtime. Thus, it is the framework code and not the user application that defines the control flow of the resulting application. In order to achieve this, the application-specific client code must conform to a rigid API defined by the framework. In short, in the final application the framework provides a

1 backbone, whose functionality can be specialized in order to fit the need of each individual client application. A framework usually aims to provide some default functionality out of the box, but it expects the client code to extend and override it in order to suit its needs. There exist multiple examples of popular software frameworks in different problem domains. These include Swing and SWT (GUI development for Java applications), ASP.NET, Google Web Toolkit, Tapestry and Django (web ap- plication development) and Apache Hadoop (distributed applications dealing with big data), just to name a few. Even though software frameworks provide significant advantages in terms of code reusability, they present a different set of challenges to the developer. One major difficulty is the steep learning curve: in order to use a framework effectively, a developer must have a good under- standing of the abstractions it provides. A framework often provides various features and each feature could require the use of more than one class defined by the framework. As a result the complete framework API could be very complex. Matters are further complicated as the software framework becomes more mature: new functionality becomes available, and consequently the API becomes even more complex. Consequently, selecting only the part of the API that is relevant to the problem the particular client application is attempting to solve is not a trivial task. 1.2 Thesis Goals

The goal of this thesis is to describe an approach that can facilitate the usage of software frameworks by reducing the initial learning curve. Feature modelling is used in order to produce a more formal specification of the set of features that are provided by a given software framework. We define a creature to be any prominent characteristic of the framework that is useful to the end user. A feature model allows the developer of the client application to

2 have a high-level view of all the functionality provided. This in turn permits the user to select a subset of the features provided by the framework that are required for solving their particular problem. Once this selection is made, the user is presented with a subset of the framework API that is relevant to the selected features. Additionally, we are interested in generating tutorials, that is, simple usage scenarios that would serve as an example of how the particular subset of the framework API should be used in the client application in order to implement the selected features. This decision is motivated by the fact that multiple sources have pointed out that learning by examples is highly effective in general [10] and in particular it applies very well to the area of reducing the learning curve of a software framework[37, 31]. Taking the idea even further, being able to generate source code from a model of the framework’s interface could be useful for purposes other than documentation. It would also allow a developer using the modelled framework to automatically generate any boilerplate code required to interface with the framework, allowing the programmer to focus on application specific tasks. 1.3 Thesis Contributions

1.3.1 Novel method of formalizing framework interfaces

We propose a method for creating a formal model of the features offered by a given software framework. The model takes into account the relationships that exist between these features. It is also able to express the interfaces of the individual features. if needed, the individual feature models can be combined in order to produce a model of the entire interface of a valid feature selection. Our method allows the users of a software framework to quickly familiarize themselves with the functionality offered by the framework. Providing the users with a model of the interface of a given feature selection allows them

3 to only focus on the part of the framework interface that is relevant to their needs. 1.3.2 Adapting the Reusable Aspect Models methodology to a new problem

The Reusable Aspect Models method has been used in order to describe the interface of a single feature or a set of features offered by a given software framework. This is a different from the standard way the RAM method is used: the typical application of RAM is to describe the behavior of a software system, since the main focus of these models is to describe the messages to and from the client application. Interactions that only involve the internal workings of the modelled framework could be included for documentation reasons, but that is not mandatory. 1.3.3 Case study: the Spring framework

We have demonstrated the utility of our method by carrying out a case study based on the widely used Spring software framework. A small subset of the framework’s features was selected, due to the fact that the framework is very mature and feature-rich. Modelling Spring in its entirety would not have been feasible under the time constraints. The features included in the case study relate to the framework’s primary goal of providing to client application. Also, we have tried to select features that de- pend on each other, therefore allowing us to better demonstrate the strengths of our modelling approach. 1.4 Thesis Outline

The rest of this thesis is organized as follows: • Chapter 2 discusses the background information that will be necessary for our subsequent discussion. It begins with a brief discussion of soft- ware frameworks and the ways they are used. Following this section is

4 a description of RAM, an Aspect-Oriented modelling approach devel- oped in the Software Engineering Lab at McGill University. This was the method chosen for the formal description of the API of the various features of a given software framework. The final part of the chapter discusses feature diagrams, in particular their utility in describing the features provided by a given software framework and the dependencies that exist between them. • Chapter 3 discusses the specifics of our method of documenting software framework features. • Chapter 4 presents information regarding the case study that was con- ducted in order to demonstrate our method. The study concentrates on the Spring framework. • Chapter 5 presents a comparison between our approach to framework feature documentation and other works in the same field. Existing al- ternatives to the RAM modelling methodology are also presented here. • Chapter 6 contains some final remarks, as well as possible directions for future research.

5 Chapter 2 Background 2.1 Software Frameworks

Object-oriented frameworks represent a common unit of software reuse. A framework constitutes “the skeleton of an application that can be customized by an application developer”[26]. The main goal of a framework is to allow software developers to quickly implement a custom application within a well- defined problem domain. This is achieved by reusing a partially implemented architecture that has been proven effective within the domain in question. It allows the developer to concentrate on writing code that is specific to their custom application without needing to re-implement infrastructure that is common between a large number of software applications. Much like an object-oriented software library, an object-oriented frame- work consists of code that can be reused by a client application. The main difference between software frameworks and software libraries stems from the fact that a library usually provides a set of components to the user. Those components can be instantiated and called by the client code at runtime. Typically, only one class of the library needs to be used in order to perform a specific task: for example a Java programmer needing to perform a given mathematical function would simply call the corresponding method of the java.lang.Math class. Frameworks on the other hand operate on the principle of IoC, also known as the “Hollywood Principle”[34] or “Don’t call us, we’ll call you”. The essence of the idea is that the client code is expected to implement custom compo- nents that can be called by the framework code at runtime. This is made

6 possible by having these components adhere to strict interfaces defined by the framework. Consequently, the application-specific components would need to extend abstract classes defined in the framework. Additionally, using a frame- work feature often requires a more complex interaction than a method call on a single component (for examples, refer to Chapter 4). The nature of these interactions is specified by the framework, since it determines the control flow of the final application. This justifies the term Inversion of Control, since the client code, which normally is in charge of specifying the control flow, is relieved of this responsibility. An object-oriented framework is a partially implemented . It offers little to no default functionality and relies on the client to provide the specialized components implementing the application-specific functionality they need. Therefore frameworks are by definition extensible. The parts of a software framework that are meant to be extended by the framework user are often referred to as “hot spots”[15]. Since the goal of a framework is to be highly reusable, it is important to choose the hot spots so that it would make the framework applicable to different applications within the domain. The parts of the framework that are not meant to be modified by the user are known as “frozen spots” and they represent the part of the framework functionality that the end user utilizes “as is”. In general, as pointed out in [26], software frameworks occupy an interesting position among the existing software reuse techniques. They are at a level of abstraction that is higher than that of software libraries (which are collections of fully implemented components). As such, frameworks benefit from additional flexibility. On the other hand,due to the partially implemented application infrastructure they provide, frameworks are more concrete than abstract architecture design descriptions. Consequently, they are more easily reusable.

7 The advantage of software reuse in this case is twofold: first, software engineers save development time by not having to re-implement existing func- tionality. Additionally, there would be gains in time due not having to worry about testing the functionality provided by the framework, since that is the responsibility of the framework developer. Therefore, provided the framework developer has put in the necessary effort in testing and debugging, the client application benefits from added robustness. Another advantage of software frameworks is uniformity: as pointed out in [26], applications built using the same framework share a lot of similarities. Therefore, the learning curve for a new developer is reduced, provided that she is already familiar with the underlying framework. The benefits outlined above do come with a cost. It has been noted that a developer might need 6-12 months in order to learn to use a new framework efficiently [15]. This is due to the fact that a good knowledge of a frame- work’s hot spots is necessary in order to customize it properly. Additional complications arise from the fact that very often a certain familiarity with the framework is required in order to determine its suitability for a particular application. Thus the selection of the proper framework to use could be a time consuming task. Finally, from the point of view of debugging, difficulties might arise from the fact that the client application is not responsible for the control flow. Therefore, while debugging, when the framework code is being executed, one of two things can happen: either the client has no access to the source code (if the framework is closed-source) or if they do, this code is unfamiliar to them. There are significant costs associated with software framework develop- ment as well. Most importantly, designing a framework takes a lot of effort and requires in-depth knowledge of the problem domain. Selecting the right

8 hot spots is crucial, since they represent the of the framework and determine the level of flexibility that the end user will have. Note that it is important for the framework to maintain a stable API throughout its evolu- tion. Otherwise, client applications relying on an older version of the interface would need refactoring. A good example of this problem is the Tapestry , that was known for lack of backwards compatibility between major releases, especially between versions 4 and 5 [6]. Finally, software frameworks suffer from the most common drawback of software reuse techniques.That is the fact that the client software depends on the framework developers for the implementation of improvements and bug- fixes to the framework. It is rare for client application developers to have the access to the source code and/or the necessary know-how in order to efficiently implement improvements a framework that has been developed by a third party. 2.2 Reusable Aspect Models

The Reusable Aspect Models approach was used for the purposes of mod- elling the structure and behavior of individual features in a given software framework. RAM is a Multi-View Aspect-Oriented approach that allows for creation of scalable software models. A detailed description of RAM can be found in [30]. Being an Aspect-Oriented approach, RAM aims to modular- ize crosscutting software concerns. An aspect, which could be any concern or functionality, is the primary unit of reusability in the RAM modelling ap- proach. A RAM model focuses on describing the structure and behavior of a single aspect. Such a model consists of three views: structural view, state view and message view. The ones most relevant to the discussion at hand are the Structural View and the Message View. Both these views are described in

9 a notation that closely resembles standard UML. Detailed information about them is presented below. 2.2.1 The Structural View

The Structural View is represented by a UML class diagram [32]. It describes the classes relevant to the aspect being modelled, the associations that exist between them, as well as their respective interfaces. The visibility of each method/attribute in a class’ interface is indicated by the symbol preceding it. Public methods, i.e. ones that are visible from outside the aspect package are marked with a “+” sign. Private methods are marked with a “-” sign. The “˜” sign indicates that its corresponding method is aspect-private. These methods are only visible to other classes within the aspect package. The public interface of an aspect is the set of all the public methods defined in all classes in the structural views. This allows a RAM model to expose only the interface relevant to using the aspect to the outside world and omit any unnecessary implementation details. This is in line with the information hiding principle, as outlined in [33]. For an example, refer to the Structural View in figure 2–1. On this figure we have an aspect model describing a variation of the Observer design pattern. Note that some of the methods and classes in the figure have a vertical bar (“|”) in front of their name. Those are known as partial classes/methods and they are described in more detail in section 2.2.3. The version of Observer in figure 2–1 is similar to the one described in

[18]. However, note that the |Observer object in our version is responsi- ble for subscribing/unsubscribing to a particular |Subject object when its startObserving() or stopObserving() methods are called. This differs from the Observer pattern described [18] where the Subject has the responsibility of attaching Observer instances to itself.

10 aspect Observer depends on ZeroToMany |Subject<|modify<|update>> structural view |Observer<|update> |Subject mySubject |Observer  0..1  ~ Set<|Observer> getObservers() + startObserving(|Subject) + * |modify(..) + stopObserving() ~ |update(..) Instantiations: ZeroToMany: |Data → |Subject; |Associated → |Observer; getAssociated → getObservers

message view startObserving caller: Caller target: |Observer s: |Subject startObserving(s) add(target)

message view stopObserving caller: Caller target: |Observer mySubject: |Subject stopObserving() remove(target)

message view |modify affected by notification message view notification Advice

caller: Caller target: |Subject caller: Caller target: |Subject |modify(..) |modify(..)

*  * observers := getObservers() Pointcut loop [o within observers] o: |Observer |update(..)

state view |Subject getObservers |m create create

Any Modifyable

state view |Observer create startObserving |update

Uninterested Observing

stopObserving

Figure 2–1: The Observer aspect

The public interface of the aspect described in figure 2–1 consist of the three public methods described in the Structural View: startObserving( |Subject s), stopObserving() of the |Observer class and the |modify() method of the |Subject class. The startObserving(|Subject s) and stopObserving() methods, as we already described, serve to attach/detach a given |Observer to/from a particular |Subject instance. When attached, an |Observer instance is notified when the state of the corresponding |Subject

11 changes. The |modify() method of the |Subject class represents an opera- tion that modifies the state of a |Subject in some way and needs to trigger the updates for all |Observer instances attached to that |Subject. Being able to invoke these three operations enables the client to make use of the Ob- server pattern functionality. The method getObservers() of the |Subject class (which serves to return the set of all |Observer instances attached to a particular |Subject ) and |update() method of the |Observer class (used to notify the |Observer that the |Subject has been updated) are marked as aspect private (“˜”) and are therefore not part of the aspect’s public interface. This is reasonable, since those two methods do not represent operations that need to be called by the user. Rather, they are helper methods that are called by the public methods of the aspect in order to implement the desired func- tionality. Consequently, the information hiding principle dictates that these methods are not be visible to the user. 2.2.2 Message Views

Just as the Structural View notation is based on the standard UML class diagram, the Message Views resemble UML sequence diagrams [32]. For a detailed explanation of the Message View notation used in RAM, please re- fer to [36]. Each Message View is identified by an unique name and serves to describe the message exchanges between entities defined in the Structural View when a method from the aspect interface is invoked. Therefore, we have at most one Message View per method of the aspect’s public interface. The public methods whose execution does not involve a message exchange between the classes defined in the Structural View do not need a Message View. As explained in [36], there are several different types of Message Views. Normal message views are the simplest type and each one of them “highlights the

12 interchange of messages that is executed when the described method is in- voked.” Going back to our Observer pattern example described in figure 2–1, the examples of Normal Message Views are the ones labeled “startObserving”, “stopObserving” and “|modify”. Notice how the “|modify” Message View is left empty. This is done because the method call does not involve any further message interaction on the level of abstraction of the current aspect. In other words, any message exchange that would take place during the execution of this method would be described in another aspect (that has a dependency on the Observer) and then mapped to |modify(). However it does include information about which Aspect Message Views the current Message View is being affected by. The “affected by” directives represent information relevant to the aspect weaver. They are discussed in more detail in section 2.2.4, but in general they contain information about other Message Views that modify the behavior of the current one. The Message Views that define “behavior that extends other message views” [36] are known as Aspect Message Views. They consist of two diagrams, labeled Pointcut and Advice. The Pointcut diagram describes a join point, i.e. “well-defined points in the execution of the program” [14] described by the original Message View. The final Message View type is “Message View Reference”. It designates a Message View that is inherited by an aspect that the current aspect depends on. Aspect dependencies are discussed in detail in section 2.2.3. Message View References are necessary in the case when an aspect needs to modify the behavior described in one of its dependent aspects. In theory, RAM allows for any interaction that can be expressed in a se- quence diagram to be used as a Pointcut. Unfortunately, in the current version

13 of the TouchRAM software only method calls can be used to describe a Point- cut. In the future, the tool will be extended in order to allow more complex interactions to be matched. As for the “Advice” diagram, it represents the changes that are to be made to the original behavior described in the Pointcut. In the Observer pattern example, the Message View labeled “notification” is an Aspect Message View that describes a behavior to be applied when the

|modify() method (the one described in the pointcut) is invoked. In both the “Pointcut” and “Advice” diagrams, the box containing the “*” symbol represents the message exchange during the original execution of the invoked method ( in this case, |modify() ). In the “Advice” diagram, the original execution box allows to specify if the new behavior is added before or after the behavior described by the original method. 2.2.3 Aspect Dependencies and Instantiation

One of the major goals of RAM is to address the issue of reusability and scalability of complex Aspect-Oriented models. This is achieved by modelling each individual concern separately and allowing more complex aspect models to reuse functionality already described in existing models. Thus, the com- plex models do not need to re-implement functionality that has already been described in other existing models. As a result the size of each individual aspect model is kept relatively small. The final model of a software design is therefore a composition of the models of the individual aspects. Composing the individual aspect models is the responsibility of the RAM Aspect Weaver. In order to weave aspects together and obtain the final model, it is neces- sary to have a method for explicitly describing aspect dependencies. In RAM, if an aspect A needs to reuse the functionality described in an aspect B, A (the “higher-level” aspect ) needs to instantiate B (the lower-level aspect). This means that a mapping must be established between classes and methods

14 of the two aspects. The mapped elements would be later composed by the weaver. Details on the weaving process can be found in section 2.2.4 As stated in [7] we have two types of aspect instantiations. In case the “depends” instantiation is used, an aspect A is said to “depend on” aspect B. This means that A internally reuses functionality defined in B in order to provide whatever functionality A needs to provide. Therefore, the aspect A represents a higher level of abstraction. On the other hand, if the “extend” instantiation is used, and aspect B “extends” aspect A, that would imply that B provides all the functionality of A plus some additional functionality. The two aspects would thus be at the same level of abstraction. Consequently, the interface of B would be a superset of the interface of A. Which elements must be mapped when an aspect dependency is instanti- ated depends on the type of the instantiation. First, in the case of a “depends” instantiation, all of the so called Incomplete or Partial classes or methods de- fined in the lower-level aspect must be mapped. Those classes/methods are the ones whose name is preceded by a vertical bar (“|”) in the Structural View. These partial classes/methods are dubbed the Mandatory Instantiation Parameters of the aspect model they are defined in. Non-partial classes can be mapped as well, as the modeller sees appropriate, but this is not obligatory. In the woven model, all public elements of the lower-level model that are not mapped to elements of the higher level model have their visibility reduced to aspect-private. That way, the details of the lower-level aspect are hidden from the user of the higher-level aspect. The case of the “extends” instantiation is simpler: since the base aspect and the extending aspect are on the same level of abstraction, all elements of the base aspect are assumed to also be present in the extending aspect. Their visibility is not modified as a result of the weaving process.

15 aspect ZeroToMany |Data structural view |Associated |Associated |Data Set  int size ~ Set create() + add(|Associated a) 1 |Associated ~ add(|Associated ) + remove(|Associated a) mySet 0..* + Set<|Associated> getAssociated() ~ boolean remove(|Associated) + boolean contains(|Associated) ~ boolean contains(|Associated) ~ delete() Implementation: Set<|Associated>: any java.util.Set<|Associated> state view |Data Advice Default Instantiation: state view Set<|Associated> AddAllowed → * Pointcut RemoveAllowed → * add Any → * add/size++ create/size:=0 AddAllowed AddAllowed contains Existing RemoveAllowed remove contains destroy remove[size>0] Any RemoveAllowed Any getAssociated /size--

message view initializeAssociation Pointcut caller: Advice Caller caller: Caller new := create(..) new: new := create(..) new: |Data |Data * mySet := create() * mySet: Set<|Associated>

message view create affected by initializeAssociation

message view add caller: Caller target: |Data mySet: Set<|Associated> add(a) add(a)

message view remove caller: Caller target: |Data mySet: remove(a) Set<|Associated> ignore := remove(a)

message view contains caller: Caller target: |Data mySet: result := contains(a) Set<|Associated> result := contains(a)

message view cleanupAssociation Advice caller: Caller target: |Data mySeq: caller: Caller target: |Data Sequence<|Associated> destroy(..) destroy(..) * * destroy() Pointcut

message view destroy affected by cleanupAssociation

Figure 2–2: The ZeroToMany aspect

2.2.4 Aspect Weaving

In this section, we examine some specifics of how aspect weaving is done. The process is slightly different depending on the relationship between the aspects that are being woven together. As we’ve seen in section 2.2.3, aspect

16 Figure 2–3: The Observer and ZeroToMany aspects woven together dependencies are indicated by the use of either a “depends on” or an “extends” instantiation. To start, let us take a look at figure 2–1 again. The dependencies of each aspect are listed at the top, next to its name. The Observer aspect has a single dependency, the ZeroToMany aspect, and the instantiation type is “depends on”. The ZeroToMany aspect describes a simple Zero-To-Many association between an |Data and zero or more instances of |Associated. The model of this aspect can be found in figure 2–2. On figure 2–3, we have an example of what the Structural View of the Observer aspect would look like after its dependency, ZeroToMany, has been woven in. Let us examine the effects of the weaving from the point of view

17 of the Structural View. First, we go through the instantiation mappings. If a class from the underlying aspect is mapped to a class of the current aspect, in the woven model the class pointed to by the mapping would have all the methods and attributes of the class from the underlying aspect. The names of these methods/attributes can differ from the ones in the lower-level aspect, but if that is the case, this must be specified in the instantiation mapping.

In our example, we see that |Data of ZeroToMany is mapped to |Subject in Observer. As a result, in the woven model we see that |Subject has obtained the contains(), create(), destroy(), add() and remove() methods of ZeroToMany. As mentioned previously, those methods have their visibility reduced to aspect private in the woven model. The getAssociated() method is also present, but it is called getObservers() at the level of abstraction of the Observer model as specified in the instantiation mapping. The mapping allows the getAssociated() method to be re-exposed on the higher level of abstraction. When the “depends on” instantiation is used , the Message View weaving process is simplified by the fact that the Message Views of the dependent as- pect are not available to the main aspect. Therefore, the main aspect cannot modify the Message Views of the dependent aspect through Message View References. One important detail to mention is the “affected by” directive. It serves to indicate that a message view is affected by one or more Aspect Mes- sage Views. Therefore, during the weaving process, every time the interaction described in the Pointcut of the affecting message view occurs in the affected Message View, this interaction would be replaced by the interaction described in the Advice of the affecting aspect. In case a message view is affected by more than one Aspect Message View, the weaver applies the changes from each affecting Aspect Message View in the order in which they appear in the

18 Figure 2–4: The PushObserver aspect

“affected by” list. That is to say, if we have a message view such as “A affected by B, C, D”, every occurrence of B’s Pointcut in A would be replaced by B’s advice. Then, the same process would be repeated for C, and finally, for D. An example can be found in the Observer aspect: the |modify Message View is being affected by the notification Message View. To understand how the “extends” instantiation works, we present the PushObserver aspect presented in figure 2–4. It extends the Observer aspect and therefore offers all the notification functionality of Observer. However, the PushObserver aspect specifies additional behavior on top of the one provided by its parent aspect.

The Observer aspect only describes that the|Subject class invokes the |update() method on every attached |Observer instance when the |modify() method of the |Subject instance is invoked. The aspect does not specify what arguments (if any) are passed to the |update() method. In fact, the two dots that appear in the method’s signature in figure 2–1 signify that the parame- ters of the method are not known on this level of abstraction and they depend on the method that will be mapped to |update(..) in a higher-level aspect.

19 Therefore, the aspect as a whole does not specify how the |Observer instances get the information they’re interested in, they only receive a notification that new information is available. In PushObserver an “extends” instantiation of Observer is used. As a result, the Structural View of PushObserver contains all elements that are present in the Structural View of the Observer aspect. In order to avoid duplication, the model elements that are already described in the parent aspect are not explicitly shown in PushObserver. However, this does not imply that the elements of the Observer aspect that are not shown are not accessible at the level of abstraction of the PushObserver aspect. If PushObserver and Observer were to be woven together, those elements would appear without having their visibility reduced. The model would look as shown on figure 2–5.

Figure 2–5: The PushObserver and Observer aspects woven together

20 The new functionality described by the PushObserver aspect is that the

|Subject instance passes the desired information to each Observer instance when |update() is invoked. This is achieved through the addition of the |getData() method to the |Subject class’ signature. Since |getData is a method that is designed to only be invoked by the |Subject itself, it is marked as aspect private. This method returns an object of type |Data that contains all data that the |Observer instances need to receive upon notification. As we can see from the “notification” Aspect Message View of PushObserver, the notification process proceeds in a fashion similar to the one described in the “notification” Aspect Message View of the Observer aspect. The difference is that now the |Subject instance invokes the |getData() method in order to retrieve a reference to an object containing the data required by the |Observer instances and passes that object to each notified |Observer as a parameter to the |update() method. Since PushObserver extends Observer, the PushObserver aspect can mod- ify the Message Views described in its parent aspect. For example, PushOb- server.notification overrides Observer.notification. As it is shown in figure 2–5, in the woven model there is only one Message View called notification and it it the one coming from the PushObserver aspect. Other than overriding, an extending aspect can modify Message Views from underlying aspects by ap- plying new Aspect Message Views to the Message View References that it can access. This is done with the “affected by” directive, in the same fashion as if the affecting and the affected message views were in the same aspect. The only difference is that the Aspect Message View specified by the extending model is going to be woven in after any affecting Message Views described in the parent model. To illustrate this, assume we have an aspect called Base that defines an Aspect Message View B and a Normal Message view A affected by

21 B. Then, we could have an aspect called Extending that extends Base and de- fines an Aspect Message View C and a Message View Reference A affected by C. When the two aspects are woven together, the resulting model will contain a single Normal Message View A affected by B, C. Note that the PushObserver aspect does not contain any instantiation mappings, as was the case with the Observer aspect. This is due to the fact that when an “extends” instantiation is used, all elements from the Structural and Message Views of the extending aspect that have the same name as the corresponding elements from the parent model are assumed to refer to the same entities. Therefore no explicit mapping is necessary. 2.3 Feature Models

Software Product Lines are defined by The Carnegie Mellon Software Engineering Institute as a set of software systems that “share a common, managed set of features satisfying the specific needs of a particular market segment or mission and that are developed from a common set of core assets in a prescribed way”[24]. It is a way to describe a product family in a way that emphasizes the common elements between the individual products, as seen by the end user. In fact every individual system implements a subsets of the Software Product Line (SPL)’s features that fits the requirements of the particular system. It is easy to see the parallel between SPLs and software frameworks, since frameworks often offer a large set of features, only a subset of which is required by a given client application. Feature models are considered to be the de-facto standard way of describing the feature set of a SPL [19] and therefore they are the natural choice for describing the features of a software framework and the dependencies that exist between them. It is important that we define what constitutes a feature. In [28] a fea- ture is said to be a “prominent or distinctive user-visible aspect, quality, or

22 Figure 2–6: A sample feature model [13] characteristic of a software system”. Therefore, we can define a feature as a prominent characteristic of a given system that is of some value to the end user. A feature model is thus a visual representation of the features that are offered by a particular SPL together with the relationships that exist between them. These relationships can be expressed as Boolean logic statements and generally define what features can or cannot be selected if a given other fea- ture is selected. A feature model is described by a feature diagram and a set of composition rules. [28] describes a feature diagram as an and/or tree with each node representing one feature. In order to select a “valid” subset of the feature set, a user traverses the tree starting at the root and selecting child features at every node according to a given set of rules. Listed below are the selection rules for each feature type that can be used in a feature diagram: • Root Feature: Must be selected. In figure 2–6 the root feature is “car” • Optional Features: It can be selected or not, according to the user’s preference. Denoted by a small circle right above the feature name. In figure 2–6, “keyless entry” and “power lock” are optional features. • Alternative Features: a set of features that share a common parent node and are denoted by an arc drawn through all alternatives. Also known

23 as a xor-group[13]. The notation implies that one and only one of the alternatives must be selected. in figure 2–6, the features “manual” and “automatic” constitute a xor-group. Note that our example diagram features a second variation of the arc notation: the one drawn across the “electric” and “gas” features. This notation designates a feature group with cardinality. This is a notation used in the context of cardinality feature models [13] and is not relevant to our current discussion. • Mandatory Features: They must be selected if their parent is selected. In [28] all features with no special notation are considered mandatory. [13] denotes mandatory features explicitly using a notation similar to that of optional features but with the circle filled out. In figure 2–6 “body”, “engine” and “gear” are all mandatory. In addition to the rules associated with the individual feature types, a set of compositional rules could exist in addition to the the tree diagram. These rules can specify extra constraints between features that are represented by non-adjacent nodes in the tree diagram. An example of such a rule is “keyless entry → power locks” found in figure 2–6. The arrow represents the boolean logic symbol “implies”. Therefore, the rule states that if the optional feature “keyless entry” is selected, then the optional feature “power locks” must also be selected.

24 Chapter 3 Theoretical Contributions 3.1 Capturing framework features with feature models

Feature models are a common way of representing the available features in a SPL. The model allows the user to select a “valid” subsection of the features available in the SPL and thus configure a valid instantiation of the product line. A framework, just like a SPL, offers a large set of features, of which the client software often requires only a given subset. Moreover, there are certain restrictions between which features can be used together and which ones are mutually exclusive. For that reason, feature models can easily be applied to software frameworks.

Figure 3–1: E-Shop Feature Model [4]

Having all feature dependencies already described in a feature model is one of the main advantages to using SPL. This allows a developers implementing a particular product within the domain space described by the SPL to leverage

25 the knowledge of the domain experts that designed the product line. For example, consider the feature model for a simple online e-store presented in figure 3–1. The model has a single composition rule : “Credit Card implies High” (see section 2.3). This constraint could be obvious for a domain expert, but a software engineer implementing a particular e-store website might not be aware of it. An analogous situation exists in the case of software frameworks: often framework features require the use of certain components defined by the frameworks. However, often there are extra constraints to the components one must use, other than having to implement the right interfaces. For example, very often some of the features provided by the framework represent alternative solutions to the same problem. Therefore, it does not make sense to select more than one of them. As explained in section 2.3, this can be easily expressed in a feature diagram by means of a xor-group. 3.2 Discovering framework features

For the purposes of the case study presented in chapter 4 the individual framework features that are modelled were discovered chiefly through examin- ing the available online documentation for the Spring framework [5]. Ideally, a developer that uses a framework should not have to go through this step. The feature diagram should be part of the standard documentation of the frame- work. This would provide the application developer with a more high-level view of the available framework capabilities than the one that can be provided by the API documentation. An empirical method for discovering framework features was also at- tempted as part of this thesis. For this purpose, a set of Open Source projects that have dependencies on the Spring framework were subjected to static source-code analysis. This was done in hope to discover additional features, as well as to determine which Spring features are commonly used by client

26 Project Homepage Shopizer www.shopizer.com Powerstone powerstone.sourceforge.net Tudu Lists www.julien-dubois.com/tudu-lists.htm Alfresco Content Management www.alfresco.com Spring Side www.springside.org.cn Plazma plazma.sourceforge.net Express agileexpress.sourceforge.net ZK Framework Sample sourceforge.net/projects/zksample2 Spring Rich Client spring-rich-c.sourceforge.net Broadleaf Commerce www.broadleafcommerce.org OpenERP sourceforge.net/projects/theopenerp HISPACTA hispacta.sourceforge.net Luigi Open Search Engine sourceforge.net/projects/cw-search JOSSO www.josso.org HSE hse.sourceforge.net Java Small Business Platform jsbp.sourceforge.net jrecruiter code.google.com/p/jrecruiter

Table 3–1: Some Open Source projects using the Spring framework applications. The projects whose source code was analyzed are listed in table 3–1. The source code for each individual project was analyzed using the Under- stand static analysis tool [3]. Understand extracts information about a given set of entities (such as classes, methods, variables) in a given set of source code

files. The tool stores the source code metrics in a .udb file. This information can be later manipulated using the Understand API. The API is available for several programming languages. For the purposes of this case study, the API for the Python programming language [2] was used. The main goal of the analysis is to find features by discovering sets of Spring-defined types that are often used together. We consider types to be used together if within the scope of a single method of the client code there is at least one variable of each type in the set that is manipulated. A vari- able is manipulated if it is instantiated, if it is passed as a parameter to a

27 method or if one of its methods is invoked. The assumption is that if a set of classes/interfaces defined by the Spring framework is used together often, they are most likely used by the same feature. Once a frequently occurring set of Spring types is discovered, we would check the API documentation of Spring specifically for those types and try to infer how they relate to each other. In order to discover these commonly occurring sets of types, a frequent itemset analysis [35] was performed. In order to perform frequent itemset analysis it is required to define a finite set I of items and a finite set of trans- actions (sometimes called baskets). In this context a transaction/basket is any given subset of the set I. The goal of the frequent item set analysis is to discover subsets of the set I that frequently appear together in the baskets. In the case study presented in this thesis, the set I is the set of all Spring types or subtypes thereof that are used in a given client application that is using the Spring framework. In order to populate the set I we developed a

Python script that queries the .udb file for a given project and returns a list of all classes or interfaces listed in it. Types whose full names begin with org.springframework are considered to belong to the Spring framework and are added to the set I right away. For all other types, information about their immediate super type exists in the metrics gathered in the project’s

.udb file. This allows our script to walk up the inheritance chain. Eventually during this traversal, if the type is not part of Spring, the script will reach the java.lang.Object type. Otherwise, if we encounter a Spring-defined type, then the type from which the traversal started, as well as all other types encountered during the traversal before the Spring type was encountered, are added the set I. Each basket on the other hand is a subset of the types in I that are used in the same method in the client application. The data was

28 analyzed using the Apriori algorithm [35]. An open-source implementation of the algorithm downloaded from [1] was used to perform the analysis. Unfortunately the approach didn’t yield as good results as expected. In general, we failed to find large frequent item sets. One item set of size 1 that was often found was one containing the ApplicationContext interface. Classes implementing ApplicationContext interface are among the more feature-rich implementations of the Spring Dependency Injection (DI) con- tainer (see section 4.2.2.1). Since DI is the central feature of the Spring frame- work, it was no surprise that most client projects made use of it. The only other feature that was discovered through the empirical process was the Transac- tion feature described in section 4.2.2.7. This was achieved by detecting a fre- quent itemset consisting of the classes org.springframework.transaction. PlatformTransactionManager and org.springframework.transaction. TransactionStatus. The fact that our static analysis did not yield better results could be at- tributed to several factors. First and foremost, we believe they are due to the fact that the examined Spring client applications tend to use the XML inter- face of the framework, in order to minimize the coupling between application code and the framework. Since our analysis only takes the source code into consideration, it follows that any information contained in the XML configu- ration files of Spring would be lost. Another source of imprecision that was encountered in one case was the fact that sometimes client applications define their own classes and put them in sub packages of the org.springframework package. Therefore those application-defined types would be wrongly consid- ered as part of the Spring framework. Another possible source of imprecision comes from the method we used in order to determine if a given type defined in a client application inherits from a type defined in Spring. As we described

29 earlier, this is done by traversing a given type’s inheritance chain until a Spring defined type is encountered. However, the traversal is stopped as soon as the first Spring type is reached. Therefore, if the type in question is inheriting from more than one Spring type, we have no guarantees which one would be returned. 3.3 Modelling the interface of individual features

In order to make use of a given feature provided by a software framework, the client application must instantiate a set of software components. At run- time the framework must be aware of these components and it must be able to interact with them. The components in question could either be provided as-is by the framework, or they can be implemented by the user by extending framework-provided interfaces. As explained in section 2.1, using a framework feature often requires a more complex interaction between components than a simple method call on a single object. Moreover, the interaction in question might represent a crosscutting concern in the final application. In order to best describe the class/interface instances required in order to use a given feature, a RAM model is a natural choice, because of its capacity to model crosscutting behaviour. A RAM model groups together a set of classes that belong to the same design concern. The model therefore describes all classes necessary for the use of a given feature. At the same time, framework classes that do not relate to the feature at hand are omitted. Moreover, even the interfaces of the classes that are included in the model do not need to be specified completely: the only elements that need to be included are the ones that are directly related to the feature that is described by the model. Each framework feature is described by a single RAM aspect model. The Structural View of the feature’s aspect model should include all classes that a client application would need to interact with in order to use the feature.

30 This includes framework-provided types, as well as implementations of any required framework interfaces. The framework-provided types and operations are represented by the non-partial elements in the model’s Structural View. Any interfaces that the user is meant to implement are typically modelled as partial classes, thus forcing the user to map them to application-specific types. In other words, the set of partial model elements in a feature’s RAM model represents the customization interface of the feature. The public interface (see section 2.2.1) of the RAM model needs to include all operations that the user application can call on the types declared in the Structural View. The model elements included in the public interface of a given feature’s RAM model represent the subset of the software framework’s interface that the user application needs to interact with in order to leverage that feature. One might argue that the interface of every given feature is identical to the public interface of its corresponding aspect. This is partially true: all public properties and methods of the classes defined in the aspect’s Structural View make up the the aspect’s public interface as defined in section 2.2.1. As we mentioned above, the customization interface of the feature modelled is also explicitly described. Despite the wealth of information about the feature interface provided by the Structural View, there is still one important detail that is crucial to the framework user. As previously mentioned, it often takes more than a simple method call in order to take advantage of a framework’s feature. When a more complex interaction is required, knowing which are the public methods in the feature’s corresponding aspect is not sufficient. The user needs to know which classes to instantiate and when, the proper order in which method calls should be made to the framework classes, as well as what argu- ments are required by each method. For the purposes of describing the order of operations that a client application must follow, we introduced the Caller

31 class to each aspect model. This object is a dummy: it is not required for the actual feature. All methods of that class are always pubic and thus accessible to the aspect user. Each of those methods represents a usage scenario, i.e., a sequence of operations involving the aspect’s public interface that the client application might invoke in order to achieve some specific goal. This allows for usage scenarios to be described as Message Views in their corresponding aspect models, thus providing the ordering and parameter information that could not be obtained from the aspect’s public interface. For every aspect model, the Caller class is either explicitly present in the model’s Structural View (if the model introduces new usage scenarios), or it is inherited from the parent model (in case the current model only modifies already existing usage scenarios). One point worth mentioning is that usually, as described in section 2.2.2, a RAM model contains at least one message view for every method in an aspect’s public interface. In the models presented here on the other hand, the existing Message View are either Normal Message Views corresponding to the public methods of the Caller class or Aspect Message Views that affect them. The reason behind this is that we are interested in modelling the way a client application interacts with the Spring framework. This is exactly what the dummy methods of the Caller class describe. Modelling every public method of the Spring-defined classes would require knowledge of Spring’s internal workings. However, this is information that should be transparent to the framework user and therefore we decided not to model it in detail. For the purposes of describing how a user application interacts with a software framework, it is only necessary to consider messages originating from the Caller instances in our Message Views. Note that the Message Views

32 generated over the course of our case study described in section 4 are more detailed: they often contain information about messages exchanged between instances of the aspect’s classes (other than Caller). The additional messages represent a simplified description of interactions between the aspect’s classes that are executed inside the framework. Although this information is not strictly necessary for the purposes of generating user tutorials / framework interaction code, it provides a way to give more detailed information about the functionality of the corresponding feature. The information provided is therefore useful for documentation purposes. An example of this can be seen in section 4.2.2.1: the create() call does not originate from the Caller instance, but it is included anyways. 3.4 Deriving feature relationships

Designing the feature model for an existing framework is a challenging task. A naive solution would be to model each feature separately, without any relationship to any of the other features. As a result, the aspect corresponding to each feature would have no dependencies on the aspects describing the other modelled features. There are several issues with this approach. First, it would fail to leverage one of the main advantages of RAM: reusability. Without feature dependencies, a sub feature can not reuse the structure and behaviour provided by a parent feature, which leads to duplication, since, as we later demonstrate in chapter 4, it is quite common for the feature aspect models to include the same Structural View elements and/or Message Views. The du- plication increases the size of the individual feature models and consequently decreases their readability. For example, compare the aspect models presented in figure 2–4 and figure 2–5. Even though both models describe the exact same PushObserver aspect, the first one is a lot more succinct. Moreover, if a model

33 element needs to be changed, the changes must be introduced to each individ- ual model that features the element in question. Finally, modelling features separately would make feature composition impossible, since no classes would be shared between any two feature models. Introducing feature relationships in our feature diagram simplifies our aspect models a great deal. If two nodes in our feature diagram are linked by a line, this implies that their corresponding aspect models exhibit an “extend” relationship. More specifically, the aspect model of the child node is using an “extend” instantiation of the aspect corresponding to the parent node. This is demonstrated by the relationship between the aspects corresponding to the Observer and the PushObserver features, as they’re modelled in the feature diagram presented in figure 3–2. As we explained in section 2.2.4, extending an aspect model allows the extending aspect to have access to and manipulate all the elements of the parent model without needing to re-declare them. In addition, if an element of the parent model needs to be modified by the child aspect, it could be mapped to a corresponding element of the child model by an instantiation mapping.

mandatory Increase Observer performance optional

alternative (XOR) Minimize network traffic or (IOR) Notification Controller Concurrent Method Update

Minimize memory usage

Pull Push Active Passive

Figure 3–2: Sample Feature Model including the Observer and PushObserver features [8]

Other types of feature relationships that can exist between the nodes of a feature diagram (as described in section 2.3), including the additional

34 compositional rules, do not need to be reflected in the RAM models of the individual features. 3.5 Generating the interface of a combination of features (tutori- als)

Having discussed how to use RAM to describe the interface of an indi- vidual feature of a software framework in section 3.3 and how to reflect the feature dependencies in the corresponding RAM models in section 3.4, in this section we’ll discuss how to generate the full model for a given selection of features. In order to produce the final woven model for a particular feature selection, we rely on the TouchRAM tool[7]. This model’s interface should correspond to the subset of the framework interface that the user application needs to interact with in order to use all the selected features. First of all, the final model must allow the user to perform all actions allowed by each individual feature. Therefore, the interface of the woven model should be a superset of the interfaces of the selected features. In order to achieve that, a naive solution would be to create a new empty RAM model that extends the RAM models of all the selected features. This approach would work but it would lead to some redundancy, since an equivalent final model can be obtained by extending only a subset of these features. The notation used for the sample feature model presented in figure 2–6, presents the feature set of the modelled SPL in a tree diagram. Selection of features is done by traversing the tree starting from the root in accordance to the rules of the model. Given the set of rules presented in section 2.3, the traversal along each branch of the tree continues until one of two types of nodes are encountered. The trivial option is a leaf node: once it is reached, there are no child features to select. The other possibility is a node for which all children are optional features. In this case, the user could decide not to select any of

35 the child features of the node, thus terminating the traversal of the current branch of the tree. One can argue that if all of those “ending” nodes of the tree diagram are selected, all nodes encountered in the traversal must be selected. This is due to the fact that each node in the feature model has a single parent and we established that if a feature is selected its parent must necessarily be selected. As a result, the aspect models of the features described by those models would have direct or indirect aspect dependencies on all the other selected features. Consequently, in order to construct the aspect model for a given feature selection, it is sufficient to create a new empty aspect that extends the aspect models of all features represented as “ending” nodes. For an example, we can take a look at the feature model presented in figure 3–2. It includes the Observer and PushObserver (the latter corre- sponds to the “Push” node in the diagram) features, whose aspect models have been presented in figure 2–1 and figure 2–4 respectively. We can see that

{Observer, Push} is a valid selection. Therefore, according to the method we discuss earlier in this section, the model for this feature selection can be ob- tained by extending the model of our single leaf node, Push. Since we are not adding any additional information to the new extending aspect, and it extends a single aspect model, it’s woven model will be identical to the woven model of PushObserver. First, the Observer dependency will be woven in, obtaining the model we’ve already examined in figure 2–5. Finally, the ZeroToMany de- pendency would be woven in. However, since a “depends on” instantiation is used for ZeroToMany, after weaving it in, the aspect model’s public elements will have their visibility reduced (see section 2.2.1). Therefore, since weaving in the ZetoToMany dependency is omitted, since it will not alter the interface of the resulting model.

36 Chapter 4 The Spring Framework Case Study In order to demonstrate our approach to software framework modelling using RAM a case study on the Spring framework was conducted. 4.1 The Spring Framework

The Spring framework is a mature framework meant to be used in enter- prise applications written in the Java programming language. According to [5], Spring evolved from code written for the book Expert one-on-one J2EE design and development [27]. Spring offers a variety of features, most no- tably a Dependency Injection container. For those unfamiliar with DI, it is a design pattern that allows a client application to be decoupled from the con- crete implementations of the services it uses [34, 17]. Spring implements DI by allowing the user to describe components and their dependencies in an a configuration file. These descriptions are parsed by the framework at runtime and the appropriate components are instantiated using reflection. Although DI is the most prominent feature of the Spring framework, there exist various others: such as support for Aspect-Oriented Programming (AOP), as well as integration with various other popular software frameworks. The Spring framework was chosen for this case study for several reasons. First and foremost, it is a mature framework that has been around for almost a decade. As a result its interface for its most popular features is well-designed and stable. Another advantage of the product’s maturity is the fact that it offers a wide range of features that can be modelled. Finally, Spring is widely used and well-documented which makes it easier to discover information about its interface and various features.

37 4.2 Features Modelled

4.2.1 Feature Model

Figure 4–1: Spring Features

Here we present the feature diagram of the subset of features of the Spring framework analyzed over the course of the case study. As shown on figure 4–1, the features modelled are the following: BeanContainer, BeanContainer- Configurable, XmlBeanFactory, EventPublisher, InitializingBean, BeanPost- Processor and Transaction. Each feature (with the exception of the root) is described in the following sections as a separate aspect having the same name as the corresponding feature in the diagram. A note on the two additional constraints: the BeanPostProcessor feature cannot be selected together with the Event Publisher feature because the bean container implementation used by the EventPublisher feature does not support programmatic registration of

38 BeanPostProcessors (described by the addPostProcessor Message View of the BeanPostProcessor feature). XmlBeanFactory is incompatible with Event-

Publisher for a similar reason: the XmlBeanFactory container provides a con- structor that takes a configuration file location as an argument, while the

GenericApplicationContext class provides no such constructor. 4.2.2 Individual Features

Here we present the RAM models of the individual features from the feature diagram in figure 4–1. The models were constructed according to the methodology described in chapter3. The figures in this section were created using the TouchRAM tool [7]. For all Structural View diagrams, dependencies and instantiation mappings are listed in the top left part of the corresponding figures.

4.2.2.1 BeanContainer

One of the most important features in Spring is Dependency Injection: the framework’s ability to instantiate objects and manage their lifecycle. Un- fortunately, for the reasons described in section 4.3, the DI feature could not be modelled in RAM. However, Spring also offers features equivalent to what is described in [17] as a “Service Locator”. This design pattern is similar to the Factory design pattern described in [18]. When it is applied, the client software has a dependency on an object that has access to all services the ap- plication software needs. This object is the titular “Service Locator”. Every time the client software needs to use a service, it queries the Service Locator, which returns the corresponding object. That way the client application can use the returned object using a software interface, but it has no control over instantiating the object, nor does it know anything about its implementation. In Spring terminology, the Service Locator object is known as the “Bean Con- tainer” and is usually an implementation of the BeanFactory interface. This

39 object is in responsible for the instantiation and lifecycle of all its managed objects (that implement the services needed by the application). The managed objects on the other hand are referred to as “Beans” in Spring terminology. The name is misleading, since these objects do not have to be Enterprise Java Beans. They are in fact just POJOs (regular Java objects) [16].

Figure 4–2: Structural View of the BeanContainer aspect

The Service Locator feature can be configured in Spring, but here we start out by modelling its most basic functionality. The corresponding aspect model is called “BeanContainer”. The Structural View of this aspect is pre- sented in figure 4–2. The aspect interface consists of two methods, both of which belong to the DefaultListableBeanFactory class: the constructor and the getBean(String beanName) method. DefaultListableBeanFactory is one of the Spring provided implementations of a bean container. As we can see from the interface of the Caller class (see section 3.3) , there are two operations that can be performed: the instantiation/initial setup of the bean container (described by the Message View for setupContainer()) and the action of querying the bean container for a particular object (described by the

Message View for getBeanInstance()). The details regarding the execution of these two operations are given by their Message Views.

40 (a) setupContainer Simple Message View

(b) getBeanInstance Simple Message View

Figure 4–3: Message Views of the BeanContainer aspect

Both Message Views for this aspect are Normal Message Views (see sec- tion 2.2.2). The interactions they describe are fairly trivial: in the setup- Container usage scenario we simply instantiate the container object by using its constructor. As for getBeanInstance, it describes how Spring containers handle bean requests. The beans are instantiated in a lazy fashion: a par- ticular bean is instantiated the first time it is requested by the client code; subsequent requests would return the same instance. This behavior is config- urable: for example, Spring provides options for returning a new instance on every request, or registering an instance that is to be returned on every sub- sequent request. However, for the purposes of this study, the default behavior has been modelled. Also, note that some simplifying assumptions have been made: in reality, the instantiation mechanism of Spring is rather complex and the container object does not directly perform the instantiation of the bean.

41 The simplification is justified: the details of how Spring instantiates beans are not relevant for the user of the framework. The message that shows how the DefaultListableBeanFactory object instantiates the bean in figure 4-3 is only there for documentation reasons: it allows the user to understand the essence of what happens when she invokes the getBean() method.

4.2.2.2 XmlBeanFactory

Figure 4–4: Structural View of the XmlBeanFactory aspect

The XmlBeanFactory feature represents a simple concrete extension of the feature described in section4.2.2.1. It maps the |BeanContainer partial class to the concrete Spring class XmlBeanFactory. It provides an extra constructor which, at instantiation, passes to each XmlBeanFactory object the path to a Spring configuration XML containing a mapping between bean names (that can be requested when getBean(String beanName) is invoked) and bean de- scriptions, specifying how each particular bean must be instantiated. As a result, the Structural View of the XmlBeanFactory aspect (presented in fig- ure 4–4) consists of a single class, XmlBeanFactory. This class extends the DefaultListableBeanFactory class.

4.2.2.3 BeanContainerConfigurable

As mentioned in section 4.2.2.2, the most popular way of loading the de- scriptions of the beans to be instantiated and managed by Spring is by parsing an XML configuration file. However the client might need to store these bean

42 Figure 4–5: Structural View of the BeanContainerConfigurable aspect descriptions in a different way (for example, in a relational ). In order to accommodate this, the Spring framework can be extended so it would be able to read this information from an arbitrary source. This is the essence of the BeanContainerConfigurable feature. The Structural View of its aspect model is presented in figure 4–5. In order to use that feature, the client appli- cation must use a bean container implementation that implements the Spring defined BeanDefinition interface. Then, the client must either provide their own implementation of the BeanDefinitionReader interface or use one that is already provided by the framework. The role of the BeanDefinitionReader is to read the information from the desired source and register it with the bean container. For detailed description of the interaction, refer to the Mes- sage Views of the BeanContainerConfigurable aspect. These are presented in figure ??.

43 Figure 4–6: BeanContainerConfigurable.setupContainer Message View Refer- ence

(a) Pointcut

(b) Advice

Figure 4–7: BeanContainerConfigurable.readDefinitions Aspect Message View

First, we notice that the diagram of the setupContainer Message View is empty. This is justified by the fact that setupContainer is a MessageViewRef- erence (see section 2.2.2). Its purpose is to indicate that the setupContainer Message View inherited from the BeanContainer aspect is being modified by the Aspect Message View readDefinitions that is defined in BeanContainer- Configurable. The readDefinition Aspect Message View describes the actual modification of the basic setupContainer message view necessary to take ad- vantage of the BeanContainerConfigurable feature. As we can see from the

Advice diagram, after the original execution of the setupContainer() op- eration, the user is required to instantiate their BeanDefinitionReader im- plementation and pass it a reference to the bean container object (which is

44 a DefaultListableBeanFactory instance) as a constructor parameter. Af- terwards, the user needs to call the loadDefinitions() method on the |BeanDefinitionReader. The definitionSource parameter passed to the loadDefinitions() method is an instance of the |Resource class and repre- sents the source from which the |BeanDefinitionReader is going to obtain information about the bean descriptions and their corresponding names that need to be loaded into the bean container. The |BeanDefinitionReader parses the information in the definitionSource. For each bean described in the definitionSource, the |BeanDefinitionReader| proceeds to instan- tiate a BeanDefinition that encapsulates the information present in the description. A reference to the BeanDefinition object is then passed to the container, by use of the registerDefinition() method. Since the registerDefinition() method is not meant to be called directly by the aspect user, it is not part of the aspect’s public interface. Consequently, its visibility is set to aspect-private. The information contained within each

BeanDefinition can be later used by the container in order to instantiate the corresponding bean, in case it is requested through the container’s getBean() method.

4.2.2.4 InitializingBean

Figure 4–8: Structural View of the InitializingBean aspect

45 The InitializingBean feature represents a simple extension of the Bean- Container feature. It allows beans to have a method that will be automat- ically called by the Spring framework after the bean is instantiated by the

|BeanContainer in order to perform bean-specific initialization. The partic- ular details of this initializing operation are implemented by the framework client. The initializing method can be specified in two different ways: the bean can either implement the Spring interface InitializingBean , in which case it would need to implement the method afterPropertiesSet() which acts like the initializing method. The second option is to specify the initializing method in the XML configuration file. The Structural View of the feature is presented in figure 4–8. It is rather simple, as the only thing that is added to the BeanContainer aspect is the ability to map a method to the |init() partial method, so that the mapped method would perform the desired ini- tialization. As far as the Message Views are concerned, the InitializingBean feature defines two: an Aspect Message View called “initialize” and a Message View Reference named “getBeanInstance” that references the Message View by the same name defined in the BeanContainer aspect. As evidenced by the “affected by” directive, the Aspect Message View “initialize” is modifying the behavior of the “getBeanInstance” message view. The modification consists of an extra interaction after the execution of the original method. It assures that if the bean requested by the getBean() method was not already instantiated at the time of invocation of the getBean() method, the initializing method |init() of the bean gets called before the reference to the bean is returned to the client application.

46 (a) Pointcut

(b) Advice

Figure 4–9: InitializingBean.initialize Aspect Message View

Figure 4–10: InitializingBean.getBeanInstance Message View Reference

4.2.2.5 BeanPostProcessor

An extension of the InitializingBean feature described in section 4.2.2.4, the BeanPostProcessor feature allows the user to define two callback methods that are called before and after the custom initialization of every bean instan- tiated. The Structural View of the feature is presented in figure 4–11. We see that the client application is responsible for specifying a BeanPostProcessor class that implements the methods postProcessBeforeInitialization() and postProcessBeforeInitialization(). The Message Views presented in figures 4–12, 4–19, 4–14, 4–15 and 4–16 describe how the user and the Spring framework interact with instances of the newly introduced |BeanPostProcessor class. As evidenced by the Message

47 Figure 4–11: Structural View of the BeanPostProcessor aspect

Figure 4–12: BeanPostProcessor.setupContainer Message View Reference

Figure 4–13: BeanPostProcessor.getBeanInstance Message View Reference

View References setupContainer and getBeanInstance, the BeanPostProces- sor aspect modifies both these behaviors. The setupContainer and getBeanIn- stance Message Views are inherited from the InitializingBean aspect (which in turn inherits them from the base BeanContainer aspect). The BeanPostPro- cessor aspect modifies the setupContainer Message View by applying the ad- dPostProcessor Aspect Message View to it. This Aspect Message View allows the client application to instantiate a |BeanPostProcessor object and then register it with the bean container by using the addBeanPostProcessor() method. The operation can be repeated so any required number of

|BeanPostProcessor instances can be registered with the container. The

48 (a) Pointcut

(b) Advice

Figure 4–14: BeanPostProcessor.addPostProcessor Aspect Message View

Spring framework does provide another way to register BeanPostProcessor in- stances with the framework: some of the Spring-provided implementations of the bean container are capable of recognizing implementations of the

BeanPostProcessor interface in the container’s configuration file and regis- ter them automatically. However, this approach relies on the XML interface of the Spring framework and for reasons mentioned in section 4.3 it is not modelled. A key observation is that similarly to the registerDefinition() method defined in the BeanContainerConfigurable aspect (see section 4.2.2.3), postProcessBeforeInitialization() and postProcessAfterInitialization() are methods designed to be called by the Spring framework and not the client application. As such, they are not part of the aspect’s public interface and they are therefore marked as aspect- private.

49 (a) Pointcut

(b) Advice

Figure 4–15: BeanPostProcessor.postProcessBefore Aspect Message View

The postProcessBefore and postProcessAfter Aspect Message Views de- scribe how the registered |BeanPostProcessor instances are used by the framework. In the case of postProcessBefore, we see that after a bean is first in- stantiated, it is passed to the postProcessBeforeInitialization() method of the |BeanPostProcessor class as a parameter and the bean object reference that is to be returned to the client application is replaced by the return value of that method. This operation is repeated for every |BeanPostProcessor registered with the container. Finally, after having been processed by all the registered |BeanPostProcessor instances, the bean instance is returned to the client application. The postProcessAfter Aspect Message View is analogous to postProcessBefore with the only difference being that the bean instance is being passed to BeanPostProcessor.postProcessAfterInitialization()

50 (a) Pointcut

(b) Advice

Figure 4–16: BeanPostProcessor.postProcessAfter Aspect Message View instead of BeanPostProcessor.postProcessBeforeInitialization(). The “affected by” directive of the getBeanInstance Message View states that the postProcessBefore and postProcessAfter Message Views are woven in order, ensuring that the postProcessBeforeInitialization() method is invoked before postProcessAfterInitialization() method when a bean is being instantiated. Due to a technical limitation of the TouchRAM tool, the weaving order for the Aspect Message Views affecting the getBeanInstance not accurately repre- sented in figure 4–19. When postProcessBefore and postProcessAfter are wo- ven into getBeanInstance, the initialize Aspect Message View from the under- lying InitializingBean aspect is already woven in. As a result, in the final woven

51 model the invocation of the |init() method inherited from the Initializing- Bean aspect would happen before the postProcessBeforeInitialization() or postProcessAfterInitialization() methods of the BeanPostProcessor class are called. This is not the intended behavior. The goal would be to over- ride the getBeanInstance Message View that is inherited from the Initializing- Bean aspect, modifying the weaving order so that that the “initialize” Message View defined in InitializingBean be woven after postProcessBefore and before postProcessAfter. Therefore, in the BeanPostProcessor aspect we would have a Message View Reference “message view getBeanInstance affectedby post- ProcessBefore, initialize, postProcessAfter”. However, currently TouchRAM tool does not support message view overriding. This is one of the features that will be added to it in the future (see section6.3).

4.2.2.6 EventPublisher

The EventPublisher feature is the Spring framework’s implementation of functionality similar to the one provided by the Observer design pattern as de- scribed in [18]. The Structural View of the EventPublisher aspect is presented in figure 4–17. The advantage of the EventPublisher feature over the classic Observer pattern is that it allows finer-grained control over which objects get notified on a subject update. The |Subject and |Listener classes described in the Structural View are the equivalent of the Subject and Observer classes in the Observer pattern, respectively. The idea is that the Observer (or, in our case, the |Listener) object is automatically notified about a change in the Subject’s state through a callback method. However, in the Observer design pattern approach, once the Subject needs to notify the Observer instances subscribed to it, it notifies all of them. The EventPublisher on the other hand, allows |Listeners to subscribe to |Event instances that are fired by the |Subject. This allows a |Subject to notify different subsets of the |Listener

52 Figure 4–17: Structural View of the EventPublisher aspect instances in different situations. Also, the |Subject is completely decoupled from the |Listener instances, since it only needs to invoke the appropriate |Event. As we can see from the instantiation mappings of the EventPublisher aspect, in order to use the functionality it provides, |Subject instances as well as |Listener instances must be beans registered in the bean container. Unlike the other features described so far, the EventPublisher uses a differ- ent implementation of the bean container: the GenericApplicationContext class. The EventPublisher aspect modifies the setupContainer Message View inherited from the BeanContainer aspect in order to accommodate the in- stantiation of a different bean container implementation. This is done by

53 (a) Pointcut

(b) Advice

Figure 4–18: EventPublisher.setupApplicationContext Aspect Message View

Figure 4–19: EventPublisher.setupContainer Message View Reference having the setupContainer Message View affected by the setupApplication-

Context Aspect Message View. Since the GenericApplicationContext con- structor takes a reference to a DefaultListableBeanFactory, as we can see from the structural view, the only thing the Aspect Message View does is to take the DefaultListableBeanFactory instance already created during the execution of the setupContainer Message View, pass to the constructor of

GenericApplicationContext and return the resulting reference to the client. The other Message View of the EventPublisher aspect is called publi- shEvent (see figure 4–20). It describes how an event is fired by the |Subject instance. The key element is the |eventPublishingOperation() partial

54 (a) Pointcut

(b) Advice

Figure 4–20: EventPublisher.publishEvent Aspect Message View method. This method is mapped by the client application to any opera- tion on the |Subject that needs to fire an event. The actual event pub- lishing is achieved by passing the appropriate event instance as an argu- ment to the publishEvent() method of the bean container. It is the con- tainer’s responsibility to maintain a list of |Listener instances that are sub- scribed to the particular event and notify them through an invocation of

|Listener.onApplicationEvent() method. Note that the aspect does not include a Message View that describes how

|Listener instances subscribe to |Events. This is because the subscriptions are done automatically by the bean container. All |Events must inherit from the Spring-defined abstract class ApplicationEvent. All |Listener instances on the other hand expect a particular subclass of ApplicationEvent as an argument to their respective onApplicationEvent() method. The Spring

55 framework ensures that every time a particular |Event instance is fired, every |Listener that expects that particular |Event subclass as an argument of its onApplicationEvent() method would get notified. The framework achieves this by using reflection.

The setApplicationEventListener() method of |Subject is marked as aspect private, because it is not meant to be invoked by the client code. It is called internally by the Spring framework at the time it instantiates the

|Subject bean. setApplicationEventListener() is used to pass a reference to the |ApplicationEventPublisher to the |Subject instance. As we have already seen, this reference is necessary in order to make the publishEvent() call.

4.2.2.7 Transaction

Figure 4–21: Structural View of the Transaction aspect

56 The Transaction feature of Spring serves to provide an abstraction layer over several existing transaction management systems. The aim is to pro- vide a simple and consistent interface for transaction support that would not couple the client application to any particular transaction library. The Structural View of the Transaction aspect is presented in figure 4–21. The

|PlatformTransactionManager object provides the API required for start- ing, committing and aborting a transaction. The |TransactionDefinition object contains a number of fields that can be set it order to configure a partic- ular transaction. Finally, a |TransactionStatus object represents an active transaction during its execution.

(a) Pointcut

(b) Advice

Figure 4–22: Transaction.transactionaExecution Aspect Message View

57 The single Message View of the Transaction aspect, presented in figure 4–22, is an Aspect Message View named transactionalExecution. A user of the Transaction aspect is allowed to make the execution of any method trans- actional by mapping it to the |executeTransactionally() partial method and defining a Message View that is affected by the transactionalExecution Aspect Message View. First, the user needs to configure the transaction. In order to do that, they need to instantiate a |TransactionDefinition and set its properties as necessary. After that, the |TransactionDefinition instance is passed to the |PlatformTransactionManager.getTransaction() method which re- turns a |TransactionStatus object. The getTransaction() method marks the start of the transaction’s execution. After that, the behavior that is to be made transactional is executed. At the end of the execution, the

|PlatformTransactionManager.commit() method is called with a reference to the |TransactionStatus instance as an argument in order to commit the transaction. If any of a pre-defined set of exceptions is thrown between the invocation of |PlatformTransactionManager.getTransaction() and the in- vocation of |PlatformTransactionManager.commit(), the transaction is con- sidered to have failed and the |PlatformTransactionManager.rollback() method is called. 4.2.3 Combining Spring Features

In the previous sections we discussed the individual features discovered over the course of the Spring case study (section 4.2.2) as well as the rela- tionship between them (section 4.2.1). Here we present an example of the woven RAM model corresponding to a given feature selection. Going back to the feature model described in figure 4–1, a valid feature selection would be {BeanContainer, XmlBeanFactory}. This selection has been chosen for the

58 Figure 4–23: Woven model for the {BeanContainer, XmlBeanFactory} feature selection sake of simplicity. According to what we established in section 3.5, in order to obtain the model for this selection, we need to construct a new empty aspect model that extends the RAM model corresponding to every “ending” node of the feature selection. In our case, there is a single leaf node, the one represent- ing the XmlBeanFactory feature. Weaving an empty aspect model that has a single “extends” dependency would be equivalent to taking the dependant

59 aspect and weaving it with its own dependencies. The result is presented in figure 4–23. As expected, the model is very similar to the BeanContainer as- pect, with the only difference being that the DefaultListableBeanFactory type has been mapped to XmlBeanFactory and has been given a constructor with a different signature, as specified in the XmlBeanFactory aspect.

Figure 4–24: Woven model for the {BeanContainer, XmlBeanFactory, Initial- izingBean, BeanPostProcessor, BeanContainerConfigurable} feature selection - Structural View

For a more complex example, we’ll take the feature selection {BeanContainer, XmlBeanFactory, InitializingBean, BeanPostProcessor, BeanContainerConfig- urable}. The Structural View of the resulting woven model is presented in figure 4–24 and its Message Views are presented in figure 4–25 Note how the Structural View in figure 4–24 explicitly lists all manda- tory instantiation parameters of the final model, therefore explicitly listing all elements that the client needs to provide for the model in order to be able to use all of its features. In this case, the client application needs to provide

60 mappings for the |Bean, |BeanPostProcessor, |BeanDefinitionReader and |Resource partial classes, as well as for the |init() partial method of the |Bean class. It is important to point out that these need not be one-to-one mappings. In the case of the Spring framework, any class of the client appli- cation that is managed by the framework is a bean, and therefore the |Bean class would be mapped to it. Similarly, each of those managed classes could have its own initialization method to map to |init() 4.3 Difficulties Encountered

During the course of the case study, several difficulties were encountered. The most notable one so far stems from the fact that the Spring framework makes heavy use of XML configuration in order to describe the framework behavior. Unfortunately, the information included in the configuration files represents a part of the framework interface that cannot be expressed by our current method. For that reason, we were unable to model certain features, such as the genuine Dependency Injection feature that minimizes the client application dependency on the Spring framework. Other features, such as the ones described in subsections 4.2.2.5 and 4.2.2.7 , offer the choice between a declarative, XML-based configuration and the standard programatic approach. In these cases, the programatic interface has been modelled. Finally, for fea- tures such as the EventPublisher (see section 4.2.2.6), a combination between the declarative and the programatic interface is necessary. In such cases, a best effort attempt was made to describe as much of the feature’s function- ality as our approach would permit. In general, the declarative interface of Spring is one of the major benefits of the framework, since it allows the client application to be very loosely coupled with the framework. Not being able to express that interface is a drawback of our method that needs to be addressed (see section 6.3).

61 Another important observation was that the features of the Spring frame- work that we examined did not exhibit complex dependencies between each other. As a result, our feature model presented in figure 4–1 is relatively simple.

62 Figure 4–25: Woven model for the {BeanContainer, XmlBeanFactory, Initial- izingBean, BeanPostProcessor, BeanContainerConfigurable} feature selection - Message Views 63 Chapter 5 Related Work 5.1 Understanding framework APIs

Several sources have suggested the use of examples in order to improve the documentation of software frameworks and facilitate familiarization with the framework. As [23] suggests , “example-based techniques are well-suited to use by beginning learners”. The empirical study conducted by the au- thors consisted of gathering information about how students well learn to use a framework API during a course that required the implementation of a client application of the Swing framework. The students were encouraged to make use of the example usage scenarios for the Swing framework avail- able online. All students interviewed made use of the examples, although most did modify the example usage scenarios to some extent. Also, it was noted that features with simpler interfaces (“features that can be accessed by function calls”) were in general better implemented than features with more complex interfaces (“features whose customization requires callbacks”). An- other observation is that “The more design knowledge about the framework it requires to use a framework feature, the more difficult it is to learn and modify”. This suggests that even API documentation and arbitrary examples are insufficient in order to describe the framework’s interface in an accessi- ble manner. The approach outlined in this thesis offers several advantages in that regard. Most importantly, it allows for the creation of tutorials that are tailored to the particular feature selection specified by the user. Therefore, we would expect that the examples generated by our method would require fewer modifications. Also, feature interfaces that require the use of callbacks

64 can be better documented, since as we have seen previously in section 3.3 we could include simplified description of how the framework is handling the components defined in the model. This is in addition to the architectural in- formation regarding the classes involved in the feature interface contained in the Structural View of each model. Hopefully, this would allow to share only the specific architectural information that is relevant to each feature, thus re- lieving the user of the responsibility of having to learn the design of the entire framework. Another interesting approach is described in [22]. This work describes the FUDA method which provides a “notion of concept implementation templates, which summarize the necessary implementation steps [for using a framework ] and an approach to automatic extraction of such templates from traces of sample applications”. The “concept implementation templates” that are men- tioned in this study are very similar in nature to the usage scenarios that are described in this thesis. The main difference lies in the fact that the “concept implementation templates” are described by pseudocode very closely resem- bling standard Java, while in our case object interaction is described in the RAM message views. Consequently we could argue that our method benefits from increased readability of the models. This is because a message view al- lows to see at a glance all the objects involved in a single interaction. This information could also be inferred from pseudocode, but it is not immediately obvious. Moreover, as mentioned in section 6.3, one of the eventual goals for the method presented in this thesis is to develop a way of using the created RAM models as basis for code generation, therefore obtaining a final result that is even more akin to a “concept implementation template”. Meanwhile, RAM models have the advantage of being more formal than pseudocode. Also,

65 the information given by a RAM model has the advantage of being well struc- tured into several different views, thus making it easier for the developers to find the information they need. A key difference between our approach and the one described in [22] lies in the way the “concept implementation templates” are generated. The FUDA method extracts this information by means of dy- namic analysis of existing client applications. Our method on the other hand, requires the example scenarios to be generated based on the models provided by the framework developers as part of the framework documentation. Both ideas have their unique advantages and drawbacks. The FUDA method can be applied on an arbitrary framework and can generate usage examples for differ- ent framework features with a high degree of accuracy. The authors claim that useful information can be extracted from as little as two example applications. This makes it very useful in situations where a framework’s documentation is incomplete or unavailable.The method presented in this paper does not have that capability. It requires the framework developers to manually include the relevant RAM models in the framework’s documentation. However, it has the advantage that the examples provided are always accurate, provided the framework developers made the effort to keep the framework documentation and framework implementation in sync. It is interesting to note that another paper focusing on the FUDA method [21], describes a study that evaluated the usefulness of the generated templates in practise. The purpose of the eval- uation is to determine if the usage of the pseudocode examples generated by using FUDA is more useful to the client application developers than the tra- ditional framework documentation. The analysis determined that in terms of development time, that is the case. This is an important result that confirms the usefulness of examples for developing applications based on a software framework.

66 5.2 Aspect-Oriented Modelling

In this section we discuss several alternatives to the RAM approach. One is the Theme/UML approach discussed in [9]. Similarly to RAM, Theme/UML serves to describe crosscutting concerns in a modular and reusable way. The unit of reusability that the approach introduces is called a “Theme” and it bears several similarities to the aspects in RAM. One notable similarity is the use of “templates that will be bound to real base elements at a later stage”, similar to partial model elements in RAM. Another similarity lies in the way that the structure and behavior of individual themes are described. Much like in RAM, UML class diagrams and UML sequence diagrams are used for those respective purposes. Also, much like RAM models, individual themes can be composed in order to obtain the model of the final system. However, the Theme/UML defines two kinds of themes base (describing the base model being modified) and crosscutting (describing the crosscutting concern applied to the base model). When it comes to theme composition, a base themes can only be composed with crosscutting themes. This is referred in [29] as “Assymetric Concern Composition”, that is, elements from the base model are distinguished from the aspect model elements. RAM on the other hand uses symmetric concern composition when it comes to weaving Structural Views (Structural View elements from all woven aspects are treated the same way). However, RAM employs assymetric concern composition when it comes to weaving Message Views: we have already seen that Normal Message Views and Aspect Message Views are treated differently (see section 2.2.2). It would be interesting to conduct a case study in order to determine how the Theme/UML approach compares to RAM when used to create a larger model. However, while tool support for RAM exists (the TouchRAM tool), there is no equivalent tool for Theme/UML.

67 Another aspect-oriented interesting modelling approach that is currently used by Motorola is the Motorola WEAVR tool [11]. It’s primary focus is on aspect-oriented modelling of reactive systems. It is based on the Specification and Description Language (SDL) [25], a language conceived for describing systems using a notation derived from Finite State Machines. The WEAVR tool “enables Aspects to be defined at the modelling level and fully woven with the base models” [12]. Therefore, similar to RAM, the WEAVR approach features the idea of aspect reusability, as well as a mechanism for weaving the functionality described in aspects into the base model. As pointed out in [29], similarly to RAM the WEAVR tool relies on mappings in order apply aspects to the base application-specific model. WEAVR models are used by Motorola as basis for code generation, which is one of the applications of the RAM approach proposed in this thesis. The major difference is the fact that the WEAVR approach uses state diagrams to specify system behavior, where RAM relies on Message Views (based on UML sequence diagrams). State diagrams are not ideal for describing a user scenarios. This is because state diagrams describe all possible input sequences the system can take at every given state. Therefore, it is not suited for describing a particular sequence of input events. 5.3 Software Product Lines

In this thesis we have demonstrated how we can represent the features of a software framework using feature diagrams, similarly to the way the features of a SPL are described. However, there are certain important differences: for example, once a valid selection is made using the feature diagram of a SPL, the instance of the product line that is generated is a complete, working application. In our case, we only generate the model of the classes needed to interface with the framework, without modelling the internal workings of the

68 framework or the software artifacts specific to the client application. The goal is to create a supplement to the user documentation in the form of example usage scenarios, rather than a model describing the entire application. Recent works exist that aim to map the features of an SPL to the actual design assets. One example is the FeatureMapper tool described in [20]. It could be applied for our method in order to map the features described in a software framework’s feature diagram to the corresponding RAM aspect models. Other works ([38]) point out the fact that when modelling a product line one uses different Domain Specific Languages in order to model the problem and solution domains. In the case of the RAM approach, this also holds: the problem domain (the feature selection offered by the framework) is modelled using a feature diagram, and the solution domain (the implementation of the features’ interface) is represented by a RAM model. The paper also includes the notion of representing optional features as aspects and weaving them to a base model selectively, based on the configuration (i.e. feature selection) cho- sen by the user. The possibility of using the models as basis of code generation is also discussed.

69 Chapter 6 Conclusions and Future Work Object-oriented software frameworks are a popular method of software reuse in modern . Although they offer significant ad- vantages in terms of software productivity, very often they can be leveraged efficiently only after the developers have spent a significant amount of time familiarizing themselves with the framework. In the case of a large and feature- rich framework, it is conceivable that there is a steep learning curve involved in order to understand and make efficient use of the functionalities offered. In this thesis we propose a modelling technique based on feature diagrams and the RAM aspect-oriented methodology. The method presents the following advantages to framework designers: • Formally describe the interfaces of individual features The subset of the framework interface needed to use each individual feature could be specified separately. Therefore, the interface of each individual feature can be redesigned in isolation from the rest of the framework’s interface. • Specifying feature dependencies Having the available framework features organized in a feature diagram, as opposed to a flat list, allows the designer to specify feature rela- tionships. The ability to specify dependency relations between features allows new features of the framework to reuse the functionality of the al- ready existing features. Therefore, functionality that is common between two or more features would not need to be modelled redundantly.

70 The framework users on the other hand are presented with the following advantages: • Explicit listing of framework features The client is presented with an explicit list of all features the modelled framework has to offer, in the form of a feature diagram. We believe that this would be a useful supplement to the framework’s documentation. We would expect the extra information to aid the users to familiarize themselves with the functionality offered by a framework. Consequently a client would be able to quickly determine if leveraging a given frame- work is useful in the context of a given application. Also, the feature model would enable the client application developers to easily select a subset of the features offered by the framework that are relevant to their needs. Finally, a detailed feature model could also be useful to the devel- opers in order to perform comparison between frameworks. An in-depth empirical study would need to be performed in order to determine to what extent our method simplifies the workflow of an application devel- oper. • Leveraging the framework designer’s domain knowledge The feature diagram contains information regarding the domain of the modelled framework, most notably about which features are to be used together and which are mutually exclusive. As a result, when using the feature model to make a selection, the client is able to determine whether a given feature selection is valid or not, without having to know why that is the case. • Formal descriptions the interfaces of individual features The framework users are provided with a formal model of the interface of each framework feature in the form of a RAM model. The Structural

71 View of the RAM model presents to the user the exact subset of the framework’s artifacts that need to be instantiated in order to take ad- vantage of a particular feature. In addition, the Message Views make the interactions between those artifacts explicit . Once again, an empirical study would need to be conducted in order to establish to what extent our method reduces the learning curve for the framework user. • Generating models for an arbitrary feature selection Once a valid feature selection is made, the aspect models of the selected features can be woven together to produce a model of the subset of the framework interface that is relevant to the selected features. As a result, the developers of the client software can examine only of the rel- evant subset of the framework’s interface. We would expect this model to serve as a useful supplements to the framework’s documentation and facilitate the users who do not have extensive experience with the frame- work. Also, the woven usage scenarios can serve as customized tutorials that demonstrate how the client application should utilize the framework artifacts relevant to the particular feature selection. 6.1 Observations

We conducted a case study based on the Spring framework in order to demonstrate our method. A number of the features modelled, namely BeanContainer, BeanContainerConfigurable, InitializingBean, BeanPostPro- cessor and EventPublisher are extensions of the BeanContainer feature and exhibit certain dependencies on each other. Consequently, leveraging a feature diagram to describe these dependencies (figure 4–1) was a success. Using the RAM modelling approach for describing the individual features was also very successful, since it allows for describing multiple elements of a given feature’s interface: the public methods, the classes involved as well as the interactions

72 between those classes that need to be implemented by the user. An added benefit is that each model can specify which classes and methods are already provided by the framework (the non-partial ones) and which are supposed to be implemented by the client software (the partial ones). Another advantage stems from the reusable nature of RAM models that allows for each model to describe only the elements relevant to the particular feature. The individ- ual models are then woven in order to build a model for the entire feature selection. The advantage in this case is that even for classes with complex interfaces, only the parts relevant to the feature at hand can be modelled in each aspect model, resulting once again in a reduction of complexity from the point of view of the framework user. 6.2 Limitations of the TouchRAM tool

One detail that is currently missing in the TouchRAM tool is a formal way of specifying a constructor for a given class. Knowing which constructor to use for a given usage scenario is an important part of a feature’s public in- terface. Consequently, it was necessary to get around this limitation in order to construct our models in TouchRAM. Therefore, for the models presented in the case study ( described in chapter 4 ) we used a method named create() as a stand-in for the class constructor. According to the convention we used, the create() method accepts the same parameters as the constructor it cor- responds to and returns an instance of the class it belongs to. As evidenced by the PushObserver aspect we discussed earlier (figure 2– 4), theoretically RAM supports Message View overriding. However, this is currently not supported by neither the TouchRAM tool nor the RAM aspect weaver. The implementation of this functionality in the TouchRAM tool was not done as part of this thesis due to time constraints.

73 In addition to adding the override functionality of the tool, we would need to update the RAM notation in order to indicate that a Message View is overriding the one from the parent aspect. That is important in cases similar to the one described in section 4.2.2.5. In that particular case, we required message view that looks like “message view getBeanInstance affectedby post- ProcessBefore, initialize, postProcessAfter”. However, if there is no explicit way to denote that this message view is overriding the one in the parent aspect, InitializingBean, then the three message views mentioned in the affecttedby directive will be simply woven in after the modifications of the parent as- pect. Therefore, when the InitializingBean and BeanPostProcessor aspects are woven, the message view would look like “message view getBeanInstance affectedby initialize, postProcessBefore, initialize, postProcessAfter”, which is not correct. 6.3 Future Work

RAM allows us to model the interaction between the interface elements of a feature or a given set of features by using a notation very similar to UML sequence diagrams. Since a sequence diagram generally represents a sequence of messages between class instances, it could easily be used to generate the actual code that needs to be implemented by the client application in order to leverage a given framework feature or set of features. The generated source code could be useful in at least two important capacities. First, as tutorials, for the purpose of demonstrating to a developer how a feature is intended to be used. Second, it could be used as the basis of a software development tool that automatically generates the framework glue code and lets the application developer complete the model by mapping the remaining partial classes in the model to application specific classes.

74 As discussed in section 4.3, one important area where our method can be improved is the support for the parts of a software framework’s interface that is not expressed in source code. In the case of Spring, the software com- ponents managed by the framework are often described in XML as opposed to being programatically registered with the IoC container. Support for mod- elling the information contained in configuration files (whether they’re XML or not) would help better describe the ways a software framework can be cus- tomized in order to fulfil the needs of client applications. One way that this could be achieved is by introducing a new way of describing usage scenarios in addition to Message Views. Instead, the aspect could have a template de- scribing the necessary modifications to be introduced in a configuration file. The TouchRAM weaver would ignore these templates. However if we need to generate code from the aspect model, the code generator would make the necessary additions to the indicated configuration file. Therefore, the usage scenario in the RAM model must allow the user to specify the format of the configuration file that must be generated. 6.4 Final Remarks

We have presented our method for developing aspect oriented models for the interface of a software frameworks. Once the concerns listed in section 6.3 are addressed, we believe that our method can become the basis of use- ful software engineering tools that can help reduce the initial learning curve associated with software frameworks and help increase developer productivity.

75 LIST OF REFERENCES

[1] Apriori algorithm implementation. https://github.com/asaini/ Apriori. [2] The python programming language. http://www.python.org/. [3] Understand tool homepage. http://www.scitools.com/index.php. [4] Wikipedia: Feature models. http://en.wikipedia.org/wiki/Feature_ model. [5] Spring documentation. http://www.springsource.org/ documentation, June 2013. [6] Tapestry 5: Principles. http://tapestry.apache.org/principles. html, June 2013. [7] Wisam Al Abed, Valentin Bonnet, Matthias Sch¨ottle,Engin Yildirim, Omar Alam, and J¨orgKienzle. Touchram: A multitouch-enabled tool for aspect-oriented software design. In Krzysztof Czarnecki and G¨orelHedin, editors, Software Language Engineering, volume 7745 of Lecture Notes in Computer Science, pages 275–285. Springer Berlin Heidelberg, 2013. [8] Omar Alam and J¨orgKienzle. Concern-oriented software design. In Proceedings of the ACM/IEEE 16th International Conference on Model Driven Engineering Languages and Systems. Springer, to be published. [9] Elisa Baniassad and Siobhan Clarke. Theme: An approach for aspect- oriented analysis and design. In Proceedings of the 26th International Conference on Software Engineering, pages 158–167. IEEE Computer So- ciety, 2004. [10] Michelene TH Chi, Miriam Bassok, Matthew W Lewis, Peter Reimann, and Robert Glaser. Self-explanations: How students study and use ex- amples in learning to solve problems. , 13(2):145–182, 1989. [11] Thomas Cottenier. The motorola weavr: Model weaving in a large in- dustrial context. In in Proceedings of the International Conference on AspectOriented Software Development, Industry Track, 2006.

76 77

[12] Thomas Cottenier, Aswin Van Den Berg, and Tzilla Elrad. Joinpoint inference from behavioral specification to implementation. In ECOOP 2007–Object-Oriented Programming, pages 476–500. Springer, 2007. [13] Krzysztof Czarnecki and Andrzej Wasowski. Feature diagrams and logics: There and back again. In Software Product Line Conference, 2007. SPLC 2007. 11th International, pages 23–34. IEEE, 2007. [14] Tzilla Elrad, Mehmet Aksit, Gregor Kiczales, Karl Lieberherr, and Harold Ossher. Discussing aspects of aop. Communications of the ACM, 44(10):33–38, 2001. [15] Mohamed Fayad and Douglas C. Schmidt. Object-oriented application frameworks. Commun. ACM, 40(10):32–38, October 1997.

[16] Martin Fowler. Pojo. http://www.martinfowler.com/bliki/POJO. html. [17] Martin Fowler. Inversion of control containers and the dependency in- jection pattern. http://www.martinfowler.com/articles/injection. html, 2004. [18] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. : elements of reusable object-oriented software. Addison-Wesley Longman Publishing Co., Inc., Boston, MA, USA, 1995. [19] Evelyn Nicole Haslinger, Roberto Erick Lopez-Herrejon, and Alexander Egyed. On extracting feature models from sets of valid feature combina- tions. In Proceedings of the 16th international conference on Fundamental Approaches to Software Engineering, FASE’13, pages 53–67, Berlin, Hei- delberg, 2013. Springer-Verlag. [20] Florian Heidenreich, Jan Kopcsek, and Christian Wende. Featuremapper: mapping features to models. In Companion of the 30th international conference on Software engineering, ICSE Companion ’08, pages 943–944, New York, NY, USA, 2008. ACM. [21] Abbas Heydarnoori, Krzysztof Czarnecki, Walter Binder, and T Bar- tolomei. Two studies of framework-usage templates extracted from dy- namic traces. 2011. [22] Abbas Heydarnoori, Krzysztof Czarnecki, and Thiago Tonelli Bar- tolomei. Supporting framework use via automatically extracted concept- implementation templates. In Sophia Drossopoulou, editor, 23rd Eu- ropean Conference on Object-Oriented Programming (ECOOP), volume 5653 of Lecture Notes in Computer Science, pages 344–368, Genova, Italy, 07/2009 2009. Springer-Verlag, Springer-Verlag. 78

[23] Daqing Hou. Investigating the effects of framework design knowledge in example-based framework learning. In , 2008. ICSM 2008. IEEE International Conference on, pages 37–46, 2008. [24] The Carnegie Mellon Software Engineering Institute. Software product lines. http://www.sei.cmu.edu/productlines/. [25] Recommendation Z ITU-T and Z Recommendation. 100: Specification and description language (sdl). International Telecommunication Union, 2000. [26] Ralph E. Johnson. Frameworks = (components + patterns). Commun. ACM, 40(10):39–42, October 1997. [27] Rod Johnson. Expert one-on-one J2EE design and development. Wrox, 2004. [28] K. C. Kang, S. G. Cohen, J. A. Hess, W. E. Novak, and A. S. Peterson. Feature-oriented domain analysis (foda) feasibility study. Technical re- port, Carnegie-Mellon University Software Engineering Institute, Novem- ber 1990. [29] J¨orgKienzle, Wisam Al Abed, Franck Fleurey, Jean-Marc J´ez´equel,and Jacques Klein. Aspect-oriented design with reusable aspect models. In Transactions on aspect-oriented software development VII, pages 272–320. Springer, 2010. [30] J¨orgKienzle, Wisam Al Abed, and Jacques Klein. Aspect-oriented multi- view modeling. In Proceedings of the 8th ACM international conference on Aspect-oriented software development, AOSD ’09, pages 87–98, New York, NY, USA, 2009. ACM. [31] D. Kirk. Understanding object-oriented frameworks. PhD thesis, Depart- ment of Computer and Information Sciences, University of Strathclyde, 2005. [32] MEILIR AUTOR PAGE-JONES. Fundamentals of object-oriented design in UML. Addison-Wesley Professional, 2000. [33] D. L. Parnas. On the criteria to be used in decomposing systems into modules. Commun. ACM, 15(12):1053–1058, December 1972. [34] Dhanji R Prasanna. Dependency Injection. Manning Publications Co., 2009. [35] Anand Rajaraman and Jeffrey David Ullman. Mining of massive datasets. Cambridge University Press, 2012. 79

[36] Matthias Sch¨ottle.Aspect-Oriented Behavior Modeling In Practice. Un- published M.Sc. Thesis, Department of Computer Science, Karlsruhe Uni- versity of Applied Sciences, Karlsruhe, Germany, September 2012. [37] Forrest Shull, Filippo Lanubile, and Victor R. Basili. Investigating read- ing techniques for object-oriented framework learning. IEEE TRANSAC- TIONS ON SOFTWARE ENGINEERING, 26:2000, 2000. [38] M. Voelter and I. Groher. Product line implementation using aspect- oriented and model-driven software development. In Software Product Line Conference, 2007. SPLC 2007. 11th International, pages 233–242, 2007.