Beyond Java - Bruce Tate [61]
Looking for further evidence that AOP-like solutions are easy in Ruby metaprogramming? The AspectR library adds some simple AOP operations to Ruby. Although not as complete as its sister library, AspectJ, from the Java world, the library itself is orders of magnitude smaller...clocking in at around 210 lines of code.
I'm not an AOP expert by any stretch of the imagination. But I've seen the relatively narrow set of problems addressed by AOP, and the wide range of metaprogramming solutions that keep cropping up in the Ruby world. Perhaps it is not Ruby that needs AOP, but Java that needs metaprogramming!
Of course, AOP is a much broader tool, and if it is successful, the typical use cases obviously will grow in scope and power. Right now, though, Java developers most frequently use the power of AOP through frameworks like Spring.
You can look at interceptors as a more primitive tool to accomplish the same sorts of things. The JBoss framework and containers like HiveMind use interceptors to provide a wide range of services, like transactions. For Ruby developers, AOP is not quite as urgent, because you've already got robust tools to deal with these kinds of concerns:
You can use interceptors. These let you add services to any object at any time. It's as easy as renaming one method and introducing another.
You can use mixins, even attaching them at runtime. You could easily make all of the methods on a domain model secure, for example.
You can use hooks . Ruby provides hooks so that you can inject custom code at certain well-defined locations. The next version of Ruby will support hooks called _ _before, _ _after, and _ _wrap.
In short, Ruby can already solve many AOP-like problems without AOP, and will add AOP-like features in the very near future. Some Ruby programmers are concerned that AOP code may be more difficult to maintain. The core value of AOP that's not yet supported in Ruby is the ability to specify a point cut quickly and efficiently, which lets you use regular expressions to define interceptors wherever you need them. Ruby already has the core features that should make point cuts easy to implement:
You can quickly query for the methods that an object supports.
You can match regular expressions.
You can invoke a method with a string.
You'll soon (Ruby 2.0) be able to hook Ruby methods with before, after, and wrap.
Ruby is very friendly to configure. You can specify the point cuts in Ruby, without requiring XML or a whole new syntax, like AspectJ.
Given these capabilities, AOP becomes a very lightweight feature. Right now, Ruby developers prefer to implement AOP-like features, piecemeal, in a style that best fits the architecture.
Dependency Injection
The difference dependency injection in Java and Ruby is a little tougher to understand for Java developers. In Java, dependency injection is rapidly changing the way that we build applications. It's a relatively simple concept:
class Speaker {
void speak(String words) {
System.out.println(words);
}
}
class Consumer {
Speaker mySpeaker;
void saySomething() {
mySpeaker.speak("something");
}
}
Notice Consumer. It doesn't instantiate Speaker. That job goes to a third party. We'll call it Container:
class Container {
public static void main(String[ ] args) {
Speaker speaker=new Speaker();
Consumer consumer=new Consumer();
consumer.mySpeaker = speaker;
consumer.saySomething();
}
}
You can make some simple improvements. You can encapsulate mySpeaker with a getter and setter. You can then extract an interface called Speaker, and provide implementations for FrenchSpeaker, EnglishSpeaker, and SpanishSpeaker. You can also make a configuration file, in Java or XML, describing all the objects that you want