CSC/ECE 517 Fall 2013/ch1 1w34 fs: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
'''Aspect-Oriented Programming''' ('''AOP''') in '''Ruby on Rails''' is a programming paradigm which aims at preserving the modularity of object –oriented programs by separating behaviors that make overall implementation scattered, bulky and tangled. It so happens with huge applications that the object boundaries in the problem domain get obscured with the introduction of more and more aspects as an application gets bigger leading to spaghetti code scenario. AOP thus compliments the object-oriented principles such as '''DRY ''' by removing excess duplication throughout the program by handling cross-cutting concerns, making the resulting code as highly modular, easy to maintain and test.  
'''Aspect-Oriented Programming''' ('''AOP''') in '''Ruby on Rails''' is a programming paradigm which aims at preserving the modularity of object –oriented programs by separating behaviors that make overall implementation scattered, bulky and tangled. It so happens with huge applications that the object boundaries in the problem domain get obscured with the introduction of more and more aspects as an application gets bigger leading to spaghetti code scenario. AOP tackles this issue and compliments the object-oriented programming principles such as '''DRY ''' by removing excess duplication throughout the program by separating cross-cutting concerns, resulting in a highly modular, easy to maintain and testable application code.  


By isolating behavior, tight coupling between functionalities handling specific logic, in a program can be prevented. Also these independent aspects such as logging, transactions and security can be applied to other applications as well.
By isolating behavior, tight coupling between functionalities handling different logic, can be prevented. Also by separating these independent aspects such as logging, transactions and security further reuse can be made in other applications as well.


==Overview==
==Overview==

Revision as of 02:20, 8 October 2013

Aspect-Oriented Programming (AOP) in Ruby on Rails is a programming paradigm which aims at preserving the modularity of object –oriented programs by separating behaviors that make overall implementation scattered, bulky and tangled. It so happens with huge applications that the object boundaries in the problem domain get obscured with the introduction of more and more aspects as an application gets bigger leading to spaghetti code scenario. AOP tackles this issue and compliments the object-oriented programming principles such as DRY by removing excess duplication throughout the program by separating cross-cutting concerns, resulting in a highly modular, easy to maintain and testable application code.

By isolating behavior, tight coupling between functionalities handling different logic, can be prevented. Also by separating these independent aspects such as logging, transactions and security further reuse can be made in other applications as well.

Overview

History

Terminology

Cross Cutting Concerns

Many applications share common functionality in their design and implementation. This shared and common logic spans across many layers and leads to repetition and bloating of the application and thereby termed as crosscutting concerns. The aim of AOP is to centralize these functionalities into modular and independent logical aspects which can be inserted into the application either during compilation or at run time, as per requirement, thereby complimenting the DRY principle. The benefits of adopting such an approach are many. Apart from keeping the application with distinct object boundaries, it modularizes aspects in separate locations which are easy to update and maintain in future as well as reuse in other web applications. Some such aspects known commonly which can be treated in AOP way are:

Authentication
authorization
caching
communication
logging
validation

This reusing behavior as per outside defined aspects, crosscutting concerns can be effectively dealt with.

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.

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 pointcut is reached when the thread enters a method, and another pointcut is reached when the thread exits the method.

Aspect

The combination of the pointcut and the advice is termed an aspect. In the example above, we add a logging aspect to our application by defining a pointcut and giving the correct advice.

AOP Interactions

Persistence of model objects is a cross-cutting concern, in the sense that the desired persistence approach (database, flat files, replication, etc.) is independent of the domain logic represented by the model. So, why should the model code have any persistence logic? Instead, capture the details of mapping the domain to the persistence approach in separate components and programmatically or declaratively modify the model objects to synchronize state changes with the persistent memory of the state.




AOP'istic flavored Rails Framework

Rails framework allows methods to be called before and after a method invocation by employing method aliasing and metaprogramming features of Ruby, but using a third party library such as Aquarium, to glue the aspects is more cleaner and robust to failures ( such as plugins overriding method_missing stepping over each other). Rails already provides for filters which can be called before, after or around to wrap the controllers such as shown here:

someController
before_filter :admin_login_required

We also show how aspect oriented programming can be employed in Rails framework by separating aspects which cross-cut the application. In the following example we illustarte it for Loggingaspect. We start by building an application which stores items to be purchased in a cart. To help log user's activity while successfully adding or removing the items, logging needs to be performed for each action. As application gets bigger more aspects need to corporated such as authentication, security etc which makes it difficult to maintain and understand the code. Also it is needed for any update to any aspect be applied everywhere in the business logic where that updated aspect was injected.

Aspects in Rails MVC
class ItemsUseCase
attr_reader :cart, :logger, :items
 def initialize(cart = cart.new, logger = Logger.new)
   @cart = cart
   @logger = logger
   @items = []
 end
# Logging Aspect for adding items to cart
def user_adds(item)
  items << item
  cart.add(item, 
                   success: self.method(:user_added),
                   failure: self.method(:fails_to_add))
 end
def user_added(item)
   logger.info "Item successfully added: #{item.name})"
 end
def fails_to_add(item)
   logger.error "Failed to add item}"
end
end

Introducing AOP concept for separating Logging aspect. By separating the logging aspect to ItemsUseCaseGlue, we see that our ItemsUseCase become much simpler and having comprehensible object boundaries. It handles all the above stated issues that comes with integrating aspect knowledge in the business logic.

class ItemsUseCase
 attr_reader :items
 def initialize
   @items = []
 end
 def user_adds(item)
   items << item
 end
 def user_added(item); end
 def fails_to_add(item);  end
end

ItemsUseCaseGlue, where we employ Aquarium for employing AOP concepts, method invocation using- calls_to is used to specify our Joint points. When invoked in the program, advice is injected to take effect before, after or around the joint point.

require 'aquarium'
class ItemsUseCaseGlue
 attr_reader :usecase, :cart, :logger
 include Aquarium::Aspects
 def initialize(usecase, cart, logger)
   @usecase = usecase
   @ cart = cart
   @logger = logger
 end
 def inject!
   Aspect.new(:after, object: usecase, calls_to: :user_adds) do |jp, obj, item|
     cart.push(item, 
                     success: usecase.method(:user_added),
                   failure: usecase.method(:fails_to_add))
   end
   Aspect.new(:after, object: usecase, calls_to: :user_added) do |jp, obj, item|
     logger.info("Successfully added: #{item.name})")
   end
   Aspect.new(:after, object: usecase, calls_to: :fails_to_add) do |jp, obj, item|
     logger.error "Failed to add item"
   end
 end
end

Finally, the application retains its pure domain object properties without including any aspect layer specifications.

class Application
 def initialize
   @items = ItemsUseCase.new
   @cart = Cart.new
   @logger = Logger.new
   @items_glue = ItemsUseCaseGlue.new(items,@cart, @logger)
                        
   @items_glue.inject!
   # logic
 end
end

Summary

References

  • Kiczales, G., J. Lamping, A. Mendhekar, C. Maeda, C. Videira Lopes, J.-M. Loingtier, J. Irwin (1997): Aspect-Oriented Programming, in: Proceedings of the 11th European Conference on Object-Oriented Programming (ECOOP 1997), Jyväskylä, Finland, Lecture Notes in Computer Science 1241, Springer-Verlag, 220-242

External Links