Enterprise Application Development
using Dependency Injection
and Aspect-Oriented Programming
S T E F A N P E T T E R S S O N
Master of Science Thesis
Stockholm, Sweden
2009Enterprise Application Development
using Dependency Injection
and Aspect-Oriented Programming
S T E F A N P E T T E R S S O N
Master’s Thesis in Computer Science (30 ECTS credits) at the School of Computer Science and Engineering Royal Institute of Technology year 2009
Supervisor at CSC was Serafim Dahl Examiner was Karl Meinke TRITA-CSC-E 2009:077 ISRN-KTH/CSC/E--09/077--SE ISSN-1653-5715
Royal Institute of Technology
School of Computer Science and Communication
KTH CSC SE-100 44 Stockholm, Sweden URL: www.csc.kth.se
Abstract
Dependency injection and aspect-oriented programming (AOP) are not related but have the common goal of improving design, implement-ation and maintenance of software projects.
As part of the development of an enterprise application in Java based on the Spring Framework these two technologies are considered and evaluated based how they affect the design, maintainability and testing of the project.
The report concludes that the use of dependency injection is easy to adopt and promotes design of less coupled modules with higher cohesion. Dependency injection is especially beneficial in regard to unit-testing by providing simplifying the use mockup objects.
Aspect-oriented programming provides an approach to develop and manage cross-cutting concerns in a more modularized way than conven-tional object-oriented programming. However, it requires the developer to think about the design in a new way in order to identify and design aspects, thus introducing a steep learning curve to both the developer as well as someone maintaining the project after deployment.
Användandet av dependency injection och
aspekt-orienterad programmering vid
applikationsutveckling
Dependency injection och aspect-oriented programming (AOP) är i sig inte direkt relaterade, men de har ett gemensamt mål i att underlätta och förbättra design, implementation och underhåll av mjukvaruprojekt. Som del i utvecklandet av en enterprise-application i Java baserad på Spring Framework har dessa två teknologier utvärderats baserat på hur de påverkar design, underhåll och testning under utvecklingsarbetet. Rapportens slutsats är att dependency injection är relativt lätt att införa och gynnar en design med färre och tydligare beroenden samt mer enhetlig kod. Depenceny injection fanns vara speciellt fördelaktigt i samband med enhetstestning, bland annat då införandet av mockup objekt underlättades.
Aspect-oriented programming är en programmeringsmetodologi som tillhandahåller ett sätt att utveckla och hantera så kalladecross-cutting concerns, aspekter av ett program som påverkar många olika bestånds-delar, på ett mer modulariserat sätt än konventionell objektorienterad programmering. Dock innebär detta ett ganska annorlunda sätt att an-gripa design och identifiera lämpliga kandidater som kan implemente-ras som aspekter. Detta gör att tröskeln för att börja använda aspect-oriented programming är relativt hög, både för utvecklaren så väl som för den som skall underhålla källkoden i efterhand.
Contents
1 Introduction 1
1.1 Problem Background . . . 1
1.2 Purpose . . . 1
1.3 Problem definition . . . 2
1.4 Limitations and Scope . . . 2
1.5 Outline . . . 2 2 Theory 5 2.1 Spring Framework . . . 5 2.2 Dependency Injection . . . 6 2.2.1 Background . . . 6 2.2.2 Introduction . . . 6 2.2.3 Example . . . 7
2.2.4 Dependency Injection in Spring Framework . . . 8
2.2.5 Other Dependency Injection Frameworks . . . 9
2.3 Aspect-Oriented Programming . . . 9
2.3.1 Background . . . 10
2.3.2 Introduction . . . 10
2.3.3 Terminology . . . 11
2.3.4 Example . . . 13
2.3.5 Aspect-Oriented Programming Frameworks . . . 15
3 Method 19 3.1 Overview . . . 19 3.1.1 Literature Study . . . 19 3.1.2 Requirements Analysis . . . 20 3.1.3 Design . . . 20 3.1.4 Development . . . 20 3.1.5 Evaluation . . . 21 3.2 Alternative Methods . . . 21 3.3 Tools . . . 21 4 Application Overview 23
4.3 Actors . . . 24 4.4 Process Overview . . . 24 4.4.1 Advertisement . . . 25 4.4.2 Receive Application . . . 25 4.4.3 Selection . . . 25 4.4.4 Communication . . . 25 4.4.5 Interview . . . 26 4.4.6 Response . . . 26 4.5 Requirements . . . 26 4.5.1 Non-Functional Requirements . . . 26 4.5.2 Additional Requirements . . . 27 4.6 User Interface . . . 27
5 Architecture and Design 29 5.1 Architecture . . . 29 5.1.1 Application Server . . . 29 5.1.2 Data Storage . . . 29 5.1.3 Data Access . . . 30 5.1.4 Business Layer . . . 30 5.1.5 Presentation Layer . . . 30 5.1.6 Rendering . . . 31 5.1.7 Build Tool . . . 31 5.2 Design . . . 31 5.2.1 Application Design . . . 31 5.2.2 Dependency Injection . . . 33 5.2.3 Aspect-Oriented Programming . . . 34 6 Evaluation 35 6.1 Dependency Injection . . . 35 6.1.1 Design . . . 35 6.1.2 Maintainability . . . 36 6.1.3 Testing . . . 37 6.2 Aspect-Oriented Programming . . . 38 6.2.1 Design . . . 38 6.2.2 Maintainability . . . 39 6.2.3 Testing . . . 41 7 Conclusion 43 7.1 Dependency Injection . . . 43 7.2 Aspect-Oriented Programming . . . 43 7.3 Future Work . . . 44
Bibliography 45
Appendices 46
A References 47
A.1 Tools . . . 47
Chapter 1
Introduction
1.1
Problem Background
Dependency injection and aspect-oriented programming are two technologies that have gained popularity lately, partly because they are important parts of wide spread application frameworks like the Spring Framework. Although the two tech-nologies are not related to each other they both have a common goal of improving design, implementation and maintenance of software development projects. The approach to achieve this is to provide a framework that reduces coupling between objects and, respectively, allow modularization of so-called cross-cutting concerns.
1.2
Purpose
However, what are the consequences of using dependency injection and aspect-oriented programming in a real-world project? How does it affect the design and architecture of a system? How is development and testing impacted? Are the technologies fire-and-forget silver bullets or is there more to it?
It is along those lines the purpose of this Master’s thesis is formulated.
The purpose of this Master’s thesis is to evaluate the consequences of intro-ducing and using dependency injection and aspect-oriented programming from a practical perspective in a real-world project. A real-world project in this context is a time-boxed project with limited resources and a real customer including unclear specifications and changing demands.
The background of this real-world project is to develop a prototype of a web-based enterprise application that supports the Human Resource department at the company Avalanche Studios during the recruitment process of new employees. The purpose of the system is to automate parts the recruitment process or make them more effective by supporting the recruiters from a job application is received until a decision is made about a candidate.
The system is Java based and developed using the Spring Framework. The
analysis and producing an architecture and design for the system. The second part implements the design using agile methods. The project is then evaluated according to the problem definition.
1.3
Problem definition
Considering the purpose of this Master’s project a number of questions have been formulated that are pivotal during the project and of interest to address in the resulting evaluation section.
What does the use of dependency injection and aspect-oriented programming mean for application design?
• In what areas are dependency injection and aspect-oriented programming
used?
• How is the design affected in terms of modularization and overall code
archi-tecture?
What does the use of dependency injection and aspect-oriented programming mean for application development?
• How is refactoring and maintainability affected?
• How is testing, especially automated unit testing, affected?
1.4
Limitations and Scope
Although dependency injection and aspect-oriented programming are techniques applicable to many different environments, applications and programming languages the focus is on Java, the Spring Framework and the particular application developed as part of this Master’s project.
One of the most important aspects in development of enterprise applications are how they are maintained during time after initial deployment, especially by other developers than the original. Due to practical reasons this is not covered in this Master’s project even if related areas such as design are discussed.
The requirements gathering phase of the project does result in far more func-tionality than what is possible to implement in the prototype application. However, in order to achieve a real-world project the design and architecture is developed with all requirements in mind, although only a subset will actually be implemented.
1.5
Outline
1.5. OUTLINE
Chapter 1: Introduction (this chapter) - provides background of the thesis and a problem definition.
Chapter 2: Theory - describes the theory behind dependency injection and aspect-oriented programming with emphasize on Spring Framework.
Chapter 3: Method - describes how the thesis work is structured into different phases involving research, design, implementation and evaluation.
Chapter 4: Application Overview - presents an overview including background and requirements of the application that is developed.
Chapter 5: Architecture and Design - describes the architecture behind the ap-plication and how it is designed and implemented.
Chapter 6: Evaluation - evaluates the design and implementation in regard to the use of dependency injection and aspect-oriented programming.
Chapter 7: Conclusion - draws conclusion based on the previous evaluation and suggests possible future work.
Chapter 2
Theory
This chapter first introduces the Spring Framework which is the framework used by the application developed as part of this thesis, next dependency injection and aspect-oriented programming will be described in detail.
The reader is assumed to have basic knowledge of design and architecture in regard to software development.
2.1
Spring Framework
The application developed as part of this Master’s project will be built using the Spring Framework.
Spring Framework is an open source application framework for Java originally developed by Rod Johnson and commercially supported by the company Spring-Source.
The fundamental mission statement of the Spring Framework is to make enter-prise application development easier and less complex, especially in comparison to J2EE [10].
The aim of the Spring Framework is that it should be largely non-invasive and applications developed should not depend on the Spring API. In line with this aim Spring Framework does support integration with a range of other solutions, such as Hibernate and other object-relational mapping solutions as well as web application frameworks like Struts. This makes it easy to use only parts of the Spring Framework together with other existing solutions.
The Spring Framework provides a lot of functionality divided into modules which may be seen as smaller frameworks by themselves. Modules include frameworks for data access, transaction management and security to support for remote manage-ment, messaging and testing.
What is most interesting among these modules are the inversion of control con-tainer that provides configuration of application components using dependency in-jection and the aspect-oriented programming framework. The support for depend-ency injection and aspect-oriented programming in the Spring Framework will be
described further in the corresponding sections about these topics below.
2.2
Dependency Injection
Dependency injection is introduced in this section including examples. How de-pendency injection is supported by the Spring Framework is explained followed by a brief overview of other dependency injection frameworks.
2.2.1 Background
Dependency injection originates from the concept of inversion of control. The point of inversion of control is to achieve looser coupling and make modules more reusable by letting a container or framework take responsibility of the flow of control of an application [9]. That is, inverting the flow of control compared to traditional architecture, hence the name. Dependency injection is a special form of inversion of control where it is the acquisition of dependencies that is inverted. The term dependency injection was coined by Martin Fowler in 2004 [5].
2.2.2 Introduction
Using a dependency injection framework the responsibilities of construction, wiring and assembly of objects are removed from the clients or services themselves and instead provided by the framework, thus inverting the flow of control.
Instead of making an object being responsible of getting hold of a service using a factory pattern [6], service locator or creating it the object may instead simply provide a property that holds the reference that gets automatically set by the frame-work when the object is created.
There are three different types of dependency injection styles; constructor injec-tion, setter injection and interface injection. The difference between these types is how they provide an object with references to dependencies.
• Constructor injection: references to dependencies are provided through the
class constructor.
• Setter injection: the object exposes a setter method that the dependency
injection framework uses to inject the dependency.
• Interface injection: the object implements an interface that contains a method
that allows the object receive a reference to the dependency.
2.2. DEPENDENCY INJECTION
2.2.3 Example
An example will be given using a conventional approach followed by examples using dependency injection. The examples are unrealistically small but concise enough to illustrate what is happening.
The example is a class representing a car. Characteristics (data) of the car like weight, dimensions, engine type and so on are read from an external source and
assigned to the object. The classes reading the data all implements theDataReader
interface. The car object may look like this (only the relevant code is included): public class Car {
private DataReader reader;
... // other variables representing the car
public Car() {
DataReader reader = new DataFileReader("cardata.txt"); }
}
It is the car object that creates the data reader explicitly usingnew. A somewhat
more flexible approach would be to use the factory design pattern but the main problem that the car itself is responsible for the type of data reader still remains.
Refactoring the car class to use dependency injection using the constructor it would look like:
public class Car {
private DataReader reader;
... // other variables representing the car
public Car(DataReader reader) { this.reader = reader; }
}
The significant difference with this solution is that the dependency is injected into the Car class; the Car class does not know, and should not know, what kind of data reader it gets.
Using setter injection the data reader property is set using a setter method after the object is created instead of as a constructor parameter.
public class Car {
private DataReader reader;
... // other variables representing the car
public Car() { }
public void setReader(DataReader reader) { this.reader = reader;
} }
Using dependency injection neither class (Car or DataReader) need to be aware of or explicitly ask for each other. The Car class simply needs to accept a data
reader object and does not need any logic of how to create a data reader class, allowing the remaining code to focus on the ”business logic” instead of including boilerplate infrastructure code for wiring and construction of dependencies [19].
What is left out of these examples is how the dependency injection is configured. This depends on the dependency injection framework and may be done using con-figuration files, annotations or programmatically. In the next section examples are given for using dependency injection in Spring Framework.
2.2.4 Dependency Injection in Spring Framework
Continuing the example in the previous section the next thing to do is configuring the wiring of the objects. In the Spring Framework the most common way to do this is using XML-files [11]. As of version 2.5 of the Spring Framework it is also possible to use annotations to configure dependency injection.
In the example a DataReaderclass and a Carclass needs to be configured. An
example of the XML-configuration (with XML header omitted for clarity) follows below.
<bean id="filereader" class="se.kth.spett.di.DataFileReader"> <constructor-arg value="cardata.txt"/>
</bean>
<bean id="car" class="se.kth.spett.di.Car"> <property name="reader" ref="filereader"/> </bean>
The id is used to identify the object (bean) and the class field specifies what
class to instantiate. In the example a DataFileReader instance is created using
constructor injection to set the source file.
The Car object is using setter injection to automatically set a reference upon
creation to the file reader object. This is done by referencing the previously specified idfilereader.
The following code example shows how to get a reference to the Car instance
using aBeanFactory.
package se.kth.spett.di;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.code.io.FileSystemResources;
public class Example {
public static void main(String[] args) throws Exception { BeanFactory factory =
new XmlBeanFactory(new FileSystemResource("config.xml"));
Car car = (Car) factory.getBean("car");
car.doStuff(); }
2.3. ASPECT-ORIENTED PROGRAMMING
Using the getBean() method of the BeanFactory object with the previously
defined id as an argument a reference to the instance of theCarobject is retrieved.
When an object is defined the default scope is set to singleton. That means
that there will be a single shared object instance for all subsequent requests and
references. The opposite is the prototype scope where a new instance is created
each and every time the prototype is referenced. Additional types exist where it is possible to scope an object to the life-cycle of a HTTP request or session.
Auto-wiring
The Spring container does also supportauto-wiring between defined objects. Using
auto-wiring it is possible to automatically let Spring resolve how object should be wired by expecting the class itself using either property name or property type.
With auto-wiring it is possible to significantly reduce or eliminate the XML-based wiring configuration. The disadvantage is that it is harder to see the rela-tionships between objects since there is no explicit configuration anywhere.
It is possible to combine auto-wiring with explicit wiring.
2.2.5 Other Dependency Injection Frameworks
Some of the other most popular Java dependency injection frameworks are briefly mentioned here.
Guice1 is an open source dependency injection framework for Java 5 developed by Google. Guice exclusively uses annotations for wiring dependencies.
Another framework is PicoContainer2 that instead of annotations or XML-files
provides an API to programmatically configure the wiring of objects.
EJB 3 does support dependency injection of two types; field injection and setter injection [17]. Field injection allows the container to inject a reference to a private variable without any public setter method.
2.3
Aspect-Oriented Programming
This section gives an overview of aspect-oriented programming (AOP), starting with some background information and an introduction of what kind of problems it attempts to solve. Next the terminology used is explained followed by a concrete example of aspect-oriented programming applied to provide a solution for a typical cross-cutting concern.
Finally, AOP frameworks are described in general, with a particular focus on the aspect-oriented programming in the Spring Framework.
1
Google Guice: http://code.google.com/p/google-guice/
2
2.3.1 Background
Methodologies for programming computers have evolved to make developing soft-ware more efficient. The introduction of procedural programming is a big step for-ward compared to using machine-level languages. Procedural programming evolved and object-oriented programming is now the de facto standard for most new soft-ware development projects [15].
Object-oriented programming introduced object abstraction and makes it easier
to model common behavior and encapsulate it in a modular way.
Modulariza-tion makes a system more flexible, easier to maintain and quicker to develop [18]. However, many programming problems are of such type that neither object-oriented programming nor procedural programming does provide a way to sufficiently design and implement these cross-cutting concerns [13].
This often leads to compromises where code for the particular concern is being scattered through-out several modules. This result in code tangling that makes not only the implementation of the concern itself, but all modules affected by it, more difficult to develop and maintain [13].
These types of problems are calledcross-cutting concerns, since they cut across
different modules, and that is what aspect-oriented programming attempts to solve
by providing a way to separate these concerns into modularized aspects.
2.3.2 Introduction
An example featuring a simplified hotel management system will be used to give an introduction to aspect-oriented programming and what it attempts to solve. The hotel management system is used by the hotel staff to book rooms for guests, reserve tables at the dinner restaurant and so on.
At first glance the module (or class) responsible for booking a room seems pretty straight forward. First the availability of a room is checked, if it is vacant during the period the guest would like to stay then go ahead and reserve the room for that particular period.
However, not anyone in the staff should be able to book a room and hence a security check is needed to verify that the current user actually has the authorization to perform this task.
In addition, every task needs to be logged in a database so it is possible to see who did what and when, as well as statistics for the hotel management.
Inserting method calls to provide security and logging in the room booking method is simple, but it adds external dependencies to other modules and thus making the room booking module coupling tighter. In the same way it lowers the module cohesion since the room booking module must now also be responsible for user authorization and to trigger logging of the task.
Figure 2.1 illustrates how the room module invokes the API of the logging and security modules.
2.3. ASPECT-ORIENTED PROGRAMMING Logging module Security module bookRoom(...) Room module API calls
Figure 2.1. Logging and security implemented in an non aspect-oriented way. The room module is responsible for invoking the API of the logging and security modules.
the sauna to reserving dinner tables and managing staff vacations. It is easy to see that concerns such as security and logging must be adhered to in many modules, scattering calls to security and logging functionality all over the system. Security and logging are typical examples of cross-cutting concerns.
These types of cross-cutting concerns are what aspect-oriented programming attempts to solve.
In aspect-oriented programming cross-cutting concerns such as security and
log-ging may be modularized intoaspects. An aspect may be configured to automatically
be executed based on a simple set of rules to remove the responsibility from each module, class or method it will be applied to.
As an example a security aspect may be automatically executed before every
call to a method with a name that starts with book(e.g. bookRoom(...)). It then
only executes the invoked method if the current user is authorized.
Figure 2.2 illustrates the room booking implemented using aspect-oriented pro-gramming.
Using aspect-oriented programming code scattering and code tangling is reduced since the booking modules now only contain their core logic for booking and not calls to facilitate security and logging. This results in lower coupling and higher cohesion thus improving modularization.
2.3.3 Terminology
To be able to discuss aspect-oriented programming some of the most fundamental parts of the vocabulary need to be described more in detail.
Even though the terms may be implemented in different ways and supported to various degrees depending on framework, they are general to aspect-oriented
Logging aspect Security aspect bookRoom(...) Room module Logging module Security module Automatically woven calls API calls
Figure 2.2. Logging and security implemented using aspect-oriented programming. The aspects define when and how to invoke the logging and security API without the need for any calls from the room module.
programming as a whole. Advice
Anadvice describeswhat to do when an aspect is applied. It contains the code that performs the actual logic that should be carried out. As an example, if the purpose of the aspect is to log events that are executed in an application the advice will contain the code that results in the appropriate string being written to the log file. An advice can be executed before, after or around join points (which is described next). It may replace the code of a join point, or even bypass it.
Join point
Join points are all possible places in the code where an advice may be executed. They are called join points because they represent points in code where an advice may be joined (or plugged in).
Possible join points may be method calls, construction of objects, an exception being thrown or when a field is modified. What different types of join points that are supported vary between different aspect-oriented programming frameworks.
In the logging example used in the advice description, join points would be all possible locations in the code where the logging advice may be triggered.
Pointcut
Apointcut answer the question ofwhere an advice should be executed by specifying a set of join points. Pointcuts specifies join points usually through class or method
2.3. ASPECT-ORIENTED PROGRAMMING
names, either explicitly or by using regular expression patterns.
Exactly how pointcuts are expressed vary between different framework imple-mentations [22]. Some does also allow the creation of dynamic pointcuts that depend on runtime decisions; such if an advice should be applied depending on the value of a method parameter.
Continuing the logging example a pointcut decides where logging should be done (out of all possible join points), for example when methods starting with the string
book are called.
The most common types of pointcuts includebefore,after andaround. The first
two are triggered just before and after a method is invoked, while thearound advice
encapsulates a method call and therefore allows code to be executed both before and after, including skipping the call completely.
Introduction
Anintroduction enables the ability to add new methods or attributes to an already existing object. This means it is possible to give existing classes new behavior
without changing them. The concept of introductions is analogous with mixins [3]
popular in languages like Python and Ruby.
Aspect
The central unit where advice, pointcuts and introductions are combined is called anaspect. Beside these aspect-oriented specific details it may also contain variables, methods and nested class members, just like a normal class in Java.
An aspect in the logging example defines everything there is to know about it, including where logging should be applied (pointcuts) and when and how the logging should be done (advice).
Target
Thetarget is the object that the aspect is applied to.
Weaving
Weaving is the process of combining aspects and the target objects into a complete system. Aspects are woven into objects at the specified join points.
The weaving itself may be done in several ways; at compile time, at classload or during runtime.
2.3.4 Example
The following examples are extremely simplified and contain no business logic so the execution flow is easy to see. The purpose is to give a basic example of how
aspect-oriented programming looks like and how it is different compared to pure object-oriented programming.
The main class is Room that contains the bookRoom() method that takes an
integer that identifies what room to book. The main method simply makes two
calls to illustrate the execution flow when invoking thebookRoom() method.
package se.kth.spett.aspectj;
public class Room {
public void bookRoom(int id) {
System.out.println("Room " + id + " booking logic performed"); }
public static void main(String[] args) { Room room = new Room();
room.bookRoom(1); room.bookRoom(0); }
}
Next is the Loggingaspect that performs logging before and after a call to the
bookRoom()method in the Room class. The pointcut definitionlogging applies to
all public methods in theRoomclass starting with ”book”, no matter of return value
and accepted parameters.
Two join points are defined to be executed before and after theloggingpointcut
is triggered.
package se.kth.spett.aspectj;
public aspect Logging {
public pointcut logging(): call(public* se.kth.spett.aspectj.Room.book*(*));
before(): logging() { System.out.println( "Entering: " + thisJoinPointStaticPart.getSignature().getName() ); } after(): logging() { System.out.println( "Exiting: " + thisJoinPointStaticPart.getSignature().getName() ); } }
The Security aspect has a similar pointcut but applies an around advice and only conditionally proceeds with the original call. The unrealistically simplified code in the example may be replaced with logic that verifies if the current user has permission to book the particular room. If not, the call will not proceed (as
illustrated in the example wheniis equal to zero).
package se.kth.spett.aspectj;
public aspect Security {
2.3. ASPECT-ORIENTED PROGRAMMING
void around(int i): access() && args(i) { if (i == 0) {
System.out.println("Blocked call when i == " + i); return; } else { proceed(i); } } }
Running this trivial example compiled with AspectJ produces the following out-put:
Entering: bookRoom
Room 1 booking logic performed Exiting: bookRoom
Entering: bookRoom Blocked call when i == 0 Exiting: bookRoom
Each call is logged both before and after a call by the Logging aspect and in
the case whenbookRoom()is called with 0 (zero) as argument the called is blocked
by the Securityaspect.
2.3.5 Aspect-Oriented Programming Frameworks
Depending on the framework used to enable aspect-oriented programming the fea-tures supported may be different. Differences include what kind of join points that are exposed, how pointcuts are defined, and how and when weaving take place.
The Spring Framework is the foundation of the application developed as part of this Master’s project and the built-in support for aspect-oriented programming in the framework will be used. AspectJ is the most widely adopted framework for aspect-oriented programming [12].
These frameworks are briefly described below with an emphasis on how aspect-oriented programming in Spring is different from AspectJ.
Spring AOP
The purpose of the support for aspect-oriented programming in the Spring Frame-work is to allow users to implement their own aspects in a simple and easy way and to provide declarative enterprise services (most importantly transaction man-agement) in the framework itself [11].
Therefore Spring AOP is not, and does not intend to be, a full-blown AOP framework such as AspectJ.
Advice in Spring is written as a standard Java class and pointcuts are specified in a XML configuration file or by using annotations. The weaving in Spring is done in runtime by wrapping the target object with a proxy class. When a call is made the proxy class poses as the target and intercepts calls where advice should be applied.
Because of this there is no need for a special compilation process, everything is pure Java and applications may be used directly in a J2EE web container or application server.
The most apparent limitation of Spring AOP is that it does only support method join points. The possible types of advice available are:
• Before advice: Advice is executed before a method but may not prevent
exe-cution of the method unless an exception is thrown.
• After returning advice: Advice is executed after a method returns normally.
• After throwing advice: Advice is executed if a method exits by throwing an
exception.
• After (finally) advice: Always executed after a method has executed.
• Around advice: Surrounds a join point and may perform custom behavior
before and after a method invocation, it may also decide to skip executing the called method altogether.
If more fine-grained advice than what is possible with method join points is needed it is also possible to use AspectJ within the Spring Framework.
AspectJ
AspectJ is the most widely used standard for aspect-oriented programming and was a product of the research led by Gregor Kiczales at Xerox PARC [13]. The first public version of AspectJ was released in 2001. AspectJ is now an open-source project in the Eclipse Foundation [1].
AspectJ is an extension to Java where the AspectJ language is used to specify pointcuts and how they should be applied and Java is used to implement the core concerns.
Every Java program is a valid AspectJ program and the AspectJ compiler pro-duces standard Java class files that may be executed by any compliant Java virtual machine. AspectJ supports compile-time weaving, post-compile weaving (weaving aspects into already compiled classes) and time weaving (LTW). With load-time weaving the weaving takes place when Java virtual machine uses the class loader to load the class.
EJB 3
EJB 3 (Enterprise JavaBeans), part of JavaEE 5, supports aspect-oriented
program-ming in terms of interceptors. The AOP features supported are limited; however,
they don’t require the complexity related to introducing a full-fledged AOP frame-work like AspectJ [17].
Interceptors are objects that are automatically executed when a method is in-voked in an EJB object. The type of pointcut supported is the around advice,
2.3. ASPECT-ORIENTED PROGRAMMING
that allow custom behavior to be executed at the beginning of a method, as well as after the method with the possibility to react to both return value and thrown exceptions.
Chapter 3
Method
This chapter describes the different stages of how the project was carried out fol-lowed by a short reflection on the method used with possible alternative methods.
The main purpose of this Master’s project is to evaluate the consequences of using dependency injection and aspect-oriented programming in a real-world pro-ject. Hence, the method resembles very much the process of a software development project at a company. Following the development phase an evaluation is conducted to recapitulate the questions put forward in the problem definition.
3.1
Overview
The sections below give an overview of the different stages of the project.
3.1.1 Literature Study
Initially a literature study was done with three goals in mind, although somewhat overlapping.
The first goal was to gather a basic knowledge of the fundamental technologies and tools used in the development of the prototype application. Most notable this involved reading books about the Spring Framework [23], Hibernate [2] and Java Enterprise design and development in general [10].
The second goal was to study the principles of dependency injection and aspect-oriented programming in general. Since they both are fundamental parts of the Spring Framework this was partly already covered. In order to get more general knowledge of application of the techniques outside the Spring Framework the liter-ature study was complemented with journal articles [24] and further reading about AspectJ [15].
The third and final goal was to gather knowledge about related academic work about the use and consequences of dependency injections and aspect-oriented pro-gramming. This part included reading the original paper published about aspect-oriented programming by Kiczales et al [13].
Worth noting is that there are a fairly large amount of published articles and papers about aspect-oriented programming while those about dependency injection (and inversion of control) is much more rare. This is no surprise since the use of dependency injection is more about introducing a design pattern [5] compared to the introduction of a new programming paradigm [8], where the latter has received much more interest from the academic world.
3.1.2 Requirements Analysis
A requirements analysis of the application to be developed, the recruitment system, was done by meetings, discussions and interviews with users and stakeholders of the system. The focus of this phase was to understand the recruitment process and identify where in the process the most benefit of a software system may be achieved. This approach was chosen, instead of asking for a set of feature specifications, because users usually don’t understand what they want or have a clear idea of their requirements [16]. The gathered requirements were put together and presented to verify their validity.
3.1.3 Design
Based on the identified features that are deemed as feasible to be part of the proto-type an overall architecture and design of the application was done. The goal of the design was to achieve best practices using the Spring Framework [23] and software design in general. What is important to note is that design decisions were made based on factors involving requirements, feature scope, time constraints, previous knowledge and expertise. Although the use of dependency injection and aspect-oriented programming was always in mind, these principles was only used where it made sense rather than being forcefully applied everywhere just because they are the topic of this Master’s thesis.
3.1.4 Development
The development phase of the project was divided into foursprints (time periods)
of about two weeks realized in what might resemble a one-man Scrum project [14].
What this basically means is that a product backlog consisting of the identified
features is created. For each sprint the features with the highest priority (from a business perspective) is picked to be included in the backlog for the upcoming
sprint (sprint backlog). When new requirements arise, both in terms of identified
new features or fixes/additions to existing features, they are added to the product backlog.
Although the Scrum methodology is much more than that [20] it served as a good way to prioritize what should be done during the development phase.
Actual implementation was done focusing on getting a feature to work in the most basic way and then refactoring the code as needed. Adequate testing code
3.2. ALTERNATIVE METHODS
for unit testing and automatic integration testing were implemented as part of each feature.
3.1.5 Evaluation
Finally the evaluation phase addresses the questions presented in the problem defin-ition. Although the evaluation step is the last, it does permeate the whole process from requirements gathering to development and deployment.
3.2
Alternative Methods
The method described that will be used is based on a subjective criterion and has a qualitative rather than quantitative approach. This is something that needs to be considered in the evaluation phase since background and experience of the author in combination with the subjective nature of the evaluation is something that will be a factor even if the goal is to minimize it as much as possible.
The choice of method is largely the result of time and resource constraints and the circumstances around this particular Master’s thesis work.
Alternative methods would include developing two systems according to the same requirements, one using aspect-oriented programming and dependency injec-tion and another only using an object-oriented approach. Using such a method it may be easier to identify the differences and consequences of each approach.
Building on this alternative method a more quantitative and empirical method would involve several developers assigned to develop the different approaches. To empirically evaluate aspects like readability, understandability and maintainability of the different approaches a set of other developers may be tasked to perform changes on the different systems. Also defined measures like CBM (coupling between modules), LCO (lack of cohesion in operations) and RFM (response for a module) may be used for comparison [4] together with metrics to indicate system size like non-comment lines of code and number of modules.
3.3
Tools
Several tools, all free open source, were used during the development of the
proto-type application1. As a development environment NetBeans IDE 6.1 was used with
Maven 2 for build management. Unit testing was done using JUnit while Canoo WebTest was used for automated integration testing.
Subversion was used for version control and Hudson served as an automated continuous integration tool.
Primarily GlassFish was used as Java application server. Also Jetty, which is a lightweight servlet container, was used for testing.
1
Chapter 4
Application Overview
The real-world project the questions in the problem definition are applied to is the development of a web based recruitment system. The purpose of the system is to support the Human Resource department during the recruitment process, from receiving an application until a decision is made to hire or decline a candidate.
The purpose of this chapter is to describe the background, requirements, scope and interface of the system to give a better understanding of the project and what is developed.
4.1
Background
The recruitment process at Avalanche Studios is managed more or less manually using a simple Excel document to track status and keep information related to a candidate. With more than one recruiter and several technical specialists involved in the process this is getting out of hand in regard to communication (internal and with the candidate), managing data and files like portfolios and work examples, keeping relevant information in one place and so on.
Avalanche Studios is one of the largest game developers in Sweden developing games primarily for Xbox 360, Playstation 3 and PC. As of July 2008 there are about 160 employees at Avalanche Studios. Being a game developer means there are several categories of employees and candidates with slightly different requirements from a recruitment process perspective.
A programmer, 3D artist and producer need to be evaluated differently in the recruitment process because their discipline requires different skills (technical, aes-thetical, administrative, leadership, etc).
4.2
Goal
The main goal of the application is, in regard to the recruitment process, to support the Human Resource staff (the recruiters) during the whole recruitment process and make their work more effective. This is achieved by automating as many tasks as
Advertisement Receive
Application Selection
Communication
Interview Response
Figure 4.1. After an application is received the candidate is evaluated. The evalu-ation including selection, communicevalu-ation and interview is iterative, where a candidate usually is interviewed more than one.
possible in the recruitment process and by providing support for other activities by allowing the system to manage and distribute relevant information.
4.3
Actors
There are persons with different roles that will interact with the system. They are referred to in this document as candidates, recruiters and specialists.
• Candidate: The person applying for a position by sending in a resume and
other related information like a personal letter and portfolio.
• Recruiter: The person doing the recruitment including selecting candidates,
conducting interviews, and so on. There are multiple recruiters using the system and multiple recruiters may be involved in the recruitment process of a single candidate. The terms recruiter and user are used interchangeably in this document since the primary user of the application is a recruiter.
• Specialist: A person in the company with specialist knowledge (like an art
director or lead programmer) or in a management position that is involved in the recruitment process, primarily by giving feedback on the selection of candidates and conducting interviews. There are several specialists and they are different depending on candidate and position.
4.4
Process Overview
Figure 4.1 illustrates the different steps in the recruitment process. Although the process is generalized it does serve well as the starting point for a brief discussion about the result of the requirements gathering phase prior to development.
The intent is to give an understanding of how the application may support each step in the process rather than to specify individual requirements.
4.4. PROCESS OVERVIEW
4.4.1 Advertisement
Open positions are advertised on the company website. Publishing and editing posi-tions are managed by recruiters using an administrative interface of the application. The published positions are displayed on public pages that require no authen-tication. In order to integrate well with the existing company website the public pages must support a custom look and style.
4.4.2 Receive Application
A candidate applies for a position by submitting a form on a web page associated with the desired position. The candidate must fill in all mandatory questions like name and email address. Next the candidate uploads related files to the application like a curriculum vitae, personal letter and examples of previous work (if applicable). Once successfully submitted a candidate profile is created in the application. The candidate profile is the central place where all related information of the candidate is located.
A candidate profile may also be created from within the application itself by a recruiter in case when the recruitment process is initiated without an applica-tion through the web page. An example of this situaapplica-tion may be when there is a recommendation of a person who have not applied herself.
4.4.3 Selection
All candidates in the application may be sorted or searched based on different criteria to support the selection of candidates in the recruitment process. To allow for useful search queries a candidate is associated with a status and additional fields such as type of position as well as notes and reminders.
In the selection process other people in the company may be involved (special-ists). In order to facilitate their involvement and avoid duplicating the candidate profile (to send in an email as an example) a recruiter may give limited access to a specialist so the specialist may review information about a specific candidate and enter feedback.
4.4.4 Communication
All communication and discussions with a candidate should be logged and available for others as well as for archiving in case of later review. A candidate profile in the application does allow for notes in terms of log entries to be stored. A log entry may be created to associate information with a candidate together with a date and information about who created the log entry. This information is then visible to other recruiters reviewing the candidate.
Ultimately all communication would automatically be associated with a candid-ate, like an email conversation. This is possible by having the application interact
with an email server. However, this feature is considered out of scope due to the time constraints involved with a Master’s project.
4.4.5 Interview
The interview phase of the recruitment process is a way to get more information about a candidate to make a better selection of which candidates to proceed with and which to reject.
The application does support the interviewing in two ways. It does provide an easy way to review and print all information about a candidate using the candidate profile and after an interview is finished an evaluation and summary of the candidate based on the interview may be entered.
4.4.6 Response
The application may send out scheduled or on-demand emails to a candidate, mak-ing it possible for a recruiter to easily communicate a decision to the candidate in the recruitment process. This specific feature was asked for when there are many unqualified candidates applying for a position and they need to be rejected. Instead of rejecting them initially an email may be scheduled to communicate the decision at the same time as the period when applications are accepted has ended.
4.5
Requirements
The result of the requirements analysis includes far more functionality than what is possible to realize within the scope of a Master’s project. Only a subset of the identified features will be implemented as part of the prototype developed.
The main goal is not to include as many features as possible in the implement-ation as long as the scope of the applicimplement-ation is substantial enough to provide a foundation for evaluation and addressing the questions asked in the problem defin-ition.
The previous section discussing the recruitment process and how the application may support it is the result of discussions with staff from the Human Resource department over several meetings. In addition to those features there are some additional requirements and non-functional requirements discussed below.
4.5.1 Non-Functional Requirements
Some non-functional requirements were identified during the requirement analysis.
• When designing the application the top priority should be to keep it simple
to the user. Rather fewer and more generic features than a lot of specialized functionality.
4.6. USER INTERFACE
• No prior knowledge, expect basic web browser usage, on behalf of the users of
the application may be assumed.
• All components, including framework, libraries, development platform and
hosting services (database, application server, operating system, etc) must be free and require no license cost.
• The application should require no or little additional system maintenance
beside regular duties common to all hosting (backup, security patching).
4.5.2 Additional Requirements
User authentication and authorization is needed since recruiters, specialists and can-didates are all somehow interacting with the system but should have fundamentally different permissions in terms of what they may do and what information they may see.
To manage users of the application user administration functionality must be provided that allows creating, editing, disabling and removing users.
4.6
User Interface
The diagram in figure 4.2 illustrates a simplified overview of the different parts of the application from a user interface perspective.
The diagram is divided into two major sections. The internal (left) section contain the different views available to recruiters and specialists; hence users must be authenticated to access the internal pages of the application. Authentication is done using username and password. To the right is the public section which represents the pages accessible by candidates when applying for a position.
Positions: List Position View / Edit Candidates: List Candidate View / Edit User Administration User View / Edit Search Filter Log Reminders Attachments Roles Overview Statistics Positions: List Info Apply
Internal
Public
Chapter 5
Architecture and Design
This chapter describes the general architecture of the application and the different technologies used followed by a more detailed design of the implementation.
The intention is to give an overview of how the application has been implemented without dwelling on specific solutions only relevant to requirements applicable only in this particular case. In the same way, specific information about the use of third-party and framework modules is only briefly mentioned, instead of duplicating already existing framework reference documentation.
5.1
Architecture
The intention is to give an overview of which components are used with a brief description explaining what they are and their purpose in the application.
Figure 5.1 shows the general architecture with what components are used for the different layers to develop the application.
5.1.1 Application Server
To run the application GlassFish v2 is used. GlassFish is an open source applic-ation server for the Java Enterprise Edition (Java EE) platform headed by Sun Microsystems. It is also called Sun Java System Application Server 9.
Although GlassFish is a fully compliant Java EE 5 application server, not all features are required considering the feature set of the application that is within the scope of the prototype. A servlet container like Apache Tomcat or Jetty would also be possible to use.
5.1.2 Data Storage
Data is stored using MySQL which is a relational database management system. Due to the design and the data access layer of the application MySQL is not a requirement by itself and may be substituted by most other popular SQL database systems.
Rendering : JSP
Presentation Layer : Spring MVC
Business Layer : Spring Framework 2.5
Data Access (ORM) :Hibernate 3
Data Storage : MySQL 5
Application Server : GlassFish v2
Build :
Maven 2
Figure 5.1. Overview of components in application architecture.
5.1.3 Data Access
Persistence of objects and management of relational data is done using the Java Persistence API (JPA) with Hibernate as the Java persistence framework.
Hibernate is an object-relational mapping (ORM) framework for Java that makes it possible to map classes in Java to database tables.
5.1.4 Business Layer
At the core of the application is the Spring Framework that, among many other things, provides modules that facilitates dependency injection and aspect-oriented programming.
5.1.5 Presentation Layer
Spring MVC, the Model-View-Controller framework of the Spring Framework is used for web related logic and the presentation layer.
5.2. DESIGN
5.1.6 Rendering
JavaServer Pages (JSP) is used to render the actual view of the Model-View-Controller architecture provided by Spring MVC. Also a number of custom made and publicly available tag libraries was used, most notable those part of the Spring Framework. Additionally, Display Tag was used to enhance the display of tables in the application.
5.1.7 Build Tool
Apache Maven is a build automation tool somewhat similar in functionality to the more well-known Apache Ant. One key difference is that Maven may automatically download component and library dependencies from the Internet, making it easier to maintain a complex project.
5.2
Design
This section describes the overall design of the application in terms of how it is implemented. The general design is described followed by a discussion about the particular use of dependency injection and aspect-oriented programming in the ap-plication.
5.2.1 Application Design
The implementation design of the application is illustrated in figure 5.2. The
blocks with text in italic font are non-custom components (Spring MVC and Spring Security is part of the Spring Framework) and Hibernate is a component by itself. The fact that the implementation uses the Spring Framework may be imagined as another box encapsulating the whole figure.
As illustrated in the figure the security module of the Spring Framework called Spring Security is leveraged to provide authentication and security throughout the application.
What is described is the general implementation design of the application rather than details that only relates to specific functionality.
DAO
Data Access Objects (DAO) are used to abstract and encapsulate all access to the underlying persistence system and data base. All Hibernate specific code is located in Data Access Objects. Typically there is a DAO for each object in the domain model.
Spring MVC View Controller ServiceManager DAO Hibernate DB Model Model Spring Securit y
Figure 5.2. Cross-section diagram of application implementation design.
ServiceManager
It is in the service managers where all business logic code resides. Controllers use one or more service manager objects and each service manager object use one or more DAOs.
Model-View-Controller
The Model-View-Controller (MVC) architectural pattern is used to separate busi-ness logic from presentation in the web interface. This is implemented using the Spring MVC module that is part of the Spring Framework.
The model represents the actual content that is manipulated or displayed and the controller manages and determines what is to be displayed. The view is the actual rendering of the model.
5.2. DESIGN
In this application the model often resembles a persistent java bean. A controller is a servlet and the view is a JSP page.
A typical scenario is when a user clicks a link on a web page of the applica-tion. Then a HTTP GET request is made that is managed by a dispatch servlet. Depending on the URL the dispatch servlet forwards the request to the appropri-ate controller that populappropri-ates a model. The model is rendered using a view and ultimately displayed as a HTML page.
Design by Interface
To achieve decoupling, classes interact with each other using interfaces rather than
specific implementations in form of classes. This technique is called design by
in-terface [21].
The purpose with design by interface is to have looser coupling between different parts of the application and have less dependencies on specific implementations. The technique is applicable on both class part of the standard Java library as well as application specific classes.
As an example, by accepting a java.util.Map (which is an interface) as a
method parameter instead of ajava.util.HashMap (which is an implementation)
it is possible to replace the implementation of the map without breaking anything. This is possible since the dependencies exist only to the interface, and not the actual implementation.
This technique together with dependency injection is especially powerful. When performing unit testing mockup objects are inserted instead of full implementations. As long as they implement the correct interface the object that is tested will not know the difference.
5.2.2 Dependency Injection
Dependency injection, and the Inversion of Control container in the Spring Frame-work providing the dependency injection, is such a central part so it is used more or less throughout the whole application.
It is used to create objects, everything from DAOs to services and controllers, and configure them by using injection dependencies either using setters or in the constructor.
Here are some examples of how it is used. All DAO classes are instantiated and injected with a reference to the Hibernate session factory which enables persistence. Service implementations in the service layer are injected with the needed DAO instances and controllers are injected with the requested services.
Beside the injection of references to other objects it is used for property con-figuration of objects. As an example, a controller object managing a web form has
a property called successViewthat decides what view to render if the submitted
form was successfully validated. This property value is specified in an XML-file and set upon object instantiation via dependency injection.
5.2.3 Aspect-Oriented Programming
Aspect-oriented programming is applied in two different ways, both related to se-curity.
In the service layer an around advice has been applied to methods that ensure
only users authenticated as administrators may access those specific methods. If the user is not an administrator the invoked methods are not executed and an exception is thrown resulting in an error page being displayed to the user.
The other advice is responsible for enforcing security and only allowing admin-istrators to edit a user, except when users edit themselves. This is also done in
the service layer by explicitly naming thesaveUser()method of theUserManager
class in the pointcut definition. The advice makes use of both the typesbefore and
Chapter 6
Evaluation
In this chapter the results of using dependency injection and aspect-oriented pro-gramming in the development of the aforementioned application are evaluated and discussed with the problem definition in mind.
The chapter is divided into two sections, one discussing dependency injection and one discussing aspect-oriented programming. In each section the most significant findings are presented divided into sub sections after the original questions posed
in the problem definition. The sub sections aredesign,maintainability andtesting.
Design is about how the application architecture and design of implementation is affected by the use of the technology in question.
Maintainability deals with the consequence of how easy the implementation is to maintain (for the original developer but more importantly for someone else not familiar with the code) as a result of the use of dependency injection and aspect-oriented programming. Maintainability includes properties such as readability, im-pact on refactoring and overall understandability of the code.
Finally testing includes testing of the application as a whole as well as features
introduces by the technology itself.
These three aspects are not discrete and may often overlap, as an example, something that improves the design and architecture of an implementation may often also make the implementation easier to maintain.
The evaluation, discussion and possible conclusions in this chapter are all made by the author based on the experience gathered from the design and implementation of the application described in this master thesis.
6.1
Dependency Injection
6.1.1 Design
Easy to implement
Dependency injection is such an integral part of the Spring Framework that it is more or less not possible to be without it unless just single modules of the Spring
Framework are used. Classes in the Spring Framework are all designed to have dependencies injected where possible.
Hence there is no question if dependency injection should be used or not if the power of the Spring Framework is leveraged, instead it is more interesting to look at the impact of design using dependency injection on objects not coupled with the framework itself.
The use of dependency injection does not affect any business logic or object-oriented design of objects. What it does is it to provide an alternative way to get references to dependent objects. Because of this little or no modifications to the overall design of a system is required to change in order to use dependency injection. Framework or not
If using the Spring Framework or another framework where dependency injection is included there is no reason not to use it.
However, if for various reasons a framework that provides dependency injection may not be used the concept and pattern of dependency injection is still useful when designing classes.
By implementing the classes with interfaces designed for setter- and constructor injection and creating them using a factory like pattern much of the benefit of dependency injection remains without the need to introduce a complete framework.
6.1.2 Maintainability
Less boilerplate code
In general less boilerplate code is required when relying on dependency injection instead of conventional lookup or creation of dependent objects. This is the case be-cause dependencies are injected typically using a setter method or in the constructor instead of being created and instantiated, retrieved through lookup methods code or using factories.
Less boilerplate code results in higher object cohesion since the code focuses less on infrastructure issues such as construction and retrieval dependent objects and more on performing the application logic.
Exposed dependencies
By consequently using dependency injection all dependencies of an object are re-trieved using constructor or setter injection. This means that it is possible to identify all external dependencies by only looking at the signature of the constructor and the public setter methods.
Another approach is to consider the configuration of dependency injection to see what references are injected into each object. Using Spring the dependency injection is typically in XML. Worth noting is that if auto-wiring is used the ability to identify dependencies by looking at the configuration is significantly reduced.
6.1. DEPENDENCY INJECTION
The conventional way without using dependency injection would require reading all method implementations line by line.
The risk is when conventional dependency lookup is used together with depend-ency injection. Then it is easy to miss dependencies only visible in code of method implementations if only looking at the method signatures or dependency injection configuration.
Refactoring
Dependency injection promotes the design of less coupled code since an object’s dependencies are injected rather than retrieved using infrastructure code in the object itself. This by itself often makes refactoring easier.
An example of when refactoring is needed is when dependencies change. For
example acollection of data changes from one data type to another. The refactoring
is potentially made significantly easier with a system using dependency injection
compared to conventional design. This is especially the case when dependency
injection is used together with the concept ofdesign by interface (see section 5.2.1).
The reason why refactoring becomes easier in this case is because dependencies are injected and the only ”contract” between the dependency and the object
per-forming logic on the dependency is the interface. If a dependency changes but still
implements the same interface little or no changes need to be done to the object.
6.1.3 Testing
Following the discussion about refactoring it is easy to see that unit testing benefits as well from dependency injection. In general less coupled objects are easier to unit
test, but when there are dependencies they sometimes need to be replaced bymock
objects.
A mock object is an object that simulates the behavior of a real object when the real object is impractical to use in a unit test. There are several reasons why mock objects may be used, examples are objects with special states that are hard to reproduce (like network errors) or too slow (certain database queries). In unit testing of web applications it is common to use a mock object representing an HTTP request.
Dependency injection allow easy replacement of objects with mock counterparts where needed. If dependencies were not as easy exposed this might potentially be a very troublesome operation.
6.2
Aspect-Oriented Programming
6.2.1 Design
Separation of concerns
Compared to dependency injection aspect-oriented programming has big impact on the design and implementation of an application. With the concept of separating scattered concerns into aspects a solution would be designed significantly differ-ent when using aspect-oridiffer-ented programming instead of only convdiffer-entional object-oriented programming.
With successful use of aspect-oriented programming, cross-cutting concerns pre-viously scattered throughout a system may be largely put into an aspect that is applied where necessary. This has two immediate effects. Code invoking cross-cutting concerns may be removed from objects, thus letting the objects focus on their application logic and thereby receive higher cohesion. The flip side of this is that the implementation and triggering of the cross-cutting concerns are centralized into aspects, hence making changes now only requires modification in the aspects instead of (in worst case) all places in the application invoking the cross-cutting concern. A typical example of such cross-cutting concern is logging.
Identifying aspects
Aspect-oriented programming introduces a new dimension to design by allowing a code flow different compared to object-oriented programming. This requires a somewhat new way of thinking to take advantage of aspect-oriented programming. Since aspect-oriented programming is a complement to object-oriented program-ming and not a replacement there is nothing that forces a design to use aspects. Hence the developer must identify what concerns are suitable to be implemented as aspects or not.
From designing the application in this Master’s project two approaches to identi-fying aspects emerged.
The first approach is to identify cross-cutting concerns during requirements ana-lysis and the initial stage of designing the architecture before starting implement-ation. This approach involves identifying business aspects that cross-cut several modules.
The second approach is to implement modules and objects in a conventional way and then refactor concerns into aspects once it is obvious that they are cross-cutting. A typical example of this is when the same type of code is repeated in several places; the objects are refactored to use an aspect instead of repeating the same type of code.
6.2. ASPECT-ORIENTED PROGRAMMING
Aspects or not
What became apparent during the development of th