The case for AOP in Python
There are many articles out there about AOP and python, and consequently, several AOP solutions for python are offered. The spectrum is broad, ranging from “python doesn’t need AOP” to “python has enough language features to do AOP without framework code” to “AOP works great with python” to “AOP is just another thing built for static languages someone is trying to bolt onto python”.
Someone made a good point back in 2004 on a python mailing list that AOP is a paradigm, not a specific framework, and that if we are going to argue against AOP in python, then it opens the door to arguing over OOP, and in turn, probably every paradigm that we know. Are you ready to throw out python classes and do everything functionally?
When Jim Moore gave his SpringSource presentation at my company a few weeks ago, he gave an excellent description of AOP: its a way to get the computer to help you drop in functionality where its needed, with minimal effort on your part.
Way back in the stone ages, we wrote programs based on how the CPU thinks: one line of code translates directly to one line of CPU instruction. As programs got bigger and bigger, we exceeded the ability to track a whole program. We needed to trim things down into smaller bites, so we could focus on one piece of logic at a time. Someone came up with the idea of combining a class of functionality based on data, and thus OOP was born. New programming paradigm; however, the CPUs are still pretty much the same. Did we worry about this? Of course! There were scores of debates on the merit of OOP. We had the compilers able to translate OOP into sequences of instructions, and just built OOP-aware tools to give us the right visibility. When the next generation of developers arrived, OOP was nothing new, and it has become a part of history.
AOP is another way to avoid DRY (don’t repeat yourself). As we write more sophisticated applications, we still find areas where the same riff of code needs to be sprinkled in several places. If we needed to update the code, we don’t want to edit it in 95 different places, and unfortunately, OOP can’t solve everything, considering its vertical-nature. We have already built compilers than can convert our OOP/AOP/structural programs into a sequence of steps for the CPU to execute. We just need the tools to help us maintain the right perspective. And…we need to wait for the next generation of developers to arrive to cement it into history. In my opinion, writing off AOP as “only needed by java developers” is akin to burying your head in the sand.
It is true that different languages have differing levels on how easily they can support the AOP paradigm. I agree that python is very adept, which is part of the reason that it took less time for me to implement an AOP solution than it possibly took to implement the Java-based one. I would generalize that other dynamic languages are probably quick as well for that.
Python has shown in many articles, that metaclass programming, using decorators, and some of the new python 2.5/2.6/3.0 constructs help as well. It depends on what you are doing. If you are in complete control of all source code, you have more options. Metaclass programming is possible, as are decorators.
Sometimes, you don’t control all the parts. You can read a whole thread, where a Spring Python newbie wanted to add a simple interceptor to an existing library, and trace a certain operation. Spring Python’s AOP module makes this very easy, because it works after the fact. Metaclass programming and usage of decorators would be very hard, unless you were willing to touch the library’s actual code. One key aspect that Spring Python seeks is to be non-obtrusive. Some of the other AOP libraries for python tend to require edits to the code itself.
Regardless of which library you use, the ability to easily intercept code and in turn add functionality based on a controlled pattern is nothing new. We needed OOP to accomplish this in some areas. We need AOP in others. And knowing how to utilize the full extension of a language sums it up. We need the ability to apply functionality at the right time, in the right place, without repeating ourselves.