[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-dev] Re: Outcomings or not-outcomings of the perobjects BOF

Matthew,

If I understand well your point is that with non-static inner aspects the original java class source code must be modified to add the inner aspect.
I agree with you in that it is better not to need access to the source code, but I'd like you to notice the following:
a) Static inner aspects are allowed in AspectJ but they need access to source code too.
b) In the example the only reason to create CleverPerson java class is to hold the state of the crosscuting concern. If you aren't going to add the aspect you don't need to create CleverPerson. The point is that the original java source code are Person and ComplexOperation and they are not modified at all. I consider CleverPerson as AspectJ source code and not part of the core code base of the application.
c) For LTW CleverPerson will be distributed in an aspect library JAR and Person and ComplexOperation in the code base JAR.
d) Sometimes we want the aspect to be as closer as possible to original source code. It is easier to understand the overall behaviour of the class.


Of course in other situations the java class that holds the state needed by the aspect is part of the code base and must not be modified.
I don't have clear if this kind of situations are common. I suspect in this cases perthis could work.
But if they are really common (or if you simply have one) it can be done in at least two ways with inner non-static aspects.


// Now CleverPerson is part of the code base and must not be modifier.
// Perhaps AspectJ developer has only .class not source code.

public class CleverPerson {

   public boolean enabled=false;
   public String message="Hey, ";
   private Person p;
   private ComplexOperation o;

public CleverPerson(Person p, ComplexOperation o) {...}
}


// Now the AspectJ library
public interface CleverPersonWithAspect { public void doMessage();


   public aspect Inner
   {
      public pointcut operationExecuted(String msg): execution(public
void ComplexOperation.operate(String)) && args(msg);

      after(String msg): operationExecuted(msg)
      {
            doMessage();
      }
   }
}

// This assumes that there are public accessors
// If not we can declare a privileged aspect (not a good idea I think)
public aspect Deploy
{
	// Since the aspect is non-static it must be inherited
	declare parents: CleverPerson implements CleverPersonWithAspect;

	public void CleverPerson.doMessage()
	{
          if(this.enabled)
                System.out.print(message+" "+this.getPerson().getName+" performs
                 "+this.getPerson().getId()+"<"+this.getMessage()+">");
   	}
}

Other ways of deploy the non static inner aspect could be:

public class CleverPersonWithAspect extends CleverPerson
{ public CleverPersonWithAspect(Person p, ComplexOperation o)
{
super(p,o);
}
public void doMessage()
{
if(this.enabled)
System.out.print(message+" "+this.getPerson().getName+" performs
"+this.getPerson().getId()+"<"+this.getMessage()+">");
}


   public aspect Inner
   {
      public pointcut operationExecuted(String msg): execution(public
void ComplexOperation.operate(String)) && args(msg);

      after(String msg): operationExecuted(msg)
      {
            doMessage();
      }
   }
}

public aspect Deploy
{
	pointcut newCalled(Person p, ComplexOperation o): call(public CleverPerson.new(Person, ComplexOperation))
	&& args(p,o) ;
	
	CleverPerson around(Person p, ComplexOperation o): newCalled(p, o)
	{
		return new CleverPersonWithAspect (p,o);
	}
}



Regards,
Enrique J. Amodeo Rubio
Matthew Webster wrote:



Enrique,

Although this is a nice idea it suffers from the problem of having to
modify source code. Sometimes when applying aspects refactoring is
necessary to produce the right set of join points but the resulting code
usually benefits from this activity independently of the use of AOP. Most
AOP can be applied without access to source code which is especially useful
when using LTW.

Matthew Webster
AOSD Project
Java Technology Centre, MP146
IBM Hursley Park, Winchester,  SO21 2JN, England
Telephone: +44 196 2816139 (external) 246139 (internal)
Email: Matthew Webster/UK/IBM @ IBMGB, matthew_webster@xxxxxxxxxx
http://w3.hursley.ibm.com/~websterm/

"Enrique J. Amodeo Rubio" <eamodeorubio@xxxxxxxxxxxxxx>@eclipse.org on
22/03/2005 11:59:32

Please respond to aspectj-dev@xxxxxxxxxxx

Sent by:    aspectj-dev-admin@xxxxxxxxxxx


To: aspectj-dev@xxxxxxxxxxx cc: Subject: Re: [aspectj-dev] Re: Outcomings or not-outcomings of the perobjects BOF


Hello, I've been following this thread with interest. I have read Eric's blog and Adrian's blog too. It's clear that in AspectJ it's difficult to associate an aspect with an arbitrary set of objects. Since I think this is an important feature that occurs in real life programming I think that some change should be made to the language. Since AspectJ is my favourite AOP language I have thinked in such a change. The idea is to allow non-static inner aspects in classes, so the aspect is associated with the enclosing class' instances. I'll illustrate how this make this feature possible with an example.

public class ComplexOperation
{
   public String getId();
   public void operate(String op) {...}
}

public class Person
{
   public String getName() {...}
}

public class CleverPerson
{
   public boolean enabled=false;
   public String message="Hey, ";
   private Person p;
   private ComplexOperation o;

   public CleverPerson(Person p, ComplexOperation o) {...}

   protected void doMessage()
   {
      if(this.enabled)
                System.out.print(message+" "+this.p.getName+" performs
"+this.o.getId()+"<"+msg+">");
   }

   protected aspect  Inner
   {
      public pointcut operationExecuted(String msg): execution(public
void ComplexOperation.operate(String)) && args(msg);

      after(String msg): operationExecuted(msg)
      {
            doMessage();
      }
   }
}

// Client code
Person p=new Person("John");
ComplexOperation op1=new ComplexOperation("Sum");
ComplexOperation op2=new ComplexOperation("Sum22");
CleverPerson cp=new CleverPerson(p, op1);
cp.message="Hello,";
cp.enabled=true;
op1.operate("2+2");

A non-static inner aspect instance is associated with each CleverPerson
instance. When a CleverPerson instance is GC then the inner aspect is GC
too. This avoids the need for extra map fields and methods to manage
mapping between objects instances and aspects instances.

I think the semantic of this change is easy to understand for most AOP
programmers and avoid complicating the per-clauses in the aspects. It's
very natural for OO programmers too. In fact I wondered why this can't
be done in AspectJ when I started to learn it. One of my early mistakes
learning AspectJ was to try this kind of constructs that I see very
natural.

Other possibility is to be able to instantiate aspects in the same way
objects are instantiated. In this way the above example could be simply
written as:

public aspect CleverPerson explicitinstantiation
{
   public boolean enabled=false;
   public String message="Hey, ";
   private Person p;
   private ComplexOperation o;

   public CleverPerson(Person p, ComplexOperation o) {...}

      after(String msg): execution(public void
ComplexOperation.operate(String)) && args(msg)
      {
            if(this.enabled)
                System.out.print(message+" "+this.p.getName+" performs
"+this.o.getId()+"<"+msg+">");
      }
}

And the client code could remain without changes. The aspect instance
should be GC as a regular object. I think this could cause more impact
in the language than the former version.

Eric's proposal of an explicit perthis is interesting but I see
confusing to have two versions of perthis. I don't undestand the exact
semantics of such construction.

I would like to know about your opinion about this kind of changes. I
can understand that it could involve major reengineering and be deferred
to later versions, but I'll like to know if there will be changes in
AspectJ to allow more complex aspect associations and how difficult they
are.

thanks for reading such large email,

Enrique J. Amodeo Rubio.

Ron Bodkin wrote:



I couldn't agree more.
-----Original Message-----
From: Nicholas Lesiecki <ndlesiecki@xxxxxxxxx>
Date: Thu, 17 Mar 2005 23:13:05
To:aspectj-dev@xxxxxxxxxxx
Subject: [aspectj-dev] Re: Outcomings or not-outcomings of the perobjects


BOF


After talking to the CeasarJ guys, I've determined that their model of
aspect instantiation and binding represents a fertile field ideas for
Aspectj to harvest from and enables several interesting use cases
(including, possibly yours Eric) cleanly. That being said, I think that
fully harvesting their ideas will require enough engineering, not to
say conceptual effort, that I would much rather address the issue in
the AspectJ6 timeframe. As a practitioner, my top priorities are speed,
stability, and Java5.


Standard disclaimer: apologies for the terseness of this email, I'm typing with a broken wrist.

Nicholas Lesiecki
Software Craftsman, specializing in J2EE,
Agile Methods, and aspect-oriented programming
m: 520 591-1849

Books:
* Mastering AspectJ: http://tinyurl.com/66vf
* Java Tools for Extreme Programming: http://tinyurl.com/66vt

Articles on AspectJ:
* http://tinyurl.com/66vu and http://tinyurl.com/66vv
On Mar 17, 2005, at 9:32 AM, Eric Bodden wrote:





First of all thank you all for attending. I think we had a fruitful
discussion. As those of you who attended will remember in the end we
were all of the *false* opinion that what I proposed - associating a
vector of objects with an aspect instance - could be simulated by a
container object holding the actual objects in questions.

So you could instantiate say an Equality by saying "new
Equality(bit1,bit2)" which would be picked up by an aspect that binds
its "perthis" instance to this equality object. Well, this
instantiation model works. The problem however arises as soon as you
try to actually do something useful with the associated objects:

You would need something like...

after(Bit bit): call(Bit.set()) && target(bit) {
 //iterate over all Equality objects and pick out those holding "bit"
 //for each such "equality" get the aspect with aspectOf(equality)
to retrieve the correct state
 //transform state somehow
}

As you see, this is all not really useful, since there is any no
benefit left from the perobjects instantiation at all. One could also
use a plain singleton aspect and a hashmap instead, which would come
down to...

after(Bit bit): call(Bit.set()) && target(bit) {
 //iterate over all Equality objects and pick out those holding "bit"
 //for each such "equality" get the state associated with equality
in the hashmap
 //transform state somehow
}

So in the end it comes down to using explicitly hashmaps and so forth
again.

There are special cases where you can get around it and this is
actually the case when you have 1:n relationships. This is e.g. the
case where you have the observer pattern: One observable holds a list
of n observers. Here "perthis" etc. suffice. As soon as you have n:m
or even n:m:o relationships and so forth, this won't help you at all.
You *have to* use hashmaps. Even ITDs won't work with n:m since you
would have n (respectively m) "overlapping" ITDs on one type.

So in the end we are back to where we started: There is no appropriate
language support for those kind of things. I do understand that there
might not be a lot obvious use cases as this. However i think it could
still be a powerful addition to have kind of this technology, cause it
can be used quite well to model relationships between roles:

Whenever certain objects stand in relationships you can just
encapsulate the whole behaviour of this relationship in one simple
easy-to-read aspect. "Equality" is just one small example. It could be
used to model all kinds of relations, for which I can imagine also a
lot of business use cases: Imagine business rules of any kind. Many of
them actually model certain relations between objects (and not
Classes!).

Example: Imagine a business unit with a project manager, some coders,
a software architet and a QA guy. And imagine an IDE that would
automatically support workflow. You could put all those people
"objects" into *one* explicit relation and then have all appropriate
things just done by the aspect: Whenever a coder finished a modulem
the QA guy is notified. Whenever a new test has been passed, the
manager is notfied, whenever requirements change, the architect is
notified and so forth...

Using current AJ tehcnology you would need various perthis aspects and
certainly hashmaps and/or ITDs to model this. Using some association
facility you could explicitly model this by just saying something
like:

new CodingTeam(aManager, new Coder[]{coder1,coder2}, aArchitect,
aQAGuy);

That would be about it.

Any comments would be highly appreciated.

Eric




_______________________________________________
aspectj-dev mailing list
aspectj-dev@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-dev


Sent wirelessly via BlackBerry from T-Mobile. _______________________________________________ aspectj-dev mailing list aspectj-dev@xxxxxxxxxxx http://dev.eclipse.org/mailman/listinfo/aspectj-dev







_______________________________________________ aspectj-dev mailing list aspectj-dev@xxxxxxxxxxx http://dev.eclipse.org/mailman/listinfo/aspectj-dev


_______________________________________________ aspectj-dev mailing list aspectj-dev@xxxxxxxxxxx http://dev.eclipse.org/mailman/listinfo/aspectj-dev