Beyond Java - Bruce Tate [60]
irb(main):009:0> i=[1,2,3]
Unattended laptop error. Unattended laptop error. Unattended laptop error.
Unattended laptop error. Unattended laptop error. Unattended laptop error.
Unattended laptop error. Unattended laptop error. Unattended laptop error.
Unattended laptop error. Irb(main):010:0>
That's an interceptor in eight lines of code. You get extra credit if you know which 10 objects get created. You don't have any Java proxies, code generation, or aspect-oriented programming. Of course, you'll not want to try this with the real Dave. That would be like throwing a firecracker under Albert Einstein's car. Like Albert and the atom, you don't want to unleash this kind of power without knowing where all the energy is going to go.
AOP
Java developers depend on AOP with increasing frequency. AOP lets you add services to your POJO without modifying any code. AOP helps you control the flow of your application, such as adding custom methods at interesting points—for instance, before or after a method executes. In particular, you'll often see AOP for:
Debugging or logging
AOP lets you add debugging or logging code everywhere that you need it, with very little syntax.
Declarative services
EJB used a container to provide services. You would specify the service with configuration rather than code. Lightweight containers do the same thing with AOP. You'll often see interceptors manage transactions, security, and remoting.
Mixins
Java doesn't provide mixins, but you can simulate them with AOP.
David Heinemeier Hansson and Jim Weirich, Two Ruby Experts: AOP in Ruby
Jim Weirich is a software consultant for Compuware. He has worked with real-time data systems for testing jet engines, networking software for information systems, and image processing software for the financial industry. Jim is active in the Ruby community, contributing to several Ruby projects including Rake and RubyGems.
Why hasn't AOP taken off for Ruby?
DHH: A standardized AOP framework has never really taken off in Ruby because the language itself already supports most of the desirable functionality of AOP.
The following is an example from Action Pack, the controller/view part of Rails. And here follows the code block that injects the layout functionality into the original render method:
base.class_eval do
alias_method :render_without_layout, :render
alias_method :render, :render_with_layout
end
So, we rename the original render method to render_without_layout, which we can then call from the enhanced render_with_layout method. And finally, we make the improved render_with_layout method take the place of render. So, we're hot-swapping out behavior of a base class with improved functionality without changing the public interface and without cluttering the base class with the enhancements directly. The next version of Ruby will take this a step further by including AOP-like constructs right in the language with pre, post, and wrap conditions.
JW: The metaprogramming capabilities of Ruby lie so close to the surface and are quite accessible to the average Ruby programmer. I suspect that most of the problems addressed by AOP are addressed by metaprogramming in Ruby.
Here's one example from the standard library. Date objects are immutable, so once you calculate the day of the week for any given date object, you could store that result and return it in later invocations without redoing the entire calculation. The code to check for a previously calculated value is simple enough to write, but it is tedious to implement it in each of the 13 or so methods in Date that could take advantage of it.
The author of the Date class took this approach. He wrote each method as if it would recalculate the value every time it was called (i.e., no special checking for previous values). Then he wrote a class method called once that takes a list of method names. The once method did the following: created an alias for the named