March 04, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath |
"Regan Heath" <regan@netwin.co.nz> wrote in message news:opsm1bmre123k2f5@ally...
> Well, true, technically.
> The way I see it, you're simply stating.
>
> Take class A. add concern C1,C2 to method x,y, and z. call it C12_A. Take class B. add concern C1,C3 to method x, and y. call it C13_B.
>
> It is similar to inheritance, as in, you could do it manually...
>
> class A {
> void foo() {}
> }
>
> class C12_A : A { <- take class A, call it C12_A
> void foo() {
> ..concern.. <- add concern to method foo
> super.foo();
> ..~concern..
> }
> }
Before the topic gets dropped, I read about AOP a couple of years ago and forgot about it. (-: But there was a Java reference implementation which could be perused. Also, I *think* you can do cross-cuts on variables as well as functions. This may pose a problem for
class T { int _a; }
class B {
public T t;
}
B = new B(); // special case for init of t
B.t = something(); // check t again
B.t._a = 3; // could even have a check on an int
|
March 05, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Hi,
are you sure a new class gets defined? I though the point was to add functionality to existing classes without actually modifying them directly.
There are three issues that are addressed by AOP - scattering (similar code all over the place), tangling (same span of code doing more than one thing) and crosscutting (if I get it right, the problem of connecting modules that do completely different stuff, like a profiler and profilee).
The typical case seems to be logging - you normally have to include logging code in all the classes you want to log (scattering+tangling), and you need to have a Logger class and pass it all around (crosscutting). This results in a large amount of code, and it's not even related to the original class functionality (an ImageProcessor should process images, not concern itself with logging). If you don't want to use Logger anymore, but a different class, you have to change all the classes that use it.
Conversely, if you have AOP at hand, you can just write an aspect that takes care of logging without modifying the original classes' code. This is obviously more efficient, especially in the amount of code to be written, ease of turning the functionality on/off (you can just remove the aspect) and modifyability (is this a word? anyway, it's really easy to do something different with all the concerned classes). It's also a cleanly defined "link" between the logging part of your app and its other parts.
Now, as far as compiling goes, what is done at compile time is that all aspects that are turned on are resolved and classes are compiled with their original code wrapped in aspect code. I'm really almost sure that you don't get a new class (it does have additional functionality, of course, but its name and position in class hierarchy are still exactly the same). For example, in AspectJ, you can attach code to reading/writing a field and calls of methods, ctors and exception handlers (you can match both before and after). So, for each of those, all matching aspects are identified and their code is inserted.
xs0
Regan Heath wrote:
> On Wed, 2 Mar 2005 23:39:21 +0000 (UTC), pandemic <pandemic_member@pathlink.com> wrote:
>
>> In article <d051g0$fq8$1@digitaldaemon.com>, Walter says...
>>
>>>
>>> Thank-you. That actually does make sense. I can see now why it would be an
>>> interesting feature. I can only understand these things in terms of how they
>>> are implemented :-). So for AOP, what I see is being essentially a derived
>>> class, with the modified methods being created that are wrappers around the
>>> base class's methods. The aspect code is inserted into the wrappers.
>>>
>>>
>>
>> Yes and no. As I understand it, the real power of AOP lies in its ability to cut
>> across multiple, perhaps unrelated, classes. Without a common base-class, and no
>> multiple inheritance. It's not really class-oriented, since the methods involved
>> are often identifed using a limited regex form (select all 'put' methods across
>> all classes, for example).
>
>
> Well, true, technically.
> The way I see it, you're simply stating.
>
> Take class A. add concern C1,C2 to method x,y, and z. call it C12_A.
> Take class B. add concern C1,C3 to method x, and y. call it C13_B.
>
> It is similar to inheritance, as in, you could do it manually...
>
> class A {
> void foo() {}
> }
>
> class C12_A : A { <- take class A, call it C12_A
> void foo() {
> ..concern.. <- add concern to method foo
> super.foo();
> ..~concern..
> }
> }
>
> but the idea is that it's done automatically, via some description/format and can be done to any base class, not just A, that you can add several different concerns to a class, that you can pick methods for each concern and they may differ to picks for another concern.
>
> Or am I missing your point? I must admit my understanding of it comes from a couple of articles I've read and not much else.
>
> Regan
|
March 07, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to xs0 | On Sat, 05 Mar 2005 10:45:31 +0100, xs0 <xs0@xs0.com> wrote: > are you sure a new class gets defined? Yes, though it's defined in a different manner to inheritance. > I though the point was to add functionality to existing classes without actually modifying them directly. Correct. > There are three issues that are addressed by AOP - scattering (similar code all over the place), tangling (same span of code doing more than one thing) and crosscutting (if I get it right, the problem of connecting modules that do completely different stuff, like a profiler and profilee). > > The typical case seems to be logging - you normally have to include logging code in all the classes you want to log (scattering+tangling), and you need to have a Logger class and pass it all around (crosscutting). This results in a large amount of code, and it's not even related to the original class functionality (an ImageProcessor should process images, not concern itself with logging). If you don't want to use Logger anymore, but a different class, you have to change all the classes that use it. > > Conversely, if you have AOP at hand, you can just write an aspect that takes care of logging without modifying the original classes' code. This is obviously more efficient, especially in the amount of code to be written, ease of turning the functionality on/off (you can just remove the aspect) and modifyability (is this a word? anyway, it's really easy to do something different with all the concerned classes). It's also a cleanly defined "link" between the logging part of your app and its other parts. I agree with the description(s) above. > Now, as far as compiling goes, what is done at compile time is that all aspects that are turned on are resolved and classes are compiled with their original code wrapped in aspect code. That seems to me to be how Walter see's it working (from his reply earlier). > I'm really almost sure that you don't get a new class (it does have additional functionality, of course, but its name and position in class hierarchy are still exactly the same). You need a new name to refer to the old class + new functionality. The old class + new functionality is a new 'thing' which sits somewhere else in the heirarchy, it's not identical to the old class. IMO AOP is just a different form of code sharing, like a mixin and the result is a new class. Regan |
March 07, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Hopefully we won't do the same thing as the last time :) >> I'm really almost sure that you don't get a new class (it does have additional functionality, of course, but its name and position in class hierarchy are still exactly the same). > > > You need a new name to refer to the old class + new functionality. > > The old class + new functionality is a new 'thing' which sits somewhere else in the heirarchy, it's not identical to the old class. > > IMO AOP is just a different form of code sharing, like a mixin and the result is a new class. If you look at http://dev.eclipse.org/viewcvs/indextech.cgi/~checkout~/aspectj-home/doc/progguide/examples-development.html you'll see that no new class names are produced. It wouldn't make sense either - the point, if you want logging, for example, is to have exactly the same code (including class hierarchy) for the logged part, and turn on logging from outside.. Or, to put it another way, there is a "new" class, but it has the same name as the "old" class and the old class doesn't exist anymore.. Or, yet another way, with AOP, the class is no longer just itself, but itself+all its aspects.. xs0 |
March 07, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to xs0 | On Mon, 07 Mar 2005 09:29:33 +0100, xs0 <xs0@xs0.com> wrote: >>> I'm really almost sure that you don't get a new class (it does have additional functionality, of course, but its name and position in class hierarchy are still exactly the same). >> You need a new name to refer to the old class + new functionality. >> The old class + new functionality is a new 'thing' which sits somewhere else in the heirarchy, it's not identical to the old class. >> IMO AOP is just a different form of code sharing, like a mixin and the result is a new class. > > If you look at > http://dev.eclipse.org/viewcvs/indextech.cgi/~checkout~/aspectj-home/doc/progguide/examples-development.html > > you'll see that no new class names are produced. It wouldn't make sense either - the point, if you want logging, for example, is to have exactly the same code (including class hierarchy) for the logged part, and turn on logging from outside.. I see. I don't like it. > Or, to put it another way, there is a "new" class, but it has the same name as the "old" class and the old class doesn't exist anymore.. > Or, yet another way, with AOP, the class is no longer just itself, but itself+all its aspects.. The very reason I don't like it. What if I want to use the old class and the new class in the same application? Regan |
March 07, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath |
>> Or, to put it another way, there is a "new" class, but it has the same name as the "old" class and the old class doesn't exist anymore..
>> Or, yet another way, with AOP, the class is no longer just itself, but itself+all its aspects..
>
> The very reason I don't like it. What if I want to use the old class and the new class in the same application?
Well, as far as I know, you can't - the aspect is an integral part of the class (or method), just like class members are, it's just defined elsewhere because it may not be what the class is about. For example, the purpose of a Shape class is to have something that can draw itself, and not also to perform timing measurements, so it makes sense to put such profiling code outside in an aspect, where it can be turned off when no longer needed. It can also be reused for all other cases where you want to measure performance, because it is not tied in to Shape. Of course, you can reuse such code as is by putting it inside some class (Profiler), but you need to change your classes to use it, and then again to not use it anymore, when you're done.
If you take a look at what the typical aspects are (tracing, logging, change monitoring, etc.), it would seem you don't use them in cases where you don't want the new behavior. Like, if you want to log all calls to some method (or whatever), you can't also want to not log some of them (of course, the logging code can choose to not do anything, but it's still "turned on" all the time).
You do have the option of defining pointcuts for just classes that are of interest, and, of course, if you want to control this inside the classes themselves, you don't need aspects, I guess..
xs0
|
March 07, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to xs0 | On Mon, 07 Mar 2005 11:02:58 +0100, xs0 <xs0@xs0.com> wrote: >>> Or, to put it another way, there is a "new" class, but it has the same name as the "old" class and the old class doesn't exist anymore.. >>> Or, yet another way, with AOP, the class is no longer just itself, but itself+all its aspects.. >> The very reason I don't like it. What if I want to use the old class and the new class in the same application? > > Well, as far as I know, you can't Using my concept, I can. What do you mean by "as far as I know" are you talking about an existing implementation, if so, is it the "JAspect" one, if so, why do we have to do it that way? > If you take a look at what the typical aspects are (tracing, logging, change monitoring, etc.), it would seem you don't use them in cases where you don't want the new behavior. Well obviously you won't use them if you don't want them. My point is that it's entirely possible I want to use them on a class at one point in my code and not on that same class at another point. Eg. Locking, I need to lock access to the members of a class, but only if it's being shared between threads. > Like, if you want to log all calls to some method (or whatever), you can't also want to not log some of them Yes, I can. It's called targetting a specific instance. It would be great for debugging. > (of course, the logging code can choose to not do anything, but it's still "turned on" all the time). There was a facility in the AOP article I read to do this. The aspect was included, but it decided not to do it's thing some of the time. > You do have the option of defining pointcuts for just classes that are of interest, and, of course, if you want to control this inside the classes themselves, you don't need aspects, I guess.. You never want to "control this inside the classes themselves" that would defeat the purpose of AOP. However, you might want to enable or disable logging with a button, that button would flip a variable, that variable would be checked by the AOP code (not the class itself), it's the feature I described above. In addition to this feature, you might want to apply the AOP code to an instance of a class and not another. I see no point in limiting AOP in the ways you describe. Regan |
March 07, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | First, I'd like to say that I responded to your claim that an aspect causes a new class to be produced (with the original one still available), which I disagreed with, so please, let's keep the discussion focused on that. >> Well, as far as I know, you can't > > Using my concept, I can. What do you mean by "as far as I know" are you talking about an existing implementation, if so, is it the "JAspect" one, if so, why do we have to do it that way? No, I was talking in general. I think that if you want two versions of the class, you need to declare the new class (if for no other reason, to give it a name), which is very different than declaring an aspect (which just modifies the existing class). If you do declare a new class, you can of course implement the new functionality using an aspect that matches the new class but not the old class. Or, you can just use a mixin.. >> If you take a look at what the typical aspects are (tracing, logging, change monitoring, etc.), it would seem you don't use them in cases where you don't want the new behavior. > > Well obviously you won't use them if you don't want them. My point is that it's entirely possible I want to use them on a class at one point in my code and not on that same class at another point. Well, then you can implement the aspect in a way that supports this. The point is that the aspect code still gets executed all the time, even though it can obviously do nothing if it is written that way. That does not require two different classes. > Eg. Locking, I need to lock access to the members of a class, but only if it's being shared between threads. I don't see how you can do this by producing a new class (how will you switch implementation in runtime? except by creating a new instance, or by using a proxy, but I guess that causes more trouble than it solves), while I can see how you could do this with a single class (e.g. if (shared) { mutex.acquire(); }). So, please provide an example how you would do this. >> Like, if you want to log all calls to some method (or whatever), you can't also want to not log some of them > > Yes, I can. It's called targetting a specific instance. It would be great for debugging. That's not logical - if you want to log all calls, you want to log all calls, not just some :) On a more serious note, you can easily implement what you want by having the aspect check some variable to see whether the instance is the one you're interested in. However, the aspect will still get executed on all calls to the method in all instances. >> (of course, the logging code can choose to not do anything, but it's still "turned on" all the time). > > There was a facility in the AOP article I read to do this. The aspect was included, but it decided not to do it's thing some of the time. Can I have the link to the article? >> You do have the option of defining pointcuts for just classes that are of interest, and, of course, if you want to control this inside the classes themselves, you don't need aspects, I guess.. > However, you might want to enable or disable logging with a button, that button would flip a variable, that variable would be checked by the AOP code (not the class itself), it's the feature I described above. Sure, AOP code can check a variable, but I don't see how this requires a new class to be produced. > In addition to this feature, you might want to apply the AOP code to an instance of a class and not another. I see no point in limiting AOP in the ways you describe. I would argue that your approach is the one that is limiting. Consider this: class A { } aspect B { // match A and do something with it } A obj=new A(); Now, if the aspect produces a new class (even if it is named A_B (or whatever) automatically), you need to change the last line to A obj=new A_B(); to use the aspect. I don't see how that could be useful (I mean, it's far easier to just modify A than to modify all references to A). You seem to see aspects as something similar to mixins, but they are actually quite different, even though they superficially seem to do the same thing - include some code somewhere. Mixins' primary purpose is to reuse a piece of code instead of typing it over and over again. Aspects' primary purpose is to connect two parts of an app that do not have much in common, in a way that is clean and doesn't require those parts to handle each other. For example, you can have a rendering module and a profiling module. It does not make sense for the rendering module to call the profiling module (which is the non-AOP way), because the rendering module should not concern itself with profiling. Likewise, the profiling module should not need to know that there exists a rendering module, because its purpose is to measure time (or memory or whatnot). So, the solution AOP provides is to have those two modules completely unaware of each other, and the only thing that provides profiling of rendering is the aspect. The benefits are obvious - in non-AOP code, you will need to have every rendering class you want to profile be aware of a profiler, you will need to implement methods to set the profiler that is used (and you will also need to set it somewhere), each draw() method will need to call functions of the profiler; when you decide you no longer need the profiling code, you will have to manually delete it from everywhere (or set the profiler to null, but that will require a bunch of null-checks slowing the thing down). If you decide to use a completely different profiler (i.e. a non-compatible class), you will again have to manually change all references to the new one, possibly also changing which methods get called and in what order. If you use AOP, you avoid all that. xs0 |
March 07, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to xs0 | On Mon, 07 Mar 2005 14:16:18 +0100, xs0 <xs0@xs0.com> wrote: >>> Well, as far as I know, you can't >> Using my concept, I can. What do you mean by "as far as I know" are you talking about an existing implementation, if so, is it the "JAspect" one, if so, why do we have to do it that way? > > No, I was talking in general. I think that if you want two versions of the class, you need to declare the new class (if for no other reason, to give it a name), which is very different than declaring an aspect (which just modifies the existing class). Nope. IMO adding aspects to a class defines a new class. >>> If you take a look at what the typical aspects are (tracing, logging, change monitoring, etc.), it would seem you don't use them in cases where you don't want the new behavior. >> Well obviously you won't use them if you don't want them. My point is that it's entirely possible I want to use them on a class at one point in my code and not on that same class at another point. > > Well, then you can implement the aspect in a way that supports this. The point is that the aspect code still gets executed all the time, even though it can obviously do nothing if it is written that way. That does not require two different classes. This is less efficient. >> Eg. Locking, I need to lock access to the members of a class, but only if it's being shared between threads. > > I don't see how you can do this by producing a new class (how will you switch implementation in runtime? You wont. You simply need a locked version of class Foo at one point, and not at another. > except by creating a new instance Exactly. You create a LockedFoo when you need a shared one, and a Foo when you don't (see below). > , or by using a proxy, but I guess that causes more trouble than it solves), while I can see how you could do this with a single class (e.g. if (shared) { mutex.acquire(); }). So, please provide an example how you would do this. The aspect calls mutex.acquire() instead of the class itself. So, instead of "if (shared) mutex.acquire();" we just apply the locked aspect to the class. eg. class Foo { void baz() {} } <.. AOP definition defining locked version of Foo ..> LockedFoo; LockedFoo a; static this() { a = new LockedFoo(); } void main() { Foo b; ..create threads, threads share 'a' .. b = new Foo(); <- nothing but main accesses 'b' ..use b.. a.baz(); <- aspect calls mutex.acquire(); } >>> Like, if you want to log all calls to some method (or whatever), you can't also want to not log some of them >> Yes, I can. It's called targetting a specific instance. It would be great for debugging. > > That's not logical - if you want to log all calls, you want to log all calls, not just some :) It's perfectly logical. I didn't say I wanted to "log all calls". I said "targetting a specific instance", in other words I wanted to "log calls for specific instances", not "all calls". > On a more serious note, you can easily implement what you want by having the aspect check some variable to see whether the instance is the one you're interested in. However, the aspect will still get executed on all calls to the method in all instances. I could, but that requires a global var, and is less efficient. >>> (of course, the logging code can choose to not do anything, but it's still "turned on" all the time). >> There was a facility in the AOP article I read to do this. The aspect was included, but it decided not to do it's thing some of the time. > > Can I have the link to the article? It was in DrDobbs Journal. Written by "Christopher Diggin" (sp?) I cannot remember the issue (the mag is at work). I have posted the article info in another message to this NG, if you search you might find it. >>> You do have the option of defining pointcuts for just classes that are of interest, and, of course, if you want to control this inside the classes themselves, you don't need aspects, I guess.. > >> However, you might want to enable or disable logging with a button, that button would flip a variable, that variable would be checked by the AOP code (not the class itself), it's the feature I described above. > > Sure, AOP code can check a variable, but I don't see how this requires a new class to be produced. It doesn't. This is another feature described in the article. It's for runtime enable/disable of an aspect. >> In addition to this feature, you might want to apply the AOP code to an instance of a class and not another. I see no point in limiting AOP in the ways you describe. > > I would argue that your approach is the one that is limiting. Consider this: > > class A { > } > > aspect B { > // match A and do something with it > } > > A obj=new A(); > > Now, if the aspect produces a new class (even if it is named A_B (or whatever) automatically), you need to change the last line to > > A obj=new A_B(); no, A_B obj = new A_B(); > I don't see how that could be useful It's useful because you can _also_ say: A obj = new A(); at the same time, and use both the normal class and the class with aspects applied. > (I mean, it's far easier to just modify A than to modify all references to A). True, which is why, if it's an aspect for debugging/profiling, one that would be enabled/disabled a lot and/or periodically you would use an alias, eg. class NormalFoo {} <.. aspect ..> LockedFoo; alias Foo NormalFoo; ... Foo f = new Foo(); just as we've been doing in C/C++ for years (with #define). > You seem to see aspects as something similar to mixins, but they are actually quite different, even though they superficially seem to do the same thing - include some code somewhere. Mixins' primary purpose is to reuse a piece of code instead of typing it over and over again. Aspects' primary purpose is to connect two parts of an app that do not have much in common, in a way that is clean and doesn't require those parts to handle each other. I understand your concept, I just don't think it makes for a better AOP implementation than my own. Your's appears (to me) to be less flexible and/or less efficient (due to inflexibility). > For example, you can have a rendering module and a profiling module. It does not make sense for the rendering module to call the profiling module (which is the non-AOP way), because the rendering module should not concern itself with profiling. Likewise, the profiling module should not need to know that there exists a rendering module, because its purpose is to measure time (or memory or whatnot). So, the solution AOP provides is to have those two modules completely unaware of each other, and the only thing that provides profiling of rendering is the aspect. > > The benefits are obvious - in non-AOP code, you will need to have every rendering class you want to profile be aware of a profiler, you will need to implement methods to set the profiler that is used (and you will also need to set it somewhere), each draw() method will need to call functions of the profiler; when you decide you no longer need the profiling code, you will have to manually delete it from everywhere (or set the profiler to null, but that will require a bunch of null-checks slowing the thing down). If you decide to use a completely different profiler (i.e. a non-compatible class), you will again have to manually change all references to the new one, possibly also changing which methods get called and in what order. If you use AOP, you avoid all that. I agree with this example, it's a good description of where you'd use AOP. I still prefer my concept/method of implementing it. Regan |
March 08, 2005 Re: Aspect Oriented Programming for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | > Nope. IMO adding aspects to a class defines a new class. Well, I looked at several AOP languages, and you seem to be the only one that thinks aspects define a new class. If I'm wrong, please provide a reference (preferably on web this time). >> Well, then you can implement the aspect in a way that supports this. The point is that the aspect code still gets executed all the time, even though it can obviously do nothing if it is written that way. That does not require two different classes. > > This is less efficient. How? I'd say it's faster to check a var than to execute completely different code, because modern CPUs rely on cache so heavily, its far more efficient to stay within cache than to avoid two CPU instructions. That is even more true in the case you're arguing (tracking a single instance), because the branch predictor will be right most of the time, avoiding even the potential cost of conditional jump (i.e. pipeline flush). >> I don't see how you can do this by producing a new class (how will you switch implementation in runtime? > > You wont. You simply need a locked version of class Foo at one point, and not at another. Why do you need an aspect for this? There is no cross-cutting concern and whatnot, if that is what you want to do.. >> Now, if the aspect produces a new class (even if it is named A_B (or whatever) automatically), you need to change the last line to >> >> A obj=new A_B(); > > no, A_B obj = new A_B(); How is that less of a change? >> I don't see how that could be useful > > It's useful because you can _also_ say: > > A obj = new A(); > > at the same time, and use both the normal class and the class with aspects applied. But there is no point in using aspects if all you want is different versions of the same class. Or, as a question, why would you use an aspect in this case? > I agree with this example, it's a good description of where you'd use AOP. > I still prefer my concept/method of implementing it. Well, it's a contradiction that you agree with what I said and also think that aspects should produce new classes. If an aspect produces a new class, you still have to manually change all references from OriginalClassName to AOPClassName (and back when you no longer want it), which is again far more work than just changing the original class, so rather pointless. Why would you do more work with same benefits (i.e. new functionality) and how is that better? xs0 |
Copyright © 1999-2021 by the D Language Foundation