My Aspect-Oriented Design Paper for AOSD 2007 Is Now Available

Posted by Dean Wampler Mon, 05 Mar 2007 00:57:00 GMT

I’m presenting a paper at AOSD 2007 called Aspect-Oriented Design Principles: Lessons from Object-Oriented Design (PDF on the AOSD 2007 Conference web site).

AOSD won’t succeed in the mainstream unless it can be used to build software with the essential characteristics expected of production code, e.g., agility, extensibility, maintainability, and of course, quality.

It shouldn’t be too surprising that principles of good OOSD apply to AOSD. Conversely, ignoring those principles is a recipe for failure. In fact, I argue that some of the early problems people have encountered with aspects and software “evolution” are really just cases of not applying these principles.

In this paper, I review 11 Principles of Good Object-Oriented Design, cataloged by Robert Martin, and discuss how they apply to aspect-oriented design (AOD), how aspects help implement them (e.g., by making it easier to achieve separation of concerns), how aspects introduce nuances into the interpretations of these principles, and finally, extensions of these principles unique to aspects.

My hope is that writers of aspects will be more successful if they apply these principles and that AOSD will prosper as a result.

I should warn you that the paper is written in a somewhat academic style, but hopefully the practicality of the principles will be clear. I’d love to hear your feedback! As time permits, I’ll try to blog about these principles here, in a less formal style ;)

By the way, if you’re really interested in AOSD, I hope to see you in Vancouver at the AOSD conference, March 12-16. I will be teaching a half-day tutorial on AOD. Please join me!

Posted in  | Tags , , ,  | no comments

Aspect-Oriented Design: "Humane Pointcut Languages"

Posted by Dean Wampler Fri, 21 Apr 2006 16:25:00 GMT

I started a discussion yesterday on the “aspectj-users” group about humane pointcut languages. The notion of “humane interfaces” in programming has been discussed by Martin Fowler and in the context of user interfaces and product design by Jef Raskin.

This conversation was a spin-off of another thread where I made a mistake that I occasionally make. An AspectJ user wanted to apply some after advice after constructor calls in a class that has an annotation, e.g.,
  @MyAnnotation
  public class Foo {
    public Foo(...) {...}
    ...
  }
He needed help writing the pointcut and advice for this case. Without repeating the whole conversation here, at one point I remarked that
  call( @MyAnnotation * *.new(..) )
matches constructors annotated with @MyAnnotation, while
  call( * (@MyAnnotation *).new(..) )
matches constructors in classes where the class has the annotation. In fact, both are invalid expressions because the first * is for the return type and there is no return type for constructors, so the first * shouldn’t be there. Hence, the correct statement is that
  call( @MyAnnotation *.new(..) )
matches constructors annotated with @MyAnnotation, while
  call( (@MyAnnotation *).new(..) )
matches constructors in classes where the class has the annotation.

This is the sort of mistake I make fairly often and I’m sure beginners really struggle with the pointcut syntax, although it’s generally great for experts because it is both succinct and powerful. However, sometimes a more “human-readable”, that is “humane”, syntax can be a real benefit.

In fact, I’ve been thinking about expressive pointcut languages quite a bit recently, not so much in this context, but more in the context of higher-level AOP abstractions. As I said in the discussion thread, it bothers me that we discuss high-level concerns, say for example security, then turn around and write PCDs using very low-level primitives that tend to reference specific classes, methods, etc.

Of course, I’m not the only person who thinks this way and the recent work on AO interface-based programming is a huge step towards making it possible to express aspects with appropriate levels of abstraction.

I would like to comment on this issue more in future blogs, but for now, let’s return to the original problem and look at some things we might do to make PCDs more humane.

The first thing I suggested in the thread is the addition of special keywords that could be substituted for some of the wild-cards:

Keyword Maps To:  Context
$any_return * Used for any return type
$any_arg * Used for any one method argument
$any_arglist .. Used for zero-many method arguments
$any_type * Used for any type expression (class, interface, ...)
So, our previous PCD that matches calls to the constructors could be written
    call( (@MyAnnotation $any_type).new($any_arglist) )

This is a little more readable, especially for new users, while experts will prefer the more terse form for its brevity.

As an aside, you could use a similar mechanism to support regular expression matching while minimizing the potential for confusion, as discussed here. Something like $re(/(foo|bar)$/) to match names ending in foo or bar, for example.

Let’s combine our new PCD with after advice, to see a little more context. We want to “bind” the newly-created Foo instance to a variable foo. Handling newly-created objects is tricky.
    after() returning(Foo foo): 
      call( (@MyAnnotation $any_type).new($any_arglist) ) {
        ...
    }
Another approach, if we’re using the execution join point, is the following:
    after(Foo foo): 
      execution( (@MyAnnotation $any_type).new($any_arglist) ) && this(foo) {
        ...
    }
However, the keywords are a small improvement. Let me suggest that a real “humane” PCD language should read more like English. Consider this rewriting of the same two expressions, using a made-up pointcut DSL:
    after() returning(Foo foo): 
      call(constructors().takingAnyArgs().inClassesAnnotatedWith(@MyAnnotation)) {
        ...
    }
and
    after(Foo foo): 
  execution(constructors().takingAnyArgs().inClassesAnnotatedWith(@MyAnnotation))
    && bindNewlyConstructedObjectTo(foo) {
    ...
}

This syntax is inspired by the syntax of mocking frameworks like JMock and equivalents in Ruby. Certainly my toy DSL could be improved; I made it up on the fly during the discussion thread yesterday.

However, because it reads like English, it is very self-documenting, making comprehension easier by AspectJ neophytes and even experienced AspectJ users who are new to the application. I think it’s useful to remember that most code is write once, read many. We may not like to type a lot, but a literate style pays dividends over time.

Note that the syntax of this DSL and the standard syntax express essentially the same pointcut language “abstraction” for AspectJ.

So, I think there is a place for a more “humane” form of the AspectJ pointcut DSL. Similarly, I think that we need DSLs appropriate for higher-level AOP abstractions (e.g., at the design level) and ideally AOP DSLs that are domain-specific for non-trivial domains.

Read more...

Posted in ,  | Tags , , , ,  | no comments | no trackbacks