Skip to content

Instantly share code, notes, and snippets.

@robmiller
Forked from Integralist/AOP.md
Created March 31, 2014 09:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robmiller/9888802 to your computer and use it in GitHub Desktop.
Save robmiller/9888802 to your computer and use it in GitHub Desktop.

What is AOP?

Aspect Oriented Programming is a means to change the behaviour of – or add behaviour to – methods and functions (including constructors) non-invasively. The added behaviour is called “advice” and can be added before, after, or around the function it advises.

This description is similar to the Extract Surrounding refactoring method. The difference is in the direction of the change. It seems AOP is more focused at modifying existing behaviour non-invasively; where as the Extract Surrounding Method actually changes the source code to allow this type of behavioural modification.

// Variation 1 (AOP format -> modifies behaviour without changing the `foo` method code)
var obj = {
foo: function(a, b, c) {
console.log('foo', a, b, c);
}
};
var originalMethod = obj.foo;
originalMethod(1, 2, 3) // => foo, a, b, c
obj.foo = function(a, b, c) {
console.log('before');
originalMethod.apply(this, arguments)
console.log('after');
};
obj.foo(1, 2, 3) // => before; foo, a, b, c; after
// Variation 2 (Same as the first but abstracted into reusable helper functions)
function before(f, advice) {
return function () {
advice.apply(this, arguments);
return f.apply(this, arguments);
};
}
function after(f, advice) {
return function () {
var result = f.apply(this, arguments);
advice.call(this, result);
return result;
};
}
var obj = {
foo: function(a, b, c) {
console.log('foo', a, b, c);
}
};
obj.foo = before(obj.foo, function(){
console.log('Before!!');
});
obj.foo = after(obj.foo, function(){
console.log('After!!');
});
obj.foo(1, 2, 3) // => Before!!; foo, a, b, c; After!!
// Variation 3 ("Extract Surrounding" format -> not AOP as it modifies the source `foo` method)
var obj = {
foo: function(before, after) {
if (before) before();
console.log('foo');
if (after) after();
}
};
function before(){
console.log('before');
}
function after(){
console.log('after');
}
object.foo(before, after);
module Around
def around(fn_name)
old_method = instance_method(fn_name)
define_method(fn_name) do |*args|
puts "before"
old_method.bind(self).call *args
puts "after"
end
end
end
class Foo
extend Around
def foo
puts "Foo!"
end
foo = around(:foo)
end
Foo.new.foo # => before; Foo!; after
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment