I have been using Java + AspectJ extensively for my startup. I would love to switch to Scala but I have a common design pattern that I am not sure entirely the best way to implement in Scala.
A tremendous amount of our application uses AspectJ pointcuts using annotations as the marker. This is very similar to Python's decorator and blogged about it here.
I have tried doing this technique in Scala but had problems with AspectJ + Scala. Even if I did get it to work it seems unScala like.
I have seen some projects do some call-by-name closure magic (I think thats what they are doing).
Example of a replace of @Transaction:
transaction {
// code in here.
}
I have to say though I prefer the annotation more as it seems more declarative. What is the Scala way of declaratively "decorating" code blocks?
Incidentally, I am giving a talk at Scala Days 2011 on the same topic. The core idea is the same as Kim's and Dean's example. However, when it comes to the full spectrum of crosscutting concerns, similarity and differences become more nuanced.
On one end of the spectrum, there are not-really-crosscutting concerns such as caching. When the host language doesn't support higher-order functions (for example, Java), implementing the concern as an aspect becomes attractive. For example, with AspectJ and annotation approach, you can say:
@Cacheable(keyScript="#account.id")
public double getNetWorth(Account account) {
... expensive computation
}
But with higher-order function in Scala, you can do:
def getNetWorth(account: Account) : Double = {
cacheable(keyScript=account.id) {
... expensive computation
}
}
The Scala approach is much better, because:
keyScript
is unlikely to be the same or easily expressible in a generic form. In the middle, there are common crosscutting concerns transaction management and security. On the surface, they look much like caching. However, we find in practice that applying these functionalities to all methods of a class (with generic sub-selection such as those with public access) or all methods of all classes marked with an annotation (say @Service
) is common. If such is the case, the AspectJ approach ends up being superior, since it provides a way to apply the functionality at a higher level that higher-order functions. You no longer have to surround each and every method with transactional {}
or secured {}
, when a class-level annotation will do just fine. For security-like concerns, AspectJ approach allows an easier way to perform security auditing.
On the other end of the spectrum are crosscutting concerns such as tracing, profiling, monitoring, policy enforcement, auditing, some forms of concurrency control (such as Swing's/SWT/Android UI thread dispatching), etc. These lend themselves very well to be selected by a pointcut (with and often without annotations). It is very difficult to do the same in a consistent manner using higher-order functions alone.
There are more semantic nuances, but the bottom line is that when you find annotating every method to have a crosscutting concern applied, higher-order function is likely to be a better approach. For others, using Scala with AspectJ is likely to provide consistent and compact solution.
p.s. I haven't tried AspectJ+Scala in Eclipse lately (since Scala in Eclipse started to work only recently). But external build using Maven worked fine after http://lampsvn.epfl.ch/trac/scala/ticket/4214 was fixed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With