CSC/ECE 517 Summer 2008/wiki1 5 a5: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(68 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== Introduction ==
== Introduction ==
'''[http://www.ruby-lang.org/en/ Ruby]''' has hooks that allows trapping a certain event (e.g., object creation) and running a particular code sequence whenever the event occurs. There's no comparable facility in Java. But both Ruby and Java have support for aspect-oriented programming ('''[http://aspectr.sf.net/ AspectR]''' and '''[http://www.eclipse.org/aspectj/ AspectJ]''', respectively). What's the difference between simply
This wiki seeks to introduce the reader to the basic concepts of hooks and Aspect-Oriented Programming. Our comparison will focus on Ruby and Java implentations in an attempt to compare and contrast the viability of these programming techniques across each of the two languages.
providing hooks, and supporting full AOP, and why is it more convenient to program this way in Ruby than Java? Give a few code sequences to justify your conclusions.


== Hooks ==
== Hooks ==
   
   
There is a strong desired from developers to have control on object life cycle. They
There is a strong desire from developers to have control of object life cycle. They
would like to know when an object is created or destroyed, or some specific method
would like to know when an object is created or destroyed, or some specific method
is executed. They would like to monitor what application is doing inside and look
is executed. Developers would like to monitor code and look
for possibility to change application behavior or add new functionality without
for opportunities to change application behavior without making major changes to the object model already in place. Some programming languages provide '''[http://en.wikipedia.org/wiki/Hooking hooks]''' to monitor such events. Hooks allow a block of code to automatically execute when a particular event is triggered.  
making big changes in object model. Some time programming languages provide '''[http://en.wikipedia.org/wiki/Hooking hooks]''' to monitor such events. Hooks are set of code that automatically execut when a particular event triggers.  


=== Hooks Implementation ===
=== Hooks Implementation ===
   
   
Most of '''[http://en.wikipedia.org/wiki/Dynamic_language dynamic languages]''' provide some ways to execute custom code at different
Most '''[http://en.wikipedia.org/wiki/Dynamic_language dynamic languages]''' provide some way to execute custom code at different
steps of object life cycle. Most of them built this functionality as part of
steps of an object's life cycle. This functionality is often built into the individual languages using the '''[http://dailydevelopment.blogspot.com/2007/04/interceptor-design-pattern.html interceptor design pattern]''' as an implementation guideline.
language design. They use '''[http://dailydevelopment.blogspot.com/2007/04/interceptor-design-pattern.html interceptor design pattern]''' as implementation guideline.


==== Hooks in Ruby ====
==== Hooks in Ruby ====
   
   
'''[http://www.ruby-lang.org/en/ Ruby]''' is a dynamic and pure object oriented language. It has a very strong support
'''[http://www.ruby-lang.org/en/ Ruby]''' is a dynamic and pure object oriented language. It has very strong support
for '''[http://en.wikipedia.org/wiki/Metaprogramming metaprogramming]'''. It provides '''[http://www.ruby-doc.org/docs/ProgrammingRuby/html/ospace.html system hooks]''' for monitoring events like object
for '''[http://en.wikipedia.org/wiki/Metaprogramming metaprogramming]''' that allow it to define hooks to for monitoring events like object creation, method access etc. The technique used by Ruby to provide this functionality is a simple
creation. The technique use by Ruby to provide this functionality is a simple
example of the interceptor design pattern.  By intercepting calls to base classes developers can modify the system behavior without changing application code.   
example of interceptor design pattern.  By intercepting calls to system classes
developer could modify the system behavior without changing application code.   
   
   
'''''Example Code:'''''
'''''Example Code:'''''
   
   
Following is an '''[http://www.ruby-doc.org/docs/ProgrammingRuby/html/ospace.html example code]''' from '''[http://www.ruby-doc.org/docs/ProgrammingRuby/ Programming Ruby - The Pragmatic Programmer's Guide (First edition is freely available on web)]''' for hooking objects
The following example code illustrates how a ruby developer is able to monitor the objects
creation event. This code modifies two Ruby system classes ('''[http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_class.html Class]''' and '''[http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_object.html Object]''').  It
creation event by using hooks. This code modifies two Ruby system classes ('''[http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_class.html Class]''' and '''[http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_object.html Object]''').  It
renames and redefines the Class new method and modifies the Object class to store
renames and redefines the Class new method and modifies the Object class to store the
timestamp.
timestamp.
   
   
Line 51: Line 45:
   end
   end
   
   
Now, lets run some tests:
Now we will define a class Test and then create two instances of this class. It is a simple class but using super class method timestamp we could see the actual time of creation of those objects. 
   
   
   class Test
   class Test
Line 57: Line 51:
   
   
   obj1 = Test.new
   obj1 = Test.new
   sleep 2
   sleep 2           #not needed if executing code using Interactive Ruby
   obj2 = Test.new
   obj2 = Test.new
   
   
   obj1.timestamp  
   obj1.timestamp  
   obj2.timestamp
   obj2.timestamp
Following is the output of above code,
  Fri Jun 06 17:29:04 -0400 2008
  Fri Jun 06 17:29:18 -0400 2008


==== Hooks in Java ====
==== Hooks in Java ====


Java is statically type language. It doesn’t provide any language level ability to monitor events like object creation etc. However, the latest JVM version through '''[http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html JVMTI]''' allow some hooks for monitoring performance but there is no way for the developer to change the behavior of an application through the available hooks.
Java is a statically typed language. It does not provide any language level ability to monitor events like object creation or method execution. However, the latest JVM Tool Interface '''[http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html (JVMTI)]''' provides some hooks for monitoring performance, but the developer can not use this interface to change the behavior of an application.


=== Benefits of Hooks ===
=== Benefits of Hooks ===


Hooks is an elegant way of changing application behavior in dynamic languages. It is simple and compatible with dynamic languages philosophy. Since most time it is part of language, developer does not have to learn new API to take advantage of this.
Hooks are an elegant way of changing application behavior in dynamic languages. It is simple and compatible with the dynamic language philosophy. Since it is usually part of dynamic languages the developer does not have to learn a new API to take advantage of hooks.


== Aspect-Oriented Programming ==
== Aspect-Oriented Programming ==
'''[http://en.wikipedia.org/wiki/Object_orientated_programming Object-Oriented Programming (OOP)]''' was a big shift from '''[http://en.wikipedia.org/wiki/Procedural_programming procedural programming]'''. Now instead of concentrating on procedures and data separately, developers start working with '''[http://en.wikipedia.org/wiki/Object_%28computer_science%29 objects]''' and their interactions to design applications. This allowed them to deal with large and more complicated system and develop them in less time ever before. Later '''[http://en.wikipedia.org/wiki/Aspect-oriented_programming Aspect-oriented Programming (AOP)]''' made developers life easier by allowing them to dynamically modify the static OO model to create a system that can grow to meet new requirements.   
'''[http://en.wikipedia.org/wiki/Object_orientated_programming Object-Oriented Programming (OOP)]''' was a big shift from '''[http://en.wikipedia.org/wiki/Procedural_programming procedural programming]'''. With OOP instead of concentrating on procedures and data separately, developers started working with '''[http://en.wikipedia.org/wiki/Object_%28computer_science%29 objects]''' and their interactions with other objects to design more efficient and maintainable applications. This allowed developers to deal with large and more complicated systems and develop them in less time than ever before. '''[http://en.wikipedia.org/wiki/Aspect-oriented_programming Aspect-oriented Programming (AOP)]''' is designed to make developers life even easier by allowing them to dynamically modify the static OO model to create a system that can grow to meet new requirements.   




''Aspect-Oriented Programming helped the developers in '''[http://en.wikipedia.org/wiki/Separation_of_concerns separation of concerns]''', specifically '''[http://en.wikipedia.org/wiki/Cross-cutting_concern cross-cutting concern]''', as an advance in '''[http://en.wikipedia.org/wiki/Modularity_%28programming%29 modularization]'''.'' – Wikipedia
''Aspect-Oriented Programming facilitates the developers attempt to '''[http://en.wikipedia.org/wiki/Separation_of_concerns reduce the amount of distinct features with overlaping functionality]''' by addressing '''[http://en.wikipedia.org/wiki/Cross-cutting_concern cross-cutting concerns]''' and facilitating '''[http://en.wikipedia.org/wiki/Modularity_%28programming%29 modular programming]'''.''




AOP is look very simple in definition but it is quite complex topic.  Before going further, it is better to familiarize ourselves with some related terminology.
AOP may appear simple but is in fact quite a complex topic.  Standard implementations usually make use of the following:


# '''Cross-cutting concerns:''' Even though most classes in an OO model will perform a single, specific function, they often share common, secondary requirements with other classes. For example, we may want to add logging to classes within the data-access layer and also to classes in the UI layer whenever a thread enters or exits a method. Even though the primary functionality of each class is very different, the code needed to perform the secondary functionality is often identical.
# '''Cross-cutting concerns:''' Even though most classes in an OO model will perform a single, specific function, they often share common, secondary requirements with other classes. For example, we may want to add logging to classes within the data-access layer and also to classes in the UI layer whenever a thread enters or exits a method. Even though the primary functionality of each class is very different, the code needed to perform the secondary functionality is often identical.
# '''Advice:''' This is the additional code that you want to apply to your existing model. In our example, this is the logging code that we want to apply whenever the thread enters or exits a method.
# '''Advice:''' This is the additional code that you want to apply to your existing model.  
# '''Point-cut:''' This is the term given to the point of execution in the application at which cross-cutting concern needs to be applied. In our example, a point-cut is reached when the thread enters a method, and another point-cut is reached when the thread exits the method.
# '''Point-cut:''' This is the term given to the point of execution in the application at which cross-cutting concern needs to be applied.
# '''Aspect:''' The combination of the point-cut and the advice is termed an aspect. In the example below, we add a logging aspect to our application by defining a point-cut and giving the correct advice.
# '''Aspect:''' The combination of the point-cut and associated advice
 
[taken from '''[http://www.onjava.com/pub/a/onjava/2004/01/14/aop.html Introduction to Aspect-Oriented Programming]''']
 
 
=== AOP Implementation ===
=== AOP Implementation ===
For both Java and Ruby multiple implementations of AOP exist.  For the purpose of this article we will look at AspectJ for Java and AspectR for Ruby.
For both Java and Ruby multiple implementations of AOP exist.  For the purpose of this article we will look at AspectJ for Java and AspectR for Ruby.


==== AOP in Java ====
==== AOP in Java ====
'''[http://www.eclipse.org/aspectj/ AspectJ]''' adds the concept of a join point to Java as well as a few new constructs: pointcuts, advice, inter-type declarations and aspects. The dynamic parts of AspectJ include: the join point which is a well-defined point in the program flow, the pointcut which picks out certain join points and values at those points, and lastly a piece of advice which is executed when a join point is reached.  AspectJ also has different kinds of inter-type declarations that allow the programmer to modify a program's static structure, namely, the members of its classes and the relationship between classes. AspectJ's aspect are the unit of modularity for crosscutting concerns. They behave somewhat like Java classes, but may also include pointcuts, advice and inter-type declarations.
'''[http://www.eclipse.org/aspectj/ AspectJ]''' adds the concept of a join point to Java as well as a few new constructs: pointcuts, advice, inter-type declarations and aspects. The dynamic parts of AspectJ include: the '''join point''' which is a well-defined point in the program flow, the '''pointcut''' which picks out certain join points and values at those points, and lastly the '''advice''' which is executed when a join point is reached.  AspectJ also has different kinds of inter-type declarations that allow the programmer to modify a program's static structure, namely, the members of its classes and the relationship between classes. AspectJ's aspect are the unit of modularity for crosscutting concerns. They behave somewhat like Java classes, but may also include pointcuts, advice and inter-type declarations.


Example Code from AspectJ Homepage:
Example Code:


   aspect SimpleTracing {
   aspect SimpleTracing {
Line 104: Line 99:
       }
       }
   }
   }
[Reference '''[http://www.eclipse.org/aspectj/doc/released/progguide/starting-development.html Development Aspects]''']


This code is meant to print a line of text everytime a FigureElement receives a draw method call.  It does this by creating an aspect called SimpleTracing which uses a pointcut called tracedCall() to capture every draw method call.  This in itself would do nothing, so to implement crosscutting behavior Advice is used.  That advice basically says print out the name of thisJoinPoint, a special variable, before the actual method starts running, but just after the arguments to the method call are evaluated.  
This code is meant to print a line of text everytime a FigureElement receives a draw method call.  It does this by creating an aspect called SimpleTracing which uses a pointcut called tracedCall() to capture every draw method call.  This in itself would do nothing, so to implement crosscutting behavior Advice is used.  That advice basically says print out the name of thisJoinPoint, a special variable, before the actual method starts running, but just after the arguments to the method call are evaluated.  
Line 133: Line 130:


   ma = MyAspect.new
   ma = MyAspect.new
   ma.wrap(someClassorObject, :preAdvice, :postAdvice, ... methods to wrap...) #Would apply to any spcified method call
   ma.wrap(someClassorObject, :preAdvice, :postAdvice, ... methods to wrap...)               #Would apply to any spcified method call
   ma.wrap(someClassorObject, :preAdvice, :postAdvice, /patternToWrap/) #Specify a pattern instead of the full method name
   ma.wrap(someClassorObject, :preAdvice, :postAdvice, /patternToWrap/)                       #Specify a pattern instead of the full method name
   AspectR.wrap_classes(ma, :preAdvice, :postAdvice, [Class1, Class2], ...methods to wrap...) #Defines which classes and methods this Aspect would apply to.
   AspectR.wrap_classes(ma, :preAdvice, :postAdvice, [Class1, Class2], ...methods to wrap...) #Defines which classes and methods this Aspect would apply to.


Line 140: Line 137:


=== Benefits of AOP ===
=== Benefits of AOP ===
Software engineers should take advantage of aspect-oriented programming to reduce the amount of scattered or tangled code within a program.  Modular programming techniques such as AOP often allow engineers to fully seperate programming tasks this allows the code to be easier to read and maintain.  Similar to the way the OSI Reference Model breaks up networking transmission into layers of related functions.  When creating software or hardware for a single layer, engineers must only provide services for the layer above and below the one currently being designed.  This allows Application Layer programmers to do their job with little or no concern for what is going on at the Physical Layer.
Software engineers should take advantage of aspect-oriented programming to reduce the amount of scattered or tangled code within a program.  Modular programming techniques such as AOP often allow engineers to fully seperate programming tasks this allows the code to be easier to read and maintain.  Similar to the way the '''[http://en.wikipedia.org/wiki/OSI_model OSI Reference Model]''' breaks up networking transmission into layers of related functions.  When creating software or hardware for a single layer, engineers must only provide services for the layer above and below the one currently being designed.  This allows Application Layer programmers to do their job with little or no concern for what is going on at the Physical Layer.


Using AOP to break down the functions of a program allow software engineers to work on one function without breaking another.  While this may seem like common sense, it can be a very difficult task.  For example when coding a database update function a few of the considerations include ensuring the user updating the database is authorized to make the change, the data is valid in respect for the field being updated, and that the change is properly logged so that it may be undone if needed later.  These concerns along with many others can be properly be encapsulated so that they may be maintained and updated without affecting the various other processes going on along side them.  
Using AOP to break down the functions of a program allow software engineers to work on one function without breaking another.  While this may seem like common sense, it can be a very difficult task.  For example when coding a database update function a few of the considerations include ensuring the user updating the database is authorized to make the change, the data is valid in respect for the field being updated, and that the change is properly logged so that it may be undone if needed later.  These concerns along with many others can be properly be encapsulated so that they may be maintained and updated without affecting the various other processes going on along side them.


== AOP vs Hooks ==
== AOP vs Hooks ==


From earlier days of object-oriented programming languages, programmers are using different techniques to execute code at different phases of object life cycle. They have successfully used programming concepts like '''[http://en.wikipedia.org/wiki/Subjects_%28programming%29 subjects]''', interception and '''[http://en.wikipedia.org/wiki/Delegation_%28programming%29 delegation]''' to deal with such requirements. All modern object-oriented dynamic languages now support hooking mechanism for such situations.
From the earliest days of object-oriented programming languages, programmers have been using different techniques to execute code at different phases of the object life cycle. They have successfully used programming concepts like '''[http://en.wikipedia.org/wiki/Subjects_%28programming%29 subjects]''', interception and '''[http://en.wikipedia.org/wiki/Delegation_%28programming%29 delegation]'''. Most all modern object-oriented dynamic languages now support hooking mechanism to aid implementation of these techniques. In Ruby by modifying the base classes’ developers could create hooks to intercept calls to application object model. They could use those events to inject new code that fulfill new requirements without modifying application object model. Requirements like, security, logging and performance monitoring could easily implemented in Ruby through hooks.
 
Aspect Oriented Programming on other hand is a new concept. It provides more comprehensive solution for dealing with complex requirements related to '''[http://en.wikipedia.org/wiki/Cross-cutting_concern cross-cutting concerns]''' and '''[http://en.wikipedia.org/wiki/Modularity_%28programming%29 modularity]'''. It has its own '''[http://en.wikipedia.org/wiki/Domain_Specific_Language domain-specific language]''' to deal with such problems. There is no comparison between AOP’s extensive semantics with hooks implementation. Hooks could be use as AOP implementation mechanism but they will never be able to compete with AOP functionality.
 
It is hard for us to come up with some good example that shows the limitation of hooks compare to AOP. Since both of us has no experience in Ruby and AOP. But while searching on web we come across a specification for implementing '''[http://rcrchive.net/rcrs/1 Cut-based AOP in Ruby]'''. This specification discusses how we could add additional functionality to existing class without subclassing it. It introduces a new class called '''Cut'''. It is used to encapsulate advice for a single class.  Following is an example for adding new functionality to existing class C without subclassing it using new Cut class,
 
  class C
  def f(*args); 1; end
  def g(*args): 2; end
  end
 
In order to add new functionality we would subclass C. i.e.
 
  class A<C
  def f
  print ‘(’, super, ‘)’
  end
  end
 
Now with AOP extension for Ruby,
 
  cut A < C
  def f
  print ‘(’, super, ‘)’
  end
  end


Now instead of subclassing C ''“we have cut-across behavior of C with A”''.
Aspect Oriented Programming on other hand is a new concept. It provides a more comprehensive solution for dealing with complex requirements related to '''[http://en.wikipedia.org/wiki/Cross-cutting_concern cross-cutting concerns]''' and '''[http://en.wikipedia.org/wiki/Modularity_%28programming%29 modularity]'''. It has its own '''[http://en.wikipedia.org/wiki/Domain_Specific_Language domain-specific language]''' to deal with such problems. There is no comparison between AOP’s extensive semantics with present hooks implementations. Hooks could be used as AOP implementation mechanisms but they will never be able to compete with the AOP functionality.
 
Now we will discuss how Ruby hooks are still better. If we compare above two examples (Ruby Hook and Java AOP) we could see using AOP is over kill for such simple problem. Ruby hooks are more elegant solution in such situation. AOP are more suitable for statically type languages like Java. Ruby as dynamic language needs simpler syntax for dealing with simple cross-cutting concern problems. It supports very strong '''[http://en.wikipedia.org/wiki/Metaprogramming metaprogramming]''' functionalities using interceptors, '''[http://en.wikipedia.org/wiki/Hotswapping hotswapping]''', '''[http://en.wikipedia.org/wiki/Mixin mixins]''' and '''[http://en.wikipedia.org/wiki/Hooking hooks]''' that make lot easier for injecting custom code during runtime. Different Ruby experts also share the same opinion,


Now the question is what is good for Ruby? If we compare the above two examples (Ruby Hook and Java AOP) it is obvious that using AOP is over kill for simple requirements. Ruby hooks are more elegant solutions. Ruby as a dynamic language needs simpler syntax for dealing with simple cross-cutting concerns and custom code injection problems and Ruby hooks provide such mechanism. Ruby supports very strong metaprogramming functionalities using interceptors, '''[http://en.wikipedia.org/wiki/Hotswapping hotswapping]''', '''[http://en.wikipedia.org/wiki/Mixin mixins]''', and '''[http://en.wikipedia.org/wiki/Hooking hooks]''' that makes it much easier to inject custom code during runtime.  Various Ruby experts also share these same opinions for example:


''“For Ruby developers, AOP is not quite as urgent, because you’ve already got robust tools to deal with these kinds of concerns.”'' Bruce Tate – Beyond Java.
''“For Ruby developers, AOP is not quite as urgent, because you’ve already got robust tools to deal with these kinds of concerns.”'' Bruce Tate – Beyond Java.


''“A standardized AOP framework has never really taken off in Ruby because the language itself already supports most of the desirable functionality of AOP.”'' David Heinemeier Hansson – Rail Architect


''“A standardized AOP framework has never really taken off in Ruby because the language itself already supports most of the desirable functionality of AOP.”'' David Heinemeier Hansson – Rail Architect
Other experts do mention that it may take more time for Ruby AOP to become a larger concern, they continue to say that often only enterprise application development warrants AOP and currently Ruby does not have a large enough group of programmers working on these types of applications.


== Links ==
== Links ==

Latest revision as of 03:11, 12 June 2008

Introduction

This wiki seeks to introduce the reader to the basic concepts of hooks and Aspect-Oriented Programming. Our comparison will focus on Ruby and Java implentations in an attempt to compare and contrast the viability of these programming techniques across each of the two languages.

Hooks

There is a strong desire from developers to have control of object life cycle. They would like to know when an object is created or destroyed, or some specific method is executed. Developers would like to monitor code and look for opportunities to change application behavior without making major changes to the object model already in place. Some programming languages provide hooks to monitor such events. Hooks allow a block of code to automatically execute when a particular event is triggered.

Hooks Implementation

Most dynamic languages provide some way to execute custom code at different steps of an object's life cycle. This functionality is often built into the individual languages using the interceptor design pattern as an implementation guideline.

Hooks in Ruby

Ruby is a dynamic and pure object oriented language. It has very strong support for metaprogramming that allow it to define hooks to for monitoring events like object creation, method access etc. The technique used by Ruby to provide this functionality is a simple example of the interceptor design pattern. By intercepting calls to base classes developers can modify the system behavior without changing application code.

Example Code:

The following example code illustrates how a ruby developer is able to monitor the objects creation event by using hooks. This code modifies two Ruby system classes (Class and Object). It renames and redefines the Class new method and modifies the Object class to store the timestamp.

  class Class 
           alias_method :old_new, new
           def new (*args)
                       result = old_new(*args)
                       result.timestamp = Time.now
                       return result
           end
  end

  class Object
           def timestamp 
                       return @timestamp
           end 
           def timestamp = (aTime)
                       @timestamp = aTime
           end
  end

Now we will define a class Test and then create two instances of this class. It is a simple class but using super class method timestamp we could see the actual time of creation of those objects.

  class Test
  end

  obj1 = Test.new
  sleep 2           #not needed if executing code using Interactive Ruby
  obj2 = Test.new

  obj1.timestamp 
  obj2.timestamp

Following is the output of above code,

  Fri Jun 06 17:29:04 -0400 2008 
  Fri Jun 06 17:29:18 -0400 2008

Hooks in Java

Java is a statically typed language. It does not provide any language level ability to monitor events like object creation or method execution. However, the latest JVM Tool Interface (JVMTI) provides some hooks for monitoring performance, but the developer can not use this interface to change the behavior of an application.

Benefits of Hooks

Hooks are an elegant way of changing application behavior in dynamic languages. It is simple and compatible with the dynamic language philosophy. Since it is usually part of dynamic languages the developer does not have to learn a new API to take advantage of hooks.

Aspect-Oriented Programming

Object-Oriented Programming (OOP) was a big shift from procedural programming. With OOP instead of concentrating on procedures and data separately, developers started working with objects and their interactions with other objects to design more efficient and maintainable applications. This allowed developers to deal with large and more complicated systems and develop them in less time than ever before. Aspect-oriented Programming (AOP) is designed to make developers life even easier by allowing them to dynamically modify the static OO model to create a system that can grow to meet new requirements.


Aspect-Oriented Programming facilitates the developers attempt to reduce the amount of distinct features with overlaping functionality by addressing cross-cutting concerns and facilitating modular programming.


AOP may appear simple but is in fact quite a complex topic. Standard implementations usually make use of the following:

  1. Cross-cutting concerns: Even though most classes in an OO model will perform a single, specific function, they often share common, secondary requirements with other classes. For example, we may want to add logging to classes within the data-access layer and also to classes in the UI layer whenever a thread enters or exits a method. Even though the primary functionality of each class is very different, the code needed to perform the secondary functionality is often identical.
  2. Advice: This is the additional code that you want to apply to your existing model.
  3. Point-cut: This is the term given to the point of execution in the application at which cross-cutting concern needs to be applied.
  4. Aspect: The combination of the point-cut and associated advice

AOP Implementation

For both Java and Ruby multiple implementations of AOP exist. For the purpose of this article we will look at AspectJ for Java and AspectR for Ruby.

AOP in Java

AspectJ adds the concept of a join point to Java as well as a few new constructs: pointcuts, advice, inter-type declarations and aspects. The dynamic parts of AspectJ include: the join point which is a well-defined point in the program flow, the pointcut which picks out certain join points and values at those points, and lastly the advice which is executed when a join point is reached. AspectJ also has different kinds of inter-type declarations that allow the programmer to modify a program's static structure, namely, the members of its classes and the relationship between classes. AspectJ's aspect are the unit of modularity for crosscutting concerns. They behave somewhat like Java classes, but may also include pointcuts, advice and inter-type declarations.

Example Code:

  aspect SimpleTracing {
     pointcut tracedCall():
        call(void FigureElement.draw(GraphicsContext));
  
     before(): tracedCall() {
        System.out.println("Entering: " + thisJoinPoint);
     }
  }

[Reference Development Aspects]

This code is meant to print a line of text everytime a FigureElement receives a draw method call. It does this by creating an aspect called SimpleTracing which uses a pointcut called tracedCall() to capture every draw method call. This in itself would do nothing, so to implement crosscutting behavior Advice is used. That advice basically says print out the name of thisJoinPoint, a special variable, before the actual method starts running, but just after the arguments to the method call are evaluated.

The result would look something like:

  Entering: call(void FigureElement.draw(GraphicsContext))

The main advantage to using this technique is that we did not have to edit the draw method call. We could extend this to report on multiple method calls from one aspect without changing any of the method call definitions.

AOP in Ruby

AspectR is an Aspect-Oriented Programming framework for Ruby. It is similar to AspectJ in implementation of AOP but is not as robust or well documented as AspectJ. AspectR includes a aspects, join points, pointcuts, advice, as well as a method profiler and logger. The authors of the software claim their profiler is much more efficient than Ruby's built in profiler and gives you more relevant information. AspectR is however not a complete implementation of AspectJ, this is due in part to the authors belief that some features do not need to be implemented in Ruby.

For the following example the author of AspectR shows us how to monitor method calls by first creating a new aspect:

Example Code from AspectR Homepage:

  require 'aspectr'
  include AspectR
  class MyAspect < Aspect 
  
     def someAdviceMethod(method, object, exitstatus, *args)
        ...
     end
        ... some other advice methods ...
     end

Now that we have an aspect here are some ways we can use it:

  ma = MyAspect.new
  ma.wrap(someClassorObject, :preAdvice, :postAdvice, ... methods to wrap...)                #Would apply to any spcified method call
  ma.wrap(someClassorObject, :preAdvice, :postAdvice, /patternToWrap/)                       #Specify a pattern instead of the full method name
  AspectR.wrap_classes(ma, :preAdvice, :postAdvice, [Class1, Class2], ...methods to wrap...) #Defines which classes and methods this Aspect would apply to.

As you can see these are several ways AspectR can be used to cross-cut code and implement systems such as loggers without modifying the methods or classes they are supposed to monitor.

Benefits of AOP

Software engineers should take advantage of aspect-oriented programming to reduce the amount of scattered or tangled code within a program. Modular programming techniques such as AOP often allow engineers to fully seperate programming tasks this allows the code to be easier to read and maintain. Similar to the way the OSI Reference Model breaks up networking transmission into layers of related functions. When creating software or hardware for a single layer, engineers must only provide services for the layer above and below the one currently being designed. This allows Application Layer programmers to do their job with little or no concern for what is going on at the Physical Layer.

Using AOP to break down the functions of a program allow software engineers to work on one function without breaking another. While this may seem like common sense, it can be a very difficult task. For example when coding a database update function a few of the considerations include ensuring the user updating the database is authorized to make the change, the data is valid in respect for the field being updated, and that the change is properly logged so that it may be undone if needed later. These concerns along with many others can be properly be encapsulated so that they may be maintained and updated without affecting the various other processes going on along side them.

AOP vs Hooks

From the earliest days of object-oriented programming languages, programmers have been using different techniques to execute code at different phases of the object life cycle. They have successfully used programming concepts like subjects, interception and delegation. Most all modern object-oriented dynamic languages now support hooking mechanism to aid implementation of these techniques. In Ruby by modifying the base classes’ developers could create hooks to intercept calls to application object model. They could use those events to inject new code that fulfill new requirements without modifying application object model. Requirements like, security, logging and performance monitoring could easily implemented in Ruby through hooks.

Aspect Oriented Programming on other hand is a new concept. It provides a more comprehensive solution for dealing with complex requirements related to cross-cutting concerns and modularity. It has its own domain-specific language to deal with such problems. There is no comparison between AOP’s extensive semantics with present hooks implementations. Hooks could be used as AOP implementation mechanisms but they will never be able to compete with the AOP functionality.

Now the question is what is good for Ruby? If we compare the above two examples (Ruby Hook and Java AOP) it is obvious that using AOP is over kill for simple requirements. Ruby hooks are more elegant solutions. Ruby as a dynamic language needs simpler syntax for dealing with simple cross-cutting concerns and custom code injection problems and Ruby hooks provide such mechanism. Ruby supports very strong metaprogramming functionalities using interceptors, hotswapping, mixins, and hooks that makes it much easier to inject custom code during runtime. Various Ruby experts also share these same opinions for example:

“For Ruby developers, AOP is not quite as urgent, because you’ve already got robust tools to deal with these kinds of concerns.” Bruce Tate – Beyond Java.

“A standardized AOP framework has never really taken off in Ruby because the language itself already supports most of the desirable functionality of AOP.” David Heinemeier Hansson – Rail Architect

Other experts do mention that it may take more time for Ruby AOP to become a larger concern, they continue to say that often only enterprise application development warrants AOP and currently Ruby does not have a large enough group of programmers working on these types of applications.

Links