Jason Williams <jason / jasonandali.org.uk> wrote in message news:<slrnbkot3p.1d5.jason / kotu.jasonandalishouse.org.uk>... > In article <8ef9bea6.0308261857.1b44a5b7 / posting.google.com>, Hung Jung Lu wrote: > > If you write programs in OOP long enough, you will realize that there > > are code spots that are not factorized. For example, you register to a > > event listener at the beginning and de-register at the end of a > > method. > > Eh? What's wrong with; > > def methodThatHasToListenForAnEvent > listenForEvent(e) do > # The method stuff goes here > end > end The question is: are there code spots that are not factored? If you have ONE single class that has to implement the before, around, or after methods, sure, nothing wrong with what you have said. But, if you have class A: def f1(): register() ... deregister() class B: def f2(): register() ... deregister() class C: def f3(): register() ... deregister() You start to ask your self: how come the register() deregister() parts are not factor out? How can I factor out these parts of code? Why do you want to factor them out? You may ask. Because sometimes later, you may realize that, heh, actually you want to do one more thing before calling f1() f2() f3(): at beginning of the calls you want to log the method call. If you don't have AOP, you would have to manually modify each class into: class A: def f1(): log() register() ... non-factorizable code specific to f1 deregister() class B: def f2(): log() register() ... non-factorizable code specific to f2 deregister() class C: def f3(): log() register() ... non-factorizable code specific to f3 deregister() And later, you find out that you want to catch an certain type of exception and respond properly, without AOP, you go back to your code and write something like: class A: def f1(): try: log() register() ... non-factorizable code specific to f1 deregister() except: ... class B: def f2(): try: log() register() ... non-factorizable code specific to f2 deregister() except: ... class C: def f3(): try: log() register() ... non-factorizable code specific to f3 deregister() except: ... And then you realize that, oh, when the exception happens, you need to do some clean up, then you go back to your code and do class A: def f1(): try: log() register() ... non-factorizable code specific to f1 deregister() except: ... finally: ... class B: def f2(): try: log() ... non-factorizable code specific to f2 ... deregister() except: ... finally: ... class C: def f3(): try: log() register() ... non-factorizable code specific to f3 deregister() except: ... finally: ... And then, someone tells you that they want to know the time spent in these methods, so you do: class A: def f1(): start_timer() try: log() register() ... non-factorizable code specific to f1 deregister() except: ... finally: ... end_timer() class B: def f2(): start_timer() try: log() ... non-factorizable code specific to f2 ... deregister() except: ... finally: ... end_timer() class C: def f3(): start_timer() try: log() register() ... non-factorizable code specific to f3 deregister() except: ... finally: ... end_timer() And it is at this point that you start to wonder, man, it's tedious and error-prone trying to do the something to all the classes that share similar functionalities. And at the moment, you start to wonder whether you can factor out the similarities. Notice that OOP or class inheritance will not allow you to factor out these types of "horizontal common code spots". A way to see it is to have three sheets of paper, and you write the code of class A, B, C on each sheet, and stack the three sheets together. The common areas that overlap are in a horizontal direction. This type of horitontal factorization is what AOP is all about. Once you factor out the common parts, you can modify the code spot just once, and it will be applied automatically to all your classes. To my, horizontal factorization is what AOP is all about. It goes beyond the before-, around-, after- hooks. I've written codes where I have many if statements in a base class method: def f(): #--------------- step 1 during calculation code shared under all circumstances #--------------- step 1 during calculation if self.has_fixed_rate(): .... else: .... if self.is_government_bond(): .... else: .... if self.is_domestic(): .... else: .... #--------------- step 2 during calculation code shared under all circumstances #--------------- step 3 during calculation if self.has_fixed_rate(): .... else: .... if self.is_domestic(): .... else: .... #--------------- step 4 during calculation code shared under all circumstances #--------------- step 5 during calculation if self.is_domestic(): .... else: .... if self.is_government_bond(): .... else: .... After writing so many if...else... statement, you start to wonder: can I factor out these if...else... statements? One way is to use OOP and subclasses to encapsulate the is_domestic(), is_government_bond(), has_fixed_rate() features, (e.g: have a subclasses like domestic_fixed_rate_government_bond foreign_variable_rate_corporate_bond, etc.), but in OOP you will find out that common steps 1,2,4 will not be factored out, and that when you need to change the code in the common steps, you need to change in all subclasses, which is tedious and error-prone. Worse, with 3 features you have a combination of 8 subclasses, and if one day you include one more feature, you will have 16 subclasses. Are you going to change the code manually in 16, 32, 64 classes? Clearly inheritance is not the way to implement properties/features like these ones. OOP just cannot solve the problem. It is only when you run into this kind of situations, that you start to think about code factorization in a different dimension. AOP is a really need. I would agree that it is still an immature field of research. But people really need it. Hung Jung