Monday, April 4, 2005

Another Smart Guy Hits the AOP Crack Pipe

Ted Neward recently blogged about Tim's XSLTO project. If I might be so bold as to summarize Ted's argument:

XSLTO looks like AOP. Tim thinks XSLTO is good. Therefore, Tim thinks AOP is good.

This is so full of holes you could strain your pasta through it. It's a classic case of overgeneralization, and in and of itself that's enough to render his argument moot. However, I'd like to examine it in slightly more detail.

Ted's basic argument is that since XSLTO uses declarative attributes to drive execution of code, and since AOP is based around more or less the same thing, that the two are equivalent. I disagree: XSLTO is a proper subset of what AOP advocates. It is a specific, specialized utilization of declarative programming. In this case, it's essentially a translation of XSLT into the C# realm, giving you the ability to process XML documents via recursive descent.  

Ted says:

And the richer and more flexible your pointcut/query system, obviously the more powerful your AOP system. This is why simple interception, such as the CORBA interceptor, .NET/COM+ context-bound attribute interceptor or Java dynamic proxy, is not a rich AOP system in the slightest--although powerful, it uses only one sort of joint point, and that in itself inherently limits your abilities. Imagine if OOP only allowed just one base class or interface; how useful would OOP be?

Still pretty damn useful, actually. I don't miss multiple inheritance in C#, despite it being a mainstay of C++. Adding more constructs to the language adds complexity, and that complexity adds cognitive overhead that can make the tool less useful in many situations. We have this conversation on the FlexWiki mailing lists all the time: people are constantly proposing extensions to the wiki syntax that bring it closer and closer to doing everything HTML can do. Of course, at some point you cross the line where you have to wonder why you should bother with having a wiki language at all? It's like Spider Man taught us: with great power comes great responsibility.

(Side note: Multiple interface implementation is probably a borderline case - I suspect we could get by without it, but since it adds less complexity than multiple inheritance, the increased cognitive load is probably worth the extra capabilities. That is not always generally true. Figuring out when it is and when it isn't is what designing good abstractions is all about, and it's really, really hard.)

Continuing. Quoting Ted:

As to the oft-quoted "killing blow" regarding AOP systems, that being that aspects cannot be ordered or stateful, it's interesting to note that people refuse to make similar accusations about XSLT, yet it (a) fundamentally presents much the same kind of programming model as an AOP-based system would, and (b) has similar problems with ordering and state, yet nobody's calling for XSLT to die....

Ted, if you want to compare AOP to XSLT, be my guest. Programming in XSLT every day of my life for everything I do would be enough to make me want to switch to a career in marketing. Just like XSLTO and AOP, XSLT is a specialized tool useful for a few very narrow problems. And just like XSLTO and AOP, it should be viewed as - although perhaps not a last resort - something you only pull out when you have a specific need, not a general-purpose tool.

At the end of the day, I guess what Ted and I disagree on is the extent to which AOP concepts are useful. I say, “very little, but not zero”, and he takes a view that is presumably much broader than that. I view XSLTO as a useful replacement for some of what XSLT does. And I view XSLT as a useful replacement for some of what the .NET XML APIs do. But most of the time I'm going to stick with my favorite API, XmlSerializer, and stay the hell away from frameworks that drive execution1 via declarative means. I take the same attitude towards (other) AOP frameworks: I'll use them when I've exhausted other options, and not before.

1. Yes, I realize XmlSerializer is declarative. But it's a declarative serialization engine, not a declarative execution engine. (That is, I don't need to debug into it except when I have problems, which is when it sucks the worst. But that just makes my point.) I have found this to be a very significant difference in practice. And again, a concept that is useful only in a narrow context.


  1. I have no idea what I am talking about, but isn't AOP more geared toward the non-functional requirements in a project such as instrumentation and logging?

  2. That's actually my point: AOP is useful in narrow scenarios, not as a general programming practice. Instrumentation, security, and logging are the ones you always hear about, because they're (almost) the only ones that are orthogonal, and therefore (almost) the only ones that AOP is any good at. Using it for (e.g.) transactions is a bad idea because of the interaction issues.