Re: Aspect Oriented Programming techniques
Hi,
christopher diggins wrote:
[color=blue][color=green]
> > If I call this technique a "compile-time Decorator pattern", would
> > it be really wrong?[/color]
>
> I do not know what you mean by that. I am aware of a Decorator pattern
> but a compile-time Decorator pattern is a new one.[/color]
Well, I may be wrong with this comparison, but consider this:
and in particular, the definition:
"Attach additional responsibilitie s to an object dynamically."
I understand that the merit of Decorator pattern is to provide non-invasive
extension to some operation, where "atomicity" of the original operation is
preserved. In other words, we "decorate" some operation with the means of
providing some pre- and post-operations and not by introducing anything in
the middle of the original operation, to which we may have no access. The
dynamic part means that polymorphism is used as a composition tool, allowing
us to change the decorations at runtime.
I found your technique to be similar and at the same time different in that:
- it composes operations with the means of providing pre- and
post-operations (or in other words on-entry and on-exit blocks); the
operations themselves are still black-box entities
- it does it at compile-time, meaning that once the composition is specified
and compiled, it cannot be later changed.
This is why I called it a compile-time Decorator.
[color=blue][color=green]
> > If not (ie. if there is some merit in stating that this is *just* a
> > Decorator pattern implemented staticly with the help of[/color]
> preprocessor), > then: what is reason to name it Aspect-Oriented[/color]
Programming?[color=blue]
>
> Because it allows the separation and isolation of cross cutting
> concerns in a reusable manner.[/color]
As do other techniques, where nobody bothered to put them into the now
trendy AOP bandwagon.
Consider the policy-based class design. I found it to be much more powerful
and expressive, but never seen it directly called AOP.
But see below.
[color=blue][color=green]
> > Note also that your technique uses more "wrapping" than "interleavi ng"
> > (that's why I tend to call it Decorator, not AOP) when composing >[/color]
> complete components.
>
> AFAICT it interleaves with existing code just as well as AspectJ or
> AspectC++ does. Do you see examples which contradicts this?[/color]
No, there is no need for contradiction.
The wrapping means that the composition of different "aspects" looks like
onion ("ogres are like onions" ;) ):
logging(on-entry)
synchro(on-entry)
memory_mgmt(on-entry)
...
operation
...
memory_mgmt(on-exit)
synchro(on-exit)
loggin(on-exit)
The "preventive " aspect still falls into this, as having only the on-entry
part.
This is wrapping. The interleaving, as I understand, it may look like this:
logging(part1)
synchro(part1)
...
logging(part2)
memory_mgmt(par t1)
synchro(part2)
operation(part1 )
memory_mgmt(par t2)
operation(part1 )
synchro(part3)
...
logging(part3)
memory_mgmt(par t3)
loggin(part4)
See? The composition of different aspects leads to some code transformations
and building onion-like structures is only one, probably the simplest
possible transformation. In general, the transformations required to compose
different aspects can be arbitrary.
It may be possible to decompose the code into pieces in a way that will lead
to onion-like structures (where everything is based on on-entry and on-exit
blocks), but such decomposition of the main program logic would be
problematic in the sense that it would be needed *only* to bend to this
particular composition technique and may spoil the initial design.
Moreover, code can be transoformed even to the extent that cannot be
expressed as moving around complete statements.
Consider, for example, that your application prints some output and one of
the *aspects* of your design is the case (lowercase/uppercase/mixed) of this
output or whether the numbers are roman or arabic, or how strings should be
compared, considering the character encoding and other localization-related
stuff used.
Another aspect may be the optimisation mode. The program can minimize DB
accesses (with the use of local caching structures) or minimize the memory
usage. This acpect may have influence on many points in the program,
possibly scattered across the whole project. Moreover, this aspect may be
bound at compile-time or at run-time and the binding time also influences
the way it is implemented.
Some aspects may not be even expressible in terms of classes or functions,
for example the compile-time optimization. The program may be optimized for
speed or for size and I may wish to bind this aspect differently for
different parts of the project.
All these exaples mean that wrapping calls with the means of on-entry and
on-exit blocks is only a single tool, probably the simplest one. The problem
is that other tools are not necessarily in the same box.
[color=blue][color=green]
> > I think that AOP calls for some new approach to development,[/color]
> including > completely new language features, or maybe a separate
> language in > itself.
>
> What do you base that statement on?[/color]
[...][color=blue]
> I would like to see you back up the statement about insufficiency for[/color]
AOP.
I base it on the above examples.
At the moment, I have to use different techniques for aspect specification
and different techniques for composition. I can use compile-time wrapping,
policy-based class design, design patterns, message filters and
interceptors, compiler switches, makefiles, and everything else, but they
are all very loosely coupled, if coupled at all. There is no clear relation
between, for example, the makefile settings, the Strategy pattern in the
middle of the project and the locale facet imbued in the single stream
object, even if they all serve the same aspect.
What I want is the possibility to specify and manage aspects in the
consistent way, no matter what technique is later used to implement and
compose aspects (or whether this is done automatically). Whether it is some
meta-language, language extension or sophisticated GUI tool, it needs to be
consistent.
The loosely coupled bunch of techniques and approaches is only an indication
that the community matures to further research, but there is still nothing
that I would call a *paradigm*.
[color=blue][color=green]
> > These are just my thoughts and I will be more than happy to learn
> > others' opinions.[/color][/color]
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Hi,
christopher diggins wrote:
[color=blue][color=green]
> > If I call this technique a "compile-time Decorator pattern", would
> > it be really wrong?[/color]
>
> I do not know what you mean by that. I am aware of a Decorator pattern
> but a compile-time Decorator pattern is a new one.[/color]
Well, I may be wrong with this comparison, but consider this:
and in particular, the definition:
"Attach additional responsibilitie s to an object dynamically."
I understand that the merit of Decorator pattern is to provide non-invasive
extension to some operation, where "atomicity" of the original operation is
preserved. In other words, we "decorate" some operation with the means of
providing some pre- and post-operations and not by introducing anything in
the middle of the original operation, to which we may have no access. The
dynamic part means that polymorphism is used as a composition tool, allowing
us to change the decorations at runtime.
I found your technique to be similar and at the same time different in that:
- it composes operations with the means of providing pre- and
post-operations (or in other words on-entry and on-exit blocks); the
operations themselves are still black-box entities
- it does it at compile-time, meaning that once the composition is specified
and compiled, it cannot be later changed.
This is why I called it a compile-time Decorator.
[color=blue][color=green]
> > If not (ie. if there is some merit in stating that this is *just* a
> > Decorator pattern implemented staticly with the help of[/color]
> preprocessor), > then: what is reason to name it Aspect-Oriented[/color]
Programming?[color=blue]
>
> Because it allows the separation and isolation of cross cutting
> concerns in a reusable manner.[/color]
As do other techniques, where nobody bothered to put them into the now
trendy AOP bandwagon.
Consider the policy-based class design. I found it to be much more powerful
and expressive, but never seen it directly called AOP.
But see below.
[color=blue][color=green]
> > Note also that your technique uses more "wrapping" than "interleavi ng"
> > (that's why I tend to call it Decorator, not AOP) when composing >[/color]
> complete components.
>
> AFAICT it interleaves with existing code just as well as AspectJ or
> AspectC++ does. Do you see examples which contradicts this?[/color]
No, there is no need for contradiction.
The wrapping means that the composition of different "aspects" looks like
onion ("ogres are like onions" ;) ):
logging(on-entry)
synchro(on-entry)
memory_mgmt(on-entry)
...
operation
...
memory_mgmt(on-exit)
synchro(on-exit)
loggin(on-exit)
The "preventive " aspect still falls into this, as having only the on-entry
part.
This is wrapping. The interleaving, as I understand, it may look like this:
logging(part1)
synchro(part1)
...
logging(part2)
memory_mgmt(par t1)
synchro(part2)
operation(part1 )
memory_mgmt(par t2)
operation(part1 )
synchro(part3)
...
logging(part3)
memory_mgmt(par t3)
loggin(part4)
See? The composition of different aspects leads to some code transformations
and building onion-like structures is only one, probably the simplest
possible transformation. In general, the transformations required to compose
different aspects can be arbitrary.
It may be possible to decompose the code into pieces in a way that will lead
to onion-like structures (where everything is based on on-entry and on-exit
blocks), but such decomposition of the main program logic would be
problematic in the sense that it would be needed *only* to bend to this
particular composition technique and may spoil the initial design.
Moreover, code can be transoformed even to the extent that cannot be
expressed as moving around complete statements.
Consider, for example, that your application prints some output and one of
the *aspects* of your design is the case (lowercase/uppercase/mixed) of this
output or whether the numbers are roman or arabic, or how strings should be
compared, considering the character encoding and other localization-related
stuff used.
Another aspect may be the optimisation mode. The program can minimize DB
accesses (with the use of local caching structures) or minimize the memory
usage. This acpect may have influence on many points in the program,
possibly scattered across the whole project. Moreover, this aspect may be
bound at compile-time or at run-time and the binding time also influences
the way it is implemented.
Some aspects may not be even expressible in terms of classes or functions,
for example the compile-time optimization. The program may be optimized for
speed or for size and I may wish to bind this aspect differently for
different parts of the project.
All these exaples mean that wrapping calls with the means of on-entry and
on-exit blocks is only a single tool, probably the simplest one. The problem
is that other tools are not necessarily in the same box.
[color=blue][color=green]
> > I think that AOP calls for some new approach to development,[/color]
> including > completely new language features, or maybe a separate
> language in > itself.
>
> What do you base that statement on?[/color]
[...][color=blue]
> I would like to see you back up the statement about insufficiency for[/color]
AOP.
I base it on the above examples.
At the moment, I have to use different techniques for aspect specification
and different techniques for composition. I can use compile-time wrapping,
policy-based class design, design patterns, message filters and
interceptors, compiler switches, makefiles, and everything else, but they
are all very loosely coupled, if coupled at all. There is no clear relation
between, for example, the makefile settings, the Strategy pattern in the
middle of the project and the locale facet imbued in the single stream
object, even if they all serve the same aspect.
What I want is the possibility to specify and manage aspects in the
consistent way, no matter what technique is later used to implement and
compose aspects (or whether this is done automatically). Whether it is some
meta-language, language extension or sophisticated GUI tool, it needs to be
consistent.
The loosely coupled bunch of techniques and approaches is only an indication
that the community matures to further research, but there is still nothing
that I would call a *paradigm*.
[color=blue][color=green]
> > These are just my thoughts and I will be more than happy to learn
> > others' opinions.[/color][/color]
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Comment