Академический Документы
Профессиональный Документы
Культура Документы
Dean Wampler Sr. Trainer, Mentor, and Consultant Object Mentor, Inc. Chicago, IL dean@objectmentor.com Friday, March 23, 2007, 3:30-5:00 PM
Outline
Why Aspect-Oriented Programming? AOP in Java and AspectJ (a Review). AOP in Ruby. What you can do today. Example AOP-isms in Ruby on Rails. Aspect-Oriented Design. The AOP Promise for Tomorrow.
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 2
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 3
The Problem:
require 'insufficient_funds' class BankAccount attr_accessor :balance def initialize @balance = 0.0 end def deposit(amount) @balance += amount end def withdraw(amount) if @balance < amount raise InsufficientFunds end @balance -= amount end end
Plain Old Ruby Object (PORO): Simple to understand, maintain, reuse, ... but ...
The Problem: ! Finally, attempt to reuse this code in a new application with a different persistence store, transaction engine, security model...
The Problem: ! The modularity of plain old domain object models break down when adding real world concerns.
! A cross-cutting concern.
Transactions
Security
BankAccount
Persistence
The Problem: ! BankAccounts modularity is compromised. ! Also, similar persistence code is added to other components:
! Redundancy:
Hard to change all occurrences consistently. Hard to replace the Persistence solution. Breaks Dont Repeat Yourself! (DRY)
! Reuse is hard.
The persistence solution may be different in another context.
A Better Solution?
! Aspect-Oriented Programming:
Encapsulate the separate concerns as aspects, Provide mechanisms for fine-grained modification of target component behavior to incorporate the aspects behaviors, and thereby restore system modularity.
BankAccount Persistence
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 16
! Dynamic Typing
! Behavior depends on type of the value.
Variable can be assigned a different value. a.k.a. late typing.
AOP in Static Languages ! Area of greatest R&D to-date. ! Ironic since many of the inventors come from Lisp backgrounds ! but reflects practical realities:
! Cross-cutting concerns most problematic in enterprise and web applications written in Java, .NET, etc. ! Metaprogramming facilities tend to be weaker...
! JBoss AOP
! jboss.org
! Pointcuts
! Sets of Join Points with a similar theme.
! Advice
! Code invoked before, after, or around a Join Point.
10
AspectJ Example
Pointcut
aspect PersistenceAspect { pointcut stateChange(BankAccount ba): (call(void BankAccount.deposit(*)) || call(void BankAccount.withdraw(*))) after && target(ba); Advice
2 Join Points
AOP in Ruby
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 22
11
AOP in Ruby (??) ! If youre doing enterprise or web development today, you should either be using Java or .NET with AOP enhancements or you should be using a dynamic language like Ruby or Smalltalk.
Anonymous consultant colleague of mine
AOP in Ruby (??) ! Once you have decent reflection and metaclasses, AOP is just part of the language.
! Dave Thomas
c2.com/cgi/wiki?AspectsAndDynamicLanguages
12
AOP in Ruby (??) ! Is AOP really only a tool for static languages?
! Cross-cutting concerns are easier to address in dynamic languages because their metaprogramming facilities are better.
13
! Introduction
! Enhancing with new (orthogonal!) state and behavior .
! Inspection
! Access to meta-information that may be exploited by pointcuts or advice.
! Modularization
! Encapsulate as aspects.
14
Interception in Ruby (Slightly Better) ! define_method: not as clear, but more robust.
! Avoids potential namespace collisions (with other old_bars). ! Avoids namespace pollution (you want old_bar invisible). ! http://jayfields.blogspot.com/2006/12/ruby-alias-methodalternative.html
# foo.rb class Foo def bar "bar end end # foo_advice.rb class Foo old_bar = self.instance_method(:bar) define_method(:bar) do "{[< " + old_bar.bind(self).call() + " >]}" end end
15
f = Foo.new puts f.other # => {other} f.name = "FOO" puts f.name # => FOO
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 31
Introductions in Ruby (cont.) ! Add a method to an instance (Cant do this with AspectJ)
f = Foo.new def f.and_another and_another end puts f.and_another puts f.singleton_methods.inspect # A "singleton method"
class << f # Another way def yet_another; "yet another"; end end puts f.yet_another puts f.singleton_methods.inspect # => yet another # => ["yet_another", "and_another"]
16
s.method(:size).arity s.method(:replace).arity
17
18
19
Note: No Observer Interface ! An Observer interface is not required in Ruby. ! With duck typing, the pattern still works. ! How do we enforce the Observer contract?
20
New name: fred New name: fred New name: ed in add_observer: Observer must respond to receive_update. (RuntimeError)
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 41
About method_missing ! Used everywhere in Rails and other toolkits. ! Your method_missing often collides with mine ! Its a form of Introductions. ! Consider using aspects to preserve modularity and reduce collisions.
! Introduce expected methods by reopening classes, ! Reduce the actual calls to method_missing.
21
Off-the-Shelf Ruby AOP Tools ! AspectR. ! Facets. ! Ruby 1.9-2.0 Proposed Features:
! Cuts. ! Method Wrappers.
! Others
! aspectr.sourceforge.net
22
Facets ! Large Ruby Add-On Library. ! Aspects and Cut Modules. ! http://facets.rubyforge.org/
23
! http://www.erikveen.dds.nl/monitorfunctions/index.html
24
Cut-based AOP ! Proposed 1.9 or 2.0 language feature. ! Uses a subclassing-like syntax.
! Robust and fine-grained join point advising.
25
Method Wrappers
class Foo def foo:pre(*args) p "pre" end def foo:post(*args) p "post" end def foo:wrap(*args) p "wrap pre" super p "wrap post" end def foo(*args); p "foo; end end
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 51
So, Whats Missing? ! Disconnect between the AOP semantics and the code boilerplate.
! Extra mental mapping between metaprogramming (MP) API and AOP semantics required. ! Not as efficient as native AOP features. ! MP is harder for average developers to understand and use.
They struggle already with objects!
26
27
28
alias_method and class_eval Advice ! ~175 Uses of alias_method in Rails 1.2 stack.
! E.g., activerecord-1.15.2/lib/active_record/associations.rb module ActiveRecord::Associations::ClassMethods def has_and_belongs_to_many(association_id, options = {}, &extension) reflection = create_has_and_belongs_to_many_reflection(association_id, options, &extension) old_method = "destroy_without_habtm_shim_for_#{reflection.name}" class_eval <<-end_eval alias_method :#{old_method}, :destroy_without_callbacks def destroy_without_callbacks; ; end end_eval end
29
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 59
30
Aspect-Oriented Design
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 62
31
! AOP can be understood as the desire to make quantified statements about the behavior of programs, and to have these quantifications hold over programs written by oblivious programmers.
Obliviousness ! The writer of the source code is unaware that aspects may be applied to the code. ! Does a programmer have to do anything to prepare the code for aspects?
! At odds with Obliviousness.
! On the other hand, wouldnt module writers want to restrict some aspects?
! Limit accessible join points? ! Limit types of advice?
32
Version 1
name
??
BankAccount
first_name last_name
Version 2
! If the module is designed to be completely oblivious to possible aspects, it will probably not expose the necessary abstractions.
33
We Forgot OOD Principles ! Open-Closed Principle ! Liskov Substitution Principle ! Dependency Inversion Principle ! Others ! These principles can be extended for aspects
! aosd.net/2007/program/industry/I6-AspectDesignPrinciples.pdf
34
1993-2007 Object Mentor Incorporated. All Rights Reserved. www.objectmentor.com 1-800-338-6716 Version 1.0 / Page 69
35
36
Rails as a Frameworks ! The domain abstractions are closely tied to the persistence framework. ! The model objects are used in all tiers of a Rails application. ! The dependency on ActiveRecord sometimes gets in the way.
! Testing. ! Non-persistent model objects. ! Scalability
Rails as a Framework
# person.rb class Person < DomainObject # 1 has_many :Addresses end # address.rb class Address < DomainObject # 1 belongs_to :Person end
# active_record_persistance.rb
#2
37
! Aspects are a natural fit for keeping non-trivial, cross-cutting concerns modular.
Conclusions ! Ruby doesnt have native AOP support. ! Rubys metaprogramming features cover many requirements.
! We saw examples of what you can do today. ! 3rd-party libraries implement some AOP concepts.
! An AOP infrastructure will make it easier to implement cross-cutting concerns with less explicit metaprogramming.
38
39