More thoughts on AOP, and why we don’t need it.
Was reading some more about AOP here on Natty Gur’s advice. I can’t say I’m all that impressed. This article mainly describes using AOP to optimize performance. But at the moment, the AOP tools carry extra performance overhead. I thought the point was to help write clearer code, and “untangle the aspects”.
At any rate, I haven’t seen any examples of actual real-world programming problems that cannot be solved elegantly with objects. As far as I can tell, the image processing optimization problem from that article can be solved elegantly using the Strategy pattern. No aspects needed. AOP advocates have a tendency to beat up on straw men with their examples.
I know a lot of people have trouble with objects, but I really think the last thing we need is a slew of complicated new runtime features in programming languages. Most people have enough trouble with polymorphism, inheritance, and encapsulation. Now they have pointcuts, advice, join-points, and more to think about. Is this really going to lead to cleaner programs? I doubt it.
I think the biggest problem with OOP right now is the way it is taught. First, there is tremendous overemphasis on the idea of inheritance. Inheritance is an import OO technique, but not nearly as important as composition. Anything you can do with inheritance you can do with composition, but the reverse is certainly not true. Secondly, people are always taught that you can implement domain objects using classes. This is not a good idea. But beginning examples of oo programming always have an example like this:
public class Customer
{
string FirstName;
string LastName;
string PhoneNumber;
}
Your going to need to do a lot of stuff with your Customer object. Lets try to enumerate some of them.
1) Store it in a database.
2) Serialize it to XML (maybe multiple formats)
3) Serialize it to a binary format.
4) Validate it.
5) Compare it to another Customer Object, possibly identifing differences.
6) Resolve references to other association entities (such as Orders) that are not available in memory.
7) The list can and will go on…
Now, in OO 101 you would add these behaviors as methods to your Customer object. Of course customer is not the only class you are going to deal with, you are going to have Orders, Deliveries, Complaints, etc… As you implement the above methods for all of those types, you start to realize you need a Supertype, and using inheritance you start factoring out similar code from all of your classes. You go even farther with template methods. If you are really dilligent about this, you end up with a large heirarchy of classes that each have dozens of little methods and it is very difficult to figure out with class contains a given piece of functionality that you need to tweak. Going forward, your heirarchy becomes more and more obscure as more baggage is added to it. Despite all your best efforts, duplicate code starts cropping up all over the place.
Lots of people have this problem, but it doesn’t mean that the OO paradigm is fundamentally flawed. You just aren’t doing it right yet. The right way is to use composition to build a dynamic object model. And to construct your domain objects out of lower level building blocks. More on that next time.